De-pre-multiplying Alpha

This is a discussion on De-pre-multiplying Alpha within the Game Programming forums, part of the General Programming Boards category; Hello, I'm in the process of coming up with a few functions that deal with rendering SVG data (vector paths, ...

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262

    Question De-pre-multiplying Alpha

    Hello,

    I'm in the process of coming up with a few functions that deal with rendering SVG data (vector paths, none of the cruft) to PNG files. To make life a bit easier and consistent I'm using Cairo to draw, then saving the 32-bits per pixel surface into a PNG file manually.

    The thing is, as Cairo expects to composite 32-bit surfaces, the pixels use pre-multiplied alpha. PNG doesn't (Apple made the mistake of doing what they liked at this point).

    It's surprisingly tricky to find concrete information on conversion between these two formats, so I've winged it a bit and come up with:-
    Code:
    double d;
    unsigned char nAlpha, *pPtr;
    
    // current format in memory: B G R A
    // assume pPtr is pointing to B of a pixel
    nAlpha = *(pPtr + 3);
    if (nAlpha > 0)
    {
        d = ((*pPtr) * 255.0) + (nAlpha / 2.0);
        *pPtr = (unsigned char)(d / nAlpha);
    }
    // repeat for G and R, then swap B and R as PNG pixels are R G B A
    It's probably quite inefficient, this is intended to be used in a process that focuses on quality over speed anyway.

    But is it right?

  2. #2
    Registered User
    Join Date
    Aug 2003
    Posts
    1,198
    Well to de-premultiply you will have to decide what color you want your background color to have.

    The normal way to composite a color over another is Ca+B(1-a) (in this case you composite color C over B, with alpha a). With premultiplied you substitute Ca with A, thus you get A+B(1-a), but since what you want is C we will work with that instead.

    So you have Ca + B(1-a) = D, where C is original color (what you want), B is background (decided by you) and D is the resulting color (the one Cairo gives you). This gives you
    Ca + B - Ba = D
    Ca - Ba = D - B
    a(C-B) = D-B
    C-B = (D-B)/a
    C = B + ((D-B)/a)

    This is what i could infer from this: [cairo] Compositing strategies and pre-multiplied alpha

    Now the real question is, why aren't you using cairo_surface_write_to_png ()? PNG Support

  3. #3
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,236
    Premultiplied alpha means exactly what it sounds like. To "un-pre-multiply" it you divide the R, G, B components by alpha:

    Code:
    int new_r = 255 * r / alpha;
    int new_g = 255 * g / alpha;
    int new_b = 255 * b / alpha;
    This loses information, but the information was already lost when it was pre-multiplied in the first place.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262
    Quote Originally Posted by Shakti View Post
    Well to de-premultiply you will have to decide what color you want your background color to have.
    Eh? Surely the point of having an alpha channel, pre-multiplied or no, is that you are storing a factor to mix with "nothingness", i.e. the background colour is whatever the initial colour of the surface is before you draw. RGBA (255, 255, 255, 0) is not white.
    Quote Originally Posted by Shakti View Post
    Now the real question is, why aren't you using cairo_surface_write_to_png ()?
    A technicality: PNG support in Cairo requires libpng. Outputting only 32bpp images with no compression applied means that I can generate compliant PNGs while adding, oooh... 2KB to the release build?

    My code is broadly similar to what Brewbuck has posted, only I can't explain the (nAlpha / 2.0) bit in mine.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. multiplying matricies
    By danieldcc in forum C Programming
    Replies: 2
    Last Post: 09-17-2011, 08:48 PM
  2. Multiplying polynomials
    By budala in forum C Programming
    Replies: 6
    Last Post: 08-19-2009, 03:19 PM
  3. Multiplying matrices
    By Star Lancer in forum C++ Programming
    Replies: 7
    Last Post: 05-22-2003, 06:07 AM
  4. Multiplying! PLEASE HELP!!!!!!!!!!!!!
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 10-23-2001, 09:12 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21