Re: [AD] premultiplied alpha

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Sun, 2010-10-31 at 12:19 +1100, Peter Wang wrote:
> On 2010-10-29, Elias Pschernig <elias.pschernig@xxxxxxxxxx> wrote:
> > > 
> > I think the flag for bitmap loading is important, otherwise you couldn't
> > use pre-multiplied alpha at all.
> 
> Isn't it just a case of multiplying in the alpha after loading?

Yes. What you would do is go through every single bitmap you loaded,
then loop through all pixels and multiply in the alpha.

> Granted, it's slower.

Yes. Would defeat our automatic uploading of loaded bitmaps into
textures.

> 
> > As for making it the default I don't know. Maybe it's best to change the
> > default blend mode from ALPHA/INVERSE_ALPHA to ONE/ZERO. That way we
> > have no default any longer, everyone needs to call al_set_blender at
> > least once in each A5 program and decide the used blending for
> > themselves.
> 
> I'm fine with leaving it as it is.
> 

Me too. With the flag you can use pre-multiplied alpha just as easy as
interpolated alpha, shouldn't matter much which one we use by default.
Attached is a possible patch, will add documentation and unit test when
committing.

-- 
Elias Pschernig <elias.pschernig@xxxxxxxxxx>
diff --git a/addons/image/bmp.c b/addons/image/bmp.c
index dd9da58..f1d4ccb 100644
--- a/addons/image/bmp.c
+++ b/addons/image/bmp.c
@@ -340,6 +340,7 @@ static void read_32bit_line(int length, ALLEGRO_FILE *f, unsigned char *data)
    int i;
    unsigned char c[4];
    unsigned char r, g, b, a;
+   bool premul = al_get_new_bitmap_flags() & ALLEGRO_PREMULTIPLY_ALPHA;
 
    for (i = 0; i < length; i++) {
       al_fread(f, c, 4);
@@ -347,6 +348,12 @@ static void read_32bit_line(int length, ALLEGRO_FILE *f, unsigned char *data)
       g = c[1];
       b = c[0];
       a = c[3];
+      
+      if (premul) {
+         r = r * a / 255;
+         g = g * a / 255;
+         b = b * a / 255;
+      }
 
       data[0] = r;
       data[1] = g;
diff --git a/addons/image/png.c b/addons/image/png.c
index 38a3e61..e292b0d 100644
--- a/addons/image/png.c
+++ b/addons/image/png.c
@@ -100,6 +100,7 @@ static ALLEGRO_BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr)
    ALLEGRO_LOCKED_REGION *lock;
    unsigned char *buf;
    unsigned char *rgba;
+   bool premul = al_get_new_bitmap_flags() & ALLEGRO_PREMULTIPLY_ALPHA;
 
    ASSERT(png_ptr && info_ptr);
 
@@ -246,11 +247,22 @@ static ALLEGRO_BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr)
          else {
             for (i = 0; i < width; i++) {
                uint32_t pix = bmp_read32(ptr);
+               int r = pix & 0xff;
+               int g = (pix >> 8) & 0xff;
+               int b = (pix >> 16) & 0xff;
+               int a = (pix >> 24) & 0xff;
                ptr += 4;
-               *(rgba++) = pix & 0xff;
-               *(rgba++) = (pix >> 8) & 0xff;
-               *(rgba++) = (pix >> 16) & 0xff;
-               *(rgba++) = (pix >> 24) & 0xff;
+
+               if (premul) {
+                  r = r * a / 255;
+                  g = g * a / 255;
+                  b = b * a / 255;
+               }
+
+               *(rgba++) = r;
+               *(rgba++) = g;
+               *(rgba++) = b;
+               *(rgba++) = a;
             }
          }
          rgba = rgba_row_start + lock->pitch;
diff --git a/addons/image/tga.c b/addons/image/tga.c
index 6379ab0..795e71b 100644
--- a/addons/image/tga.c
+++ b/addons/image/tga.c
@@ -248,6 +248,7 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f)
    ALLEGRO_BITMAP *bmp;
    ALLEGRO_LOCKED_REGION *lr;
    unsigned char *buf;
+   bool premul = al_get_new_bitmap_flags() & ALLEGRO_PREMULTIPLY_ALPHA;
    ASSERT(f);
 
    id_length = al_fgetc(f);
@@ -410,6 +411,12 @@ ALLEGRO_BITMAP *_al_load_tga_f(ALLEGRO_FILE *f)
                   int g = buf[i * 4 + 1];
                   int r = buf[i * 4 + 2];
                   int a = buf[i * 4 + 3];
+                  
+                  if (premul) {
+                     r = r * a / 255;
+                     g = g * a / 255;
+                     b = b * a / 255;
+                  }
 
                   unsigned char *dest = (unsigned char*)lr->data +
                      lr->pitch*true_y + true_x*4;
diff --git a/include/allegro5/bitmap.h b/include/allegro5/bitmap.h
index 772ed3d..adee06f 100644
--- a/include/allegro5/bitmap.h
+++ b/include/allegro5/bitmap.h
@@ -61,6 +61,7 @@ typedef enum ALLEGRO_PIXEL_FORMAT
 #define ALLEGRO_MIN_LINEAR            0x0040
 #define ALLEGRO_MAG_LINEAR            0x0080
 #define ALLEGRO_MIPMAP                0x0100
+#define ALLEGRO_PREMULTIPLY_ALPHA     0x0200
 
 
 /* Flags for the blitting functions */


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/