Allow ninepatches to be encoded using non-RGBA modes
The original intention for forcing ninepatches to be encoded as
RGBA (with alpha) was to avoid the possibility of the decoder
producing 565 output.
565 output is bad for ninepatches because dithering tiny images
that we intend to scale later leads to bad results. I would
argue that, since the new BitmapFactory does not dither, we might
now be ok to allow 565 decodes for ninepatches. However, we
will maintain the old behavior by disabling 565 decodes for
ninepatch.
There are two changes to PNG encodings:
(1) Allows ninepatch images to be encoded in any mode. Forcing
them to RGBA makes things awkward for the decoder. Currently,
BitmapFactory's png decoder checks every pixel for alpha.
That way, RGBA images that are actually opaque can be marked
as opaque, in order to optimize drawing. We want to remove
this complexity from the decoder.
(2) Make sure ninepatch chunks are stored in the png header. That
way we know immediately that the png is a ninepatch, and can
refuse to decode to 565 (if we feel this is best).
Change-Id: I724f5dbefb1be7b412f9b362dff83cbc0603f0bf
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index d8ec22a0..92f7812 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -260,6 +260,15 @@
return nullObjectReturn("SkAndroidCodec::NewFromStream returned null");
}
+ // Do not allow ninepatch decodes to 565. In the past, decodes to 565
+ // would dither, and we do not want to pre-dither ninepatches, since we
+ // know that they will be stretched. We no longer dither 565 decodes,
+ // but we continue to prevent ninepatches from decoding to 565, in order
+ // to maintain the old behavior.
+ if (peeker.mPatch && kRGB_565_SkColorType == prefColorType) {
+ prefColorType = kN32_SkColorType;
+ }
+
// Determine the output size and return if the client only wants the size.
SkISize size = codec->getSampledDimensions(sampleSize);
if (options != NULL) {
@@ -369,15 +378,7 @@
case SkCodec::kIncompleteInput:
break;
default:
- return nullObjectReturn("codec->getAndoridPixels() failed.");
- }
-
- // Some images may initially report that they have alpha due to the format
- // of the encoded data, but then never use any colors which have alpha
- // less than 100%. Here we check if the image really had alpha, and
- // mark it as opaque if it is actually opaque.
- if (kOpaque_SkAlphaType != alphaType && !codec->reallyHasAlpha()) {
- decodingBitmap.setAlphaType(kOpaque_SkAlphaType);
+ return nullObjectReturn("codec->getAndroidPixels() failed.");
}
int scaledWidth = size.width();
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index e4738f5..5ad3379 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -1095,13 +1095,6 @@
analyze_image(imageName, imageInfo, grayscaleTolerance, rgbPalette, alphaPalette,
&paletteEntries, &hasTransparency, &color_type, outRows);
- // If the image is a 9-patch, we need to preserve it as a ARGB file to make
- // sure the pixels will not be pre-dithered/clamped until we decide they are
- if (imageInfo.is9Patch && (color_type == PNG_COLOR_TYPE_RGB ||
- color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)) {
- color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- }
-
if (kIsDebug) {
switch (color_type) {
case PNG_COLOR_TYPE_PALETTE:
@@ -1180,18 +1173,11 @@
}
for (int i = 0; i < chunk_count; i++) {
- unknowns[i].location = PNG_HAVE_PLTE;
+ unknowns[i].location = PNG_HAVE_IHDR;
}
png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
chunk_names, chunk_count);
png_set_unknown_chunks(write_ptr, write_info, unknowns, chunk_count);
-#if PNG_LIBPNG_VER < 10600
- /* Deal with unknown chunk location bug in 1.5.x and earlier */
- png_set_unknown_chunk_location(write_ptr, write_info, 0, PNG_HAVE_PLTE);
- if (imageInfo.haveLayoutBounds) {
- png_set_unknown_chunk_location(write_ptr, write_info, 1, PNG_HAVE_PLTE);
- }
-#endif
}