encode kAlpha_8 as grayalpha with sigbits for gray==1

Bug: skia:
Change-Id: Ib61e8e0f62af92d8746f5e73469002e7804a8447
Reviewed-on: https://skia-review.googlesource.com/78481
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 59978c6..a0f1fb2 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -175,6 +175,10 @@
         case kGray_8_SkColorType:
             return SkEncodedInfo::kGray_Color == srcColor && srcIsOpaque &&
                    !needs_color_xform(dst, srcCS, false);
+        case kAlpha_8_SkColorType:
+            // conceptually we can convert anything into alpha_8, but we haven't actually coded
+            // all of those other conversions yet, so only return true for the case we have codec.
+            return fSrcInfo.colorType() == kAlpha_8_SkColorType;;
         default:
             return false;
     }
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index e9fff97..9df7bc6 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -14,6 +14,7 @@
 #include "SkMath.h"
 #include "SkOpts.h"
 #include "SkPngCodec.h"
+#include "SkPngPriv.h"
 #include "SkPoint3.h"
 #include "SkSize.h"
 #include "SkStream.h"
@@ -935,7 +936,14 @@
         SkEncodedInfo encodedInfo = SkEncodedInfo::Make(color, alpha, bitDepth);
         SkImageInfo imageInfo = encodedInfo.makeImageInfo(origWidth, origHeight, colorSpace);
 
-        if (SkEncodedInfo::kOpaque_Alpha == alpha) {
+        if (encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
+            png_color_8p sigBits;
+            if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) {
+                if (8 == sigBits->alpha && kGraySigBit_GrayAlphaIsJustAlpha == sigBits->gray) {
+                    imageInfo = imageInfo.makeColorType(kAlpha_8_SkColorType);
+                }
+            }
+        } else if (SkEncodedInfo::kOpaque_Alpha == alpha) {
             png_color_8p sigBits;
             if (png_get_sBIT(fPng_ptr, fInfo_ptr, &sigBits)) {
                 if (5 == sigBits->red && 6 == sigBits->green && 5 == sigBits->blue) {
diff --git a/src/codec/SkPngPriv.h b/src/codec/SkPngPriv.h
new file mode 100644
index 0000000..3269309
--- /dev/null
+++ b/src/codec/SkPngPriv.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPngPriv_DEFINED
+#define SkPngPriv_DEFINED
+
+#include "SkTypes.h"
+
+// We store kAlpha_8 images as GrayAlpha in png. Our private signal is significant bits for gray.
+// If that is set to 1, we assume the gray channel can be ignored, and we output just alpha.
+// We tried 0 at first, but png doesn't like a 0 sigbit for a channel it expects, hence we chose 1.
+
+static constexpr int kGraySigBit_GrayAlphaIsJustAlpha = 1;
+
+#endif
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index 84bb097..f3d97af 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -357,6 +357,16 @@
     SkOpts::grayA_to_rgbA((uint32_t*) dst, src + offset, width);
 }
 
+static void swizzle_grayalpha_to_a8(void* dst, const uint8_t* src, int width, int bpp,
+                                    int deltaSrc, int offset, const SkPMColor[]) {
+    src += offset;
+    uint8_t* dst8 = (uint8_t*)dst;
+    for (int x = 0; x < width; ++x) {
+        dst8[x] = src[1];   // src[0] is gray, ignored
+        src += deltaSrc;
+    }
+}
+
 // kBGR
 
 static void swizzle_bgr_to_565(
@@ -906,6 +916,9 @@
                             }
                         }
                         break;
+                    case kAlpha_8_SkColorType:
+                        proc = &swizzle_grayalpha_to_a8;
+                        break;
                     default:
                         return nullptr;
                 }
diff --git a/src/images/SkImageEncoderFns.h b/src/images/SkImageEncoderFns.h
index d5de065..dd02ebf 100644
--- a/src/images/SkImageEncoderFns.h
+++ b/src/images/SkImageEncoderFns.h
@@ -92,6 +92,18 @@
 }
 
 /**
+ * Transform from kAlpha_8_Config to 2-bytes-per-pixel GrayAlpha.
+ */
+static inline void transform_scanline_A8_to_GrayAlpha(char* SK_RESTRICT dst,
+                                                      const char* SK_RESTRICT src,
+                                                      int width, int, const SkPMColor*) {
+    for (int i = 0; i < width; i++) {
+        *dst++ = 0;         // gray (ignored)
+        *dst++ = *src++;    // alpha
+    }
+}
+
+/**
  * Transform from kRGBA_8888_SkColorType to 3-bytes-per-pixel RGB.
  * Alpha channel data is abandoned.
  */
diff --git a/src/images/SkPngEncoder.cpp b/src/images/SkPngEncoder.cpp
index 748953f..211efa8 100644
--- a/src/images/SkPngEncoder.cpp
+++ b/src/images/SkPngEncoder.cpp
@@ -15,6 +15,7 @@
 #include "SkStream.h"
 #include "SkString.h"
 #include "SkPngEncoder.h"
+#include "SkPngPriv.h"
 
 #include "png.h"
 
@@ -149,6 +150,12 @@
             fPngBytesPerPixel = 3;
             SkASSERT(srcInfo.isOpaque());
             break;
+        case kAlpha_8_SkColorType:  // store as gray+alpha, but ignore gray
+            sigBit.gray = kGraySigBit_GrayAlphaIsJustAlpha;
+            sigBit.alpha = 8;
+            pngColorType = PNG_COLOR_TYPE_GRAY_ALPHA;
+            fPngBytesPerPixel = 2;
+            break;
         default:
             return false;
     }
@@ -254,6 +261,8 @@
                     SkASSERT(false);
                     return nullptr;
             }
+        case kAlpha_8_SkColorType:
+            return transform_scanline_A8_to_GrayAlpha;
         default:
             SkASSERT(false);
             return nullptr;