Hello,

If you compute the errors, that is:

a*float(256/255) - (a + (a>>7))

and

a*float(256/255) - (a + 1)

you'll see that the former is a better choice; the maximum error is
smaller (0.5 instead of 1.0)

The later is also incorrect per the OpenGL blending specification
because it doesn't map "0" to "0" (you're lucky in that specific
example, but if you were to dither the result, it wouldn't work).

Additionally, doing the actual computation in integer:

(a * 256)/255

will give you the same result than with the equation used in skia.

Mathias


On Feb 26, 11:04 am, Eric <[email protected]> wrote:
> When using some of the PorterDuff modes in the Android SDK incorrect
> alpha values are produced. For example the following:
>
> Bitmap bitmap = Bitmap.createBitmap(100, 100,
> Bitmap.Config.ARGB_8888);
> bitmap.eraseColor(0xff000000); // Black with alpha 255
> Canvas canvas = new Canvas(bitmap);
> canvas.drawColor(0x80000000, PorterDuff.Mode.SRC_OVER);  // Black with
> alpha 128
>
> results in 0xfe000000 so an alpha value of 254 instead of 255
>
> After some digging in the source code I traced it back to incorrect
> use of SkAlpha255To256 defined in
>
> platform/external/skia.git/include/core/SkColorPriv.h
>
> 34 static inline unsigned SkAlpha255To256(U8CPU alpha) {
> 35     SkASSERT(SkToU8(alpha) == alpha);
> 36     return alpha + (alpha >> 7);
> 37 }
>
> It is frequently used in the PorterDuff blending functions, below is
> SRC_OVER from:
>
> platform/external/skia.git/src/core/SkXfermode.cpp
>
> 347 //  kSrcOver_Mode,  //!< [Sa + (1 - Sa)*Da, Sc + (1 - Sa)*Dc]
> 348 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
> 349     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 -
> SkGetPackedA32(src)));
> 350 }
>
> Running the above numbers for alpha it produces 128 + (255 * 127) >> 8
> = 254. Doing it without the shift optimization returns 128 + (255 *
> 127) / 255 = 255.
>
> Fro some of these functions (not all) it would be better to use a
> SkAlpha255To256 defined as
>
> static inline unsigned SkAlpha255To256(U8CPU alpha) {
>      SkASSERT(SkToU8(alpha) == alpha);
>      return alpha + 1;
>
> }
>
> which is not 100% accurate either but you can still use the shift
> trick and it does produce correct result when alpha is 0 and when
> alpha is 255. Any thoughts?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"android-framework" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/android-framework?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to