Reputation: 1322
In order to prevent artifacts when scaling sprites or displaying them on not full pixels in my graphics engine of choice I have a need to go through all my sprites and add an edge to each one of them. The edge needs to be of the color of the neighboring pixels, just like this:
The left image is the original image and the right one is the expected result.
Is it possible to achieve this effect in ImageMagick? In other words, can you expand the image in all four directions by one pixel, copying the edge pixels into the newly added border?
Upvotes: 3
Views: 2014
Reputation: 491
Using Virtual Pixels:
convert -resize "%[fx:w+4]x%[fx:h+4]" "./input.png" -set option:distort:viewport "%[fx:w+4]x%[fx:h+4]"-2-2 -virtual-pixel Edge -distort SRT 0 +repage ./output.png
input.png
is the input image. output.png
will have it's border extended by 2 pixels with the colors of the original edge. The image is resized by adding twice the extended width. The viewport offset is set to extended width.
See this page for more information.
Upvotes: 0
Reputation: 207345
I think the easiest way to tackle this is to resize the original image to be 2 pixels taller and 2 pixels wider than the original, and then to avoid distortions in the interior pixels, composite the unchanged original picture back on top in the centre.
So, to get the dimensions of the output image, by adding 2 to width and height,
geom=$(identify -format "%[fx:w+2]x%[fx:h+2]" sprite.png)
that gives something like
34x34
if the original image is 32x32.
Then I resize the image to this new size to fill the border pixels and composite the unchanged original back on top
convert sprite.png -resize $geom -gravity center sprite.png -composite out.png
Upvotes: 1
Reputation: 90193
First, you should be aware about the following basic image operations, which will serve as building blocks to the full command:
image.ext[NxM+x+y]
will cut out an NxM
pixels-sized area from image.ext that is offset by +x
pixels to the right and +y
pixels to the bottom, calculated from the top left corner.+append
appends two (or more) images horizontally.-append
appends two (or more) images vertically.image.ext[1x+0+0]
cuts off the left-most column of pixels in an image.-flop
will mirror an image from left to right.-flip
will mirror an image from top to bottom.image.ext[x1+0+0]
cuts out the top-most row of pixels in an image.image.ext[1x+0+0]
cuts out the left-most column of pixels in an image.-crop NxM+x+y
does the same as 1.
.mpr:ABC
will write an image into a Magick Persistent Registry, using the label ABC. From an MPR, which resides in a special memory location, ImageMagick can retrieve a copy of the image simply by invoking the label name.-delete 0
will delete the image with index 0 from the current image sequence.+write
will write the image sequence under the name given.+repage
normalizes the image canvas again.Now you can combine 5.
with 8.
to cut out the right-most row of pixels:
-flop image.ext[1x+0+0]
You can also combine 6.
with 7.
to cut out the bottom-most column of pixels:
-flip image.ext[x1+0+0]
Now combine these effects with the parentheses syntax \( ... \)
for side-processing of images for the complete command:
convert image.png \
-respect-parentheses \
+write mpr:ABC \
-delete 0 \
\( mpr:ABC[1x+0+0] \) \
\( mpr:ABC \) \
\( mpr:ABC -flop -crop 1x+0+0 \) \
+append +repage \
+write mpr:XYZ \
-delete 0 \
\( mpr:XYZ[x1+0+0] \) \
\( mpr:XYZ \) \
\( mpr:XYZ -flip -crop x1+0+0 \) \
-append +repage \
extended-edges.png
Applying this to the builtin rose:
image:
convert rose: \
-respect-parentheses \
+write mpr:ABC \
-delete 0 \
\( mpr:ABC[1x+0+0] \) \
\( mpr:ABC \) \
\( mpr:ABC -flop -crop 1x+0+0 \) \
+append +repage \
+write mpr:XYZ \
-delete 0 \
\( mpr:XYZ[x1+0+0] \) \
\( mpr:XYZ \) \
\( mpr:XYZ -flip -crop x1+0+0 \) \
-append +repage \
extend.png
identify rose: extend.png
rose:=>ROSE PPM 70x46 70x46+0+0 8-bit sRGB 9.67KB 0.000u 0:00.000
extend.png[1] PNG 72x48 72x48+0+0 8-bit sRGB 7.11KB 0.000u 0:00.000
Top-most row:
convert extend.png[x1+0+0] txt:- | md5sum
12b639cd1606559633ee23a062ae42a6 -
Second row from top:
convert extend.png[x1+0+1] txt:- | md5sum
12b639cd1606559633ee23a062ae42a6 -
Third row from top:
convert extend.png[x1+0+2] txt:- | md5sum
88fc6f9bac3f8ab4cbf2374fbef6fcf0 -
Left-most column:
convert extend.png[1x+0+0] txt:- | md5sum
4d2223b74901f9ce1fb4456dacb4315c -
Second column from left:
convert extend.png[1x+1+0] txt:- | md5sum
4d2223b74901f9ce1fb4456dacb4315c -
Third column from left:
convert extend.png[1x+2+0] txt:- | md5sum
07794b4423f5b6515142d15a5c652743 -
I'm not showing how to check if two bottom-most rows and two right-most columns are also identical...
There is also a way to achieve the same effect by using the -virtual-pixel edge
operation, but it is more difficult to understand...
Upvotes: 4