Using Virtual pixel Edge will solve things to some degree. but using any form of virtual-pixel, or even faking virtual pixels by adding a border, is not actually solving the problem.
Remember the problem is to make distort emulate resize, and resize filters completely ignores virtual pixels. they just don't use them in the calculation.
Using a VP of transparent makes distort ignore VP contributions for Color channels, which is fine if you are going to ignore (turn off) alpha at the end. However as transparency channls is still effected you can't just turn off alpha channel at the end (original image has some transparency.
You can use VP edge, but then edge pixels get replicated outward from the image, making edge pixels influence the filtered result (assuming it is just for alpha). And an even stronger effect for corners.
VP mirror can work better, but the filter will still not ignore alpha.
HOLD THE PRESS...
When a VP transparency is used. Color channel results are not VP effected (as VP pixels are transparent)!
Solution....
- clone image, extract alpha as a greyscale image, with a opaque alpha channel.
- Now you have two images, the original (with its own alpha), and the alpha in color channels!
- Do the resize distort on both and turn off alpha on both.
- Now merge the second alpha channel image back into the original image (compose CopyOpacity is good for this).
As the second 'alpha mask' image was resized using only color channels it will also be not be VP effected! Just like the color channels in the original image (though the first image has alpha edge effects)
test image, a half circle on edge.
Code: Select all
convert -size 70x70 xc:none -fill red -draw 'circle 35,65 15,55' hcircle.png
Try resizing this image with a very 'large' filter, to see how the filter effects results near edge. A very blurry gaussian should be good for this test!
Resize (with large vastly over blurry gaussian)
Code: Select all
convert hcircle.png -filter gaussian -define filter:blur=10 -resize 100x100 hcircle_resize.png
Note that this is what we want to achieve in distort, with gaussian resize filter we should get a almost perfect match.
Now try this with distort and VP transparency (without the final alpha turn off).
Code: Select all
convert hcircle.png -alpha on -virtual-pixel transparent \
-filter gaussian -define filter:blur=10 \
+distort Affine '0,0 0,0 70,0 100,0 0,70 0,100' \
-crop 100x100+0+0 +repage hcircle_distort_vp.png
Note the effect of the VP transparency on the edge. The color values are right, just alpha is not. And it is only an edge effect, though in this case the effect is up to 20 pixels inward from the edge. Actually it is outward too. but IM distort only provides a 1-2 pixel buffer for the outward effect, and we use crop to remove it.
Now lets try separating alpha and distorting that channel in the color channels to remove VP effects on it. Remember -distort can distort a list of images all in the same way!)
Code: Select all
convert hcircle.png -alpha set -virtual-pixel transparent \
\( +clone -alpha extract -alpha opaque \) \
-filter gaussian -define filter:blur=10 \
+distort Affine '0,0 0,0 70,0 100,0 0,70 0,100' \
-crop 100x100+0+0 +repage \
-alpha off -compose CopyOpacity -composite \
hcircle_distort_alpha.png
A practically perfect distort-resize with an image containing alpha and all VP effect ignored!
Yes yes Yes!!!
ASIDE: the distort use of gaussian is slightly different to the resize version. The Bluring is slightly larger as a sqrt(2) 'blur' factor was internally included as per suggestions from some research articles on the use of 2D filters. With this example I think that blur factor difference may be a mistake, and probably should be removed. It may also be that my implementation was not quite right.
NOTE: Gaussian is a 2-pass separable function, as such as a filter it should produce the same results if used as a 2 pass orthogonal filter (resize), or as a 1 pass cylindrical filter (distort).
UPDATE: the blur factor is now the same for orthogonal or cylindrical filters