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
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 867a6ff..a2a42a3 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -906,10 +906,34 @@
         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);