Intro (semi fictional)

I'm the solo developer of a game, I'm already struggling with character design as is. Hence I've thought of a smart solution, I'll just use images for regular monsters, outline them a bit and suddenly they are boss monsters! That will save me from thinking up new bosses yay.
However, I have approximately 100 monster designs already and I wouldn't like duplicating them all and manually drawing an outline to the images...


Given a file name (of a PNG file) as input, you should write a program/function which will draw an outline around every non-transparent pixel. The program/function should save the output file to a new file called a.png

What does outlining mean

Outlining is the process of adding non-transparent pixels in the place of transparent pixels, around pixels which were non-transparent already. Any transparent pixel has an opacity of exactly 0%, anything else is defined as non-transparent. Any pixel which will be outlined will have an opacity of 100%, aka the alpha channel of that pixel will be 255.


Your program/function should take 3 variables as input. Feel free to provide these as function parameters, read them from stdin or any other method which suits you best.

The first variable is the file name, which is always a PNG file.
The second variable is the outline colour, which is a round integer, you can also take the colour from 3 separate r,g,b byte values.
The third variable is the outline width, also an integer.

Outline width

The width of the outline equals the maximum distance any transparent pixel should have to a non-transparent pixel in order to be outlined. The distance is calculated using the Manhattan distance between two points.
If the input image has only 1 non-transparent pixel, at [0,0] and the outline width is 2, then the following pixels will be coloured: [0,1] [0,-1] [1,0] [-1,0] [1,1] [-1,-1] [1,-1] [-1,1] [2,0] [-2,0] [0,2] [0,-2], for these have a manhattan distance of 2 or less from the coloured pixel

Test cases

The following test cases are scaled up 7 times for visibility, so every block of 7 pixels should be treated as a single pixel

These are the input images used for the test cases:




enter image description here


enter image description here

These are the actual test cases:

input1.png, 0xFF0000, 0

enter image description here

input1.png, 0xFF0000, 1

enter image description here

input1.png, 0xFF0000, 2

enter image description here

input1.png, 0xFF0000, 3

enter image description here

input1.png, 0xFF0000, 10

enter image description here

input2.png, 0xFF0000, 2

enter image description here

input3.png, 0x000000, 2

enter image description here

Click here for the full Imgur album.

This is , standard loopholes apply! Feel free to submit your own images as test cases, since these pixel images aren't very creative ;)

  • \$\begingroup\$ Could the color also be taken as three separate r,g,b values? \$\endgroup\$
    – flawr
    May 5, 2016 at 12:26
  • \$\begingroup\$ @flawr also fine with me \$\endgroup\$ May 5, 2016 at 12:42
  • \$\begingroup\$ I assume you enlarged the images in the challenge description. Can you also post the ones with the original size? \$\endgroup\$
    – flawr
    May 5, 2016 at 12:46
  • \$\begingroup\$ The PNG image requirement ruins the challenge. \$\endgroup\$
    – 12Me21
    Mar 9, 2018 at 18:13

2 Answers 2


Matlab, 202 bytes

function f(i,r,g,b,n);[i,~,a]=imread(i);[x,y]=ndgrid(abs(-n:n));d=permute([r,g,b,255]',3:-1:1);I=cat(3,i,a);J=uint8(bsxfun(@times,~~convn(a,x+y<=n,'s')&~a,d))+I;imwrite(J(:,:,1:3),'a.png','Al',J(:,:,4))

As always:

Convolution is the key to success.

The function can be called like so:

f('my_image.png', red_int, green_int, blue_int, dist)


function f(i,r,g,b,n)
[i,~,a]=imread(i);                   %read image and alpha channel
[x,y]=ndgrid(abs(-n:n));             %computations for convolution kernel
d=permute([r,g,b,255]',3:-1:1);      %create 'pixel' that will be inserted
I=cat(3,i,a);                        %concatenate image and alpha channel
J=uint8(bsxfun(@times,~~convn(a,x+y<=n,'s')&~a,d))+I; %find border via convolution of kernel, insert pixels and recombine with original
imwrite(J(:,:,1:3),'a.png','Al',J(:,:,4)) %write file

PHP, 559 chars


$img = ImageCreateFromPng($p);
$width = imagesx($img);
$height = imagesy($img);
$new = ImageCreateFromPng($p);
$inv = '2130706432';
        $color = ImageColorAt($img, $w, $h);
        if($color != $inv)
                    if(abs($h - $y) + abs($w - $x) <= intval($argv[3]))
                        $_color = ImageColorAt($img, $x, $y);
                        if($_color == $inv)
                            imagesetpixel($new, $x, $y, hexdec($argv[2]));
imagepng($new, str_replace(".png", ".border.png", $p));

function alphaFix(&$img)
    $background = imagecolorallocate($img, 0, 0, 0);
    imagecolortransparent($img, $background);
    imagealphablending($img, false);
    imagesavealpha($img, true);


<?error_reporting(0);$j=$argv[1];$g=ImageCreateFromPng($j);$e=imagesx($g);$b=imagesy($g);$l=ImageCreateFromPng($j);a($g);a($l);$f='2130706432';for($m=0;$m<$e;$m++)for($l=0;$l<$b;$l++){$d=ImageColorAt($g,$m,$l);if($d!=$f)for($k=0;$k<$e;$k++)for($i=0;$i<$b;$i++){if(abs($l-$i)+abs($m-$k)<=intval($argv[3])){$c=ImageColorAt($g,$k,$i);if($c==$f)imagesetpixel($l,$k,$i,hexdec($argv[2]));}}}imagepng($l,str_replace(".png",".border.png",$j));function a(&$g){$a=imagecolorallocate($g,0,0,0);imagecolortransparent($g,$a);imagealphablending($g,0);imagesavealpha($g,1);}


php outline.php "image1.png" 0xFF0000 1
                     |           |    |
                     |           |    *- Border Size
                     |           *------ Color HEX
                     *------------------ Image Name


I made an Imgur album, because I slightly changed the images and there you can also see the arguments I passed my script.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.