Reputation: 935
I have an image with known dimensions, let's say 8x8. I am needing to know definitively if there are any non-transparent pixels around the outer edge pixels of the image using MiniMagick. I'd love to know how to do this in ImageMagick as well, if that's possible (for the sake of my own understanding), but I really only need this in MiniMagick for now.
If anyone even has half-answers, feel free to throw something at this issue. I'm willing to play around with concepts as well. Thanks!
Upvotes: 1
Views: 362
Reputation: 207465
I would approach it like this. Fill the inner, non-edge pixels with a fully transparent nothingness - a hole, if you like. Then any opacity remaining in the image must be as a result of some opacity in the edge pixels. So if we overlay the newly-created image with a hole on top of any background and that results in a change to the background, we can deduce there must be non-transparent pixels in the new image, and therefore in the edges of the new image as we already made sure there were no non-transparent pixels in the middle. It sounds harder than it is!
#!/bin/bash
# First get dimensions of inner "hole", it's the width minus 2 and height minus 2
# so for a 16x16 image, it will be 14x14
inner=$(convert input.png -format "%[fx:w-2]x%[fx:h-2]" info:)
# Now punch a fully transparent hole in the input image
convert input.png \
-size $inner xc:none -alpha set -geometry +1+1 \
-compose copy -composite tmp.png
input.png
tmp.png
So, now we overlay the image with a hole on top of a white background, and then compare the result with a plain white image, and count how many pixels differ.
convert -size 16x16 xc:white tmp.png -composite \
xc:white -metric AE -compare -format "%[distortion]" info:
60
And there are 60 => 16 across the top, 16 across the bottom and 14 down each vertical edge. If we repeat the exercise with a fully transparent original image, the answer will be zero. So the test you need is whether the error metric (number of differing pixels) is non-zero.
Actually, in the shell and as your images are small, you would probably just convert the image to text and let awk
find the edge pixels, like this:
# Create opaque image
convert -size 16x16 xc:red PNG32:input.png
# Find pixels in row 0, row 15, col 0, col 15 where transparency (last digit before closing paren) is non-zero
convert input.png txt: | awk '/,0:|,15:|^0,|^15,/ && !/,0)/'
0,0: (255,0,0,1) #FF0000 red
1,0: (255,0,0,1) #FF0000 red
2,0: (255,0,0,1) #FF0000 red
3,0: (255,0,0,1) #FF0000 red
4,0: (255,0,0,1) #FF0000 red
5,0: (255,0,0,1) #FF0000 red
6,0: (255,0,0,1) #FF0000 red
7,0: (255,0,0,1) #FF0000 red
8,0: (255,0,0,1) #FF0000 red
9,0: (255,0,0,1) #FF0000 red
10,0: (255,0,0,1) #FF0000 red
11,0: (255,0,0,1) #FF0000 red
12,0: (255,0,0,1) #FF0000 red
13,0: (255,0,0,1) #FF0000 red
14,0: (255,0,0,1) #FF0000 red
15,0: (255,0,0,1) #FF0000 red
0,1: (255,0,0,1) #FF0000 red
15,1: (255,0,0,1) #FF0000 red
0,2: (255,0,0,1) #FF0000 red
15,2: (255,0,0,1) #FF0000 red
0,3: (255,0,0,1) #FF0000 red
15,3: (255,0,0,1) #FF0000 red
0,4: (255,0,0,1) #FF0000 red
15,4: (255,0,0,1) #FF0000 red
0,5: (255,0,0,1) #FF0000 red
15,5: (255,0,0,1) #FF0000 red
0,6: (255,0,0,1) #FF0000 red
15,6: (255,0,0,1) #FF0000 red
0,7: (255,0,0,1) #FF0000 red
15,7: (255,0,0,1) #FF0000 red
0,8: (255,0,0,1) #FF0000 red
15,8: (255,0,0,1) #FF0000 red
0,9: (255,0,0,1) #FF0000 red
15,9: (255,0,0,1) #FF0000 red
0,10: (255,0,0,1) #FF0000 red
15,10: (255,0,0,1) #FF0000 red
0,11: (255,0,0,1) #FF0000 red
15,11: (255,0,0,1) #FF0000 red
0,12: (255,0,0,1) #FF0000 red
15,12: (255,0,0,1) #FF0000 red
0,13: (255,0,0,1) #FF0000 red
15,13: (255,0,0,1) #FF0000 red
0,14: (255,0,0,1) #FF0000 red
15,14: (255,0,0,1) #FF0000 red
0,15: (255,0,0,1) #FF0000 red
1,15: (255,0,0,1) #FF0000 red
2,15: (255,0,0,1) #FF0000 red
3,15: (255,0,0,1) #FF0000 red
4,15: (255,0,0,1) #FF0000 red
5,15: (255,0,0,1) #FF0000 red
6,15: (255,0,0,1) #FF0000 red
7,15: (255,0,0,1) #FF0000 red
8,15: (255,0,0,1) #FF0000 red
9,15: (255,0,0,1) #FF0000 red
10,15: (255,0,0,1) #FF0000 red
11,15: (255,0,0,1) #FF0000 red
12,15: (255,0,0,1) #FF0000 red
13,15: (255,0,0,1) #FF0000 red
14,15: (255,0,0,1) #FF0000 red
15,15: (255,0,0,1) #FF0000 red
# Now create fully transparent image
convert -size 16x16 xc:none PNG32:input.png
# Find any non-opaque pixels
convert input.png txt: | awk '/,0:|,15:|^0,|^15,/ && !/,0)/'
# None
If you don't like hard-coding the 15
s into awk
like I have done, you could of course, pick up the width and height from the first line of the output of convert
where it appears like this:
# ImageMagick pixel enumeration: 16,16,255,srgba
and make a search pattern with the last row/col along these lines - just ask if you don't know how to do it:
awk 'NR==1 {... pattern="0,|,0:..." } # First line, get dimensions, make pattern
$0 ~ pattern && !/,0)/ {print "..."; exit}' # Find non-transparent edge pixels
Upvotes: 1