On 10/11/16 12:49 PM, Jim Graham wrote:
Right now I tried to fix overlapping, which produce visible artifacts and were
considered as a bugs. The next issue
which I would like to fix is a overlapping of drawImage().
Yes, that bears investigation...
I looked into it and the issue is basically floating point bit error.
Basically, in the test program we don't use a ScaledBlit because we don't have one defined for the combination of
(IntArgb, SrcOver, IntArgb), since our ScaledBlit implementations are all for opaque images. The loop macros can't even
create a non-opaque ScaledBlit without a bit of work.
So, we end up in TransformHelper where we perform the blit by doing an inverse transform on the graphics transform and
then use that to map back from destination pixels to the source pixels.
The issue here is that with a scale of 1.5, the forward transform is a nice IEEE-floating-point spec compatible bit
pattern, but inverting it gives a scale of 2/3s which doesn't have an exact IEEE representation. The result is that it
marches through the image and the very last edge of that image maps to 10.5 which is an exact center of the pixel. If
the math were perfect then we'd back-transform that coordinate into the source image and get 7.0 and that would be "past
the right edge of the image" and we'd bail at that point. But, we back-transform it and get 6.99999 and we think "OK,
this pixel just squeaks by and gets one last sample of the image before we fall off the edge of the image".
But, this should not happen with 1:1 image copies. And it shouldn't happen when we have a ScaledBlit function since
that uses more exact math without inverting the scale, but I haven't written a test case to verify that. And, it
shouldn't happen with integer scales and scales where we don't have a situation of an image mapping to exactly
(pixel+0.5). But, I don't think we can improve the pixel accuracy of our inverse transforms to handle this exact case
without a lot of work...