Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33fcd11b authored by Matt Sarett's avatar Matt Sarett
Browse files

Encode paletted PNGs more efficiently (part 2)

Many PNGs have multiple distinct pixels with zero alpha.  This
CL allows us to treat all of those pixels as a single zero pixel.

This saves space in the color palette and also may help save
memory pages when we skip writing zeros.

There is also a potential disadvantage: if someone intended to decode
this image as unpremultiplied with particular transfer modes where
their color components have an effect even though alpha is zero,
this will prevent that.  At the moment, we do not support unpremul as
a source, so this won't affect anyone trying to draw with the view
system.

This change originated in:
https://googleplex-android-review.git.corp.google.com/#/c/854580/

Change-Id: I702c7bd22d431cc7c775ed29bbd73c930f945ca3
parent fc1159c8
Loading
Loading
Loading
Loading
+28 −4
Original line number Diff line number Diff line
@@ -906,10 +906,34 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray
        png_bytep row = imageInfo.rows[j];
        png_bytep out = outRows[j];
        for (i = 0; i < w; i++) {
            rr = *row++;
            gg = *row++;
            bb = *row++;
            aa = *row++;

            // Make sure any zero alpha pixels are fully zeroed.  On average,
            // each of our PNG assets seem to have about four distinct pixels
            // with zero alpha.
            // There are several advantages to setting these to zero:
            // (1) Images are more likely able to be encodable with a palette.
            // (2) Image palettes will be smaller.
            // (3) Premultiplied and unpremultiplied PNG decodes can skip
            //     writing zeros to memory, often saving significant numbers
            //     of memory pages.
            aa = *(row + 3);
            if (aa == 0) {
                rr = 0;
                gg = 0;
                bb = 0;

                // Also set red, green, and blue to zero in "row".  If we later
                // decide to encode the PNG as RGB or RGBA, we will use the
                // values stored there.
                *(row) = 0;
                *(row + 1) = 0;
                *(row + 2) = 0;
            } else {
                rr = *(row);
                gg = *(row + 1);
                bb = *(row + 2);
            }
            row += 4;

            int odev = maxGrayDeviation;
            maxGrayDeviation = MAX(ABS(rr - gg), maxGrayDeviation);