diff options
Diffstat (limited to 'tools/aapt/Images.cpp')
-rw-r--r-- | tools/aapt/Images.cpp | 272 |
1 files changed, 143 insertions, 129 deletions
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp index 5d4a6ac..e4738f5 100644 --- a/tools/aapt/Images.cpp +++ b/tools/aapt/Images.cpp @@ -14,7 +14,8 @@ #include <png.h> #include <zlib.h> -#define NOISY(x) //x +// Change this to true for noisy debug output. +static const bool kIsDebug = false; static void png_write_aapt_file(png_structp png_ptr, png_bytep data, png_size_t length) @@ -28,7 +29,7 @@ png_write_aapt_file(png_structp png_ptr, png_bytep data, png_size_t length) static void -png_flush_aapt_file(png_structp png_ptr) +png_flush_aapt_file(png_structp /* png_ptr */) { } @@ -156,11 +157,13 @@ static void read_png(const char* imageName, png_read_end(read_ptr, read_info); - NOISY(printf("Image %s: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", - imageName, - (int)outImageInfo->width, (int)outImageInfo->height, - bit_depth, color_type, - interlace_type, compression_type)); + if (kIsDebug) { + printf("Image %s: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", + imageName, + (int)outImageInfo->width, (int)outImageInfo->height, + bit_depth, color_type, + interlace_type, compression_type); + } png_get_IHDR(read_ptr, read_info, &outImageInfo->width, &outImageInfo->height, &bit_depth, &color_type, @@ -330,7 +333,7 @@ static status_t get_vertical_ticks( } static status_t get_horizontal_layout_bounds_ticks( - png_bytep row, int width, bool transparent, bool required, + png_bytep row, int width, bool transparent, bool /* required */, int32_t* outLeft, int32_t* outRight, const char** outError) { int i; @@ -368,7 +371,7 @@ static status_t get_horizontal_layout_bounds_ticks( } static status_t get_vertical_layout_bounds_ticks( - png_bytepp rows, int offset, int height, bool transparent, bool required, + png_bytepp rows, int offset, int height, bool transparent, bool /* required */, int32_t* outTop, int32_t* outBottom, const char** outError) { int i; @@ -409,7 +412,6 @@ static void find_max_opacity(png_byte** rows, int startX, int startY, int endX, int endY, int dX, int dY, int* out_inset) { - bool opaque_within_inset = true; uint8_t max_opacity = 0; int inset = 0; *out_inset = 0; @@ -478,8 +480,9 @@ static void get_outline(image_info* image) // assuming the image is a round rect, compute the radius by marching // diagonally from the top left corner towards the center - image->outlineAlpha = max(max_alpha_over_row(image->rows[innerMidY], innerStartX, innerEndX), - max_alpha_over_col(image->rows, innerMidX, innerStartY, innerStartY)); + image->outlineAlpha = std::max( + max_alpha_over_row(image->rows[innerMidY], innerStartX, innerEndX), + max_alpha_over_col(image->rows, innerMidX, innerStartY, innerStartY)); int diagonalInset = 0; find_max_opacity(image->rows, innerStartX, innerStartY, innerMidX, innerMidY, 1, 1, @@ -493,13 +496,15 @@ static void get_outline(image_info* image) */ image->outlineRadius = 3.4142f * diagonalInset; - NOISY(printf("outline insets %d %d %d %d, rad %f, alpha %x\n", - image->outlineInsetsLeft, - image->outlineInsetsTop, - image->outlineInsetsRight, - image->outlineInsetsBottom, - image->outlineRadius, - image->outlineAlpha)); + if (kIsDebug) { + printf("outline insets %d %d %d %d, rad %f, alpha %x\n", + image->outlineInsetsLeft, + image->outlineInsetsTop, + image->outlineInsetsRight, + image->outlineInsetsBottom, + image->outlineRadius, + image->outlineAlpha); + } } @@ -533,41 +538,6 @@ static uint32_t get_color( return (color[3]<<24) | (color[0]<<16) | (color[1]<<8) | color[2]; } -static void select_patch( - int which, int front, int back, int size, int* start, int* end) -{ - switch (which) { - case 0: - *start = 0; - *end = front-1; - break; - case 1: - *start = front; - *end = back-1; - break; - case 2: - *start = back; - *end = size-1; - break; - } -} - -static uint32_t get_color(image_info* image, int hpatch, int vpatch) -{ - int left, right, top, bottom; - select_patch( - hpatch, image->xDivs[0], image->xDivs[1], - image->width, &left, &right); - select_patch( - vpatch, image->yDivs[0], image->yDivs[1], - image->height, &top, &bottom); - //printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n", - // hpatch, vpatch, left, top, right, bottom); - const uint32_t c = get_color(image->rows, left, top, right, bottom); - NOISY(printf("Color in (%d,%d)-(%d,%d): #%08x\n", left, top, right, bottom, c)); - return c; -} - static status_t do_9patch(const char* imageName, image_info* image) { image->is9Patch = true; @@ -672,8 +642,10 @@ static status_t do_9patch(const char* imageName, image_info* image) || image->layoutBoundsBottom != 0; if (image->haveLayoutBounds) { - NOISY(printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop, - image->layoutBoundsRight, image->layoutBoundsBottom)); + if (kIsDebug) { + printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop, + image->layoutBoundsRight, image->layoutBoundsBottom); + } } // use opacity of pixels to estimate the round rect outline @@ -695,12 +667,14 @@ static status_t do_9patch(const char* imageName, image_info* image) image->info9Patch.paddingBottom = H - 2 - image->info9Patch.paddingBottom; } - NOISY(printf("Size ticks for %s: x0=%d, x1=%d, y0=%d, y1=%d\n", imageName, - xDivs[0], xDivs[1], - yDivs[0], yDivs[1])); - NOISY(printf("padding ticks for %s: l=%d, r=%d, t=%d, b=%d\n", imageName, - image->info9Patch.paddingLeft, image->info9Patch.paddingRight, - image->info9Patch.paddingTop, image->info9Patch.paddingBottom)); + if (kIsDebug) { + printf("Size ticks for %s: x0=%d, x1=%d, y0=%d, y1=%d\n", imageName, + xDivs[0], xDivs[1], + yDivs[0], yDivs[1]); + printf("padding ticks for %s: l=%d, r=%d, t=%d, b=%d\n", imageName, + image->info9Patch.paddingLeft, image->info9Patch.paddingRight, + image->info9Patch.paddingTop, image->info9Patch.paddingBottom); + } // Remove frame from image. image->rows = (png_bytepp)malloc((H-2) * sizeof(png_bytep)); @@ -782,7 +756,10 @@ static status_t do_9patch(const char* imageName, image_info* image) } c = get_color(image->rows, left, top, right - 1, bottom - 1); image->colors[colorIndex++] = c; - NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true); + if (kIsDebug) { + if (c != Res_png_9patch::NO_COLOR) + hasColor = true; + } left = right; } top = bottom; @@ -885,7 +862,7 @@ static void dump_image(int w, int h, png_bytepp rows, int color_type) break; } if (i == (w - 1)) { - NOISY(printf("\n")); + printf("\n"); } } } @@ -915,8 +892,10 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray // 2. Every pixel has A == 255 (opaque) // 3. There are no more than 256 distinct RGBA colors - // NOISY(printf("Initial image data:\n")); - // dump_image(w, h, imageInfo.rows, PNG_COLOR_TYPE_RGB_ALPHA); + if (kIsDebug) { + printf("Initial image data:\n"); + dump_image(w, h, imageInfo.rows, PNG_COLOR_TYPE_RGB_ALPHA); + } for (j = 0; j < h; j++) { png_bytep row = imageInfo.rows[j]; @@ -932,15 +911,19 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray maxGrayDeviation = MAX(ABS(gg - bb), maxGrayDeviation); maxGrayDeviation = MAX(ABS(bb - rr), maxGrayDeviation); if (maxGrayDeviation > odev) { - NOISY(printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", - maxGrayDeviation, i, j, rr, gg, bb, aa)); + if (kIsDebug) { + printf("New max dev. = %d at pixel (%d, %d) = (%d %d %d %d)\n", + maxGrayDeviation, i, j, rr, gg, bb, aa); + } } // Check if image is really grayscale if (isGrayscale) { if (rr != gg || rr != bb) { - NOISY(printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", - i, j, rr, gg, bb, aa)); + if (kIsDebug) { + printf("Found a non-gray pixel at %d, %d = (%d %d %d %d)\n", + i, j, rr, gg, bb, aa); + } isGrayscale = false; } } @@ -948,8 +931,10 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray // Check if image is really opaque if (isOpaque) { if (aa != 0xff) { - NOISY(printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", - i, j, rr, gg, bb, aa)); + if (kIsDebug) { + printf("Found a non-opaque pixel at %d, %d = (%d %d %d %d)\n", + i, j, rr, gg, bb, aa); + } isOpaque = false; } } @@ -971,7 +956,9 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray *out++ = idx; if (!match) { if (num_colors == 256) { - NOISY(printf("Found 257th color at %d, %d\n", i, j)); + if (kIsDebug) { + printf("Found 257th color at %d, %d\n", i, j); + } isPalette = false; } else { colors[num_colors++] = col; @@ -986,12 +973,14 @@ static void analyze_image(const char *imageName, image_info &imageInfo, int gray int bpp = isOpaque ? 3 : 4; int paletteSize = w * h + bpp * num_colors; - NOISY(printf("isGrayscale = %s\n", isGrayscale ? "true" : "false")); - NOISY(printf("isOpaque = %s\n", isOpaque ? "true" : "false")); - NOISY(printf("isPalette = %s\n", isPalette ? "true" : "false")); - NOISY(printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", - paletteSize, 2 * w * h, bpp * w * h)); - NOISY(printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, grayscaleTolerance)); + if (kIsDebug) { + printf("isGrayscale = %s\n", isGrayscale ? "true" : "false"); + printf("isOpaque = %s\n", isOpaque ? "true" : "false"); + printf("isPalette = %s\n", isPalette ? "true" : "false"); + printf("Size w/ palette = %d, gray+alpha = %d, rgb(a) = %d\n", + paletteSize, 2 * w * h, bpp * w * h); + printf("Max gray deviation = %d, tolerance = %d\n", maxGrayDeviation, grayscaleTolerance); + } // Choose the best color type for the image. // 1. Opaque gray - use COLOR_TYPE_GRAY at 1 byte/pixel @@ -1068,7 +1057,6 @@ static void write_png(const char* imageName, png_structp write_ptr, png_infop write_info, image_info& imageInfo, int grayscaleTolerance) { - bool optimize = true; png_uint_32 width, height; int color_type; int bit_depth, interlace_type, compression_type; @@ -1094,8 +1082,10 @@ static void write_png(const char* imageName, png_set_compression_level(write_ptr, Z_BEST_COMPRESSION); - NOISY(printf("Writing image %s: w = %d, h = %d\n", imageName, - (int) imageInfo.width, (int) imageInfo.height)); + if (kIsDebug) { + printf("Writing image %s: w = %d, h = %d\n", imageName, + (int) imageInfo.width, (int) imageInfo.height); + } png_color rgbPalette[256]; png_byte alphaPalette[256]; @@ -1112,24 +1102,26 @@ static void write_png(const char* imageName, color_type = PNG_COLOR_TYPE_RGB_ALPHA; } - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - NOISY(printf("Image %s has %d colors%s, using PNG_COLOR_TYPE_PALETTE\n", - imageName, paletteEntries, - hasTransparency ? " (with alpha)" : "")); - break; - case PNG_COLOR_TYPE_GRAY: - NOISY(printf("Image %s is opaque gray, using PNG_COLOR_TYPE_GRAY\n", imageName)); - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - NOISY(printf("Image %s is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA\n", imageName)); - break; - case PNG_COLOR_TYPE_RGB: - NOISY(printf("Image %s is opaque RGB, using PNG_COLOR_TYPE_RGB\n", imageName)); - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - NOISY(printf("Image %s is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA\n", imageName)); - break; + if (kIsDebug) { + switch (color_type) { + case PNG_COLOR_TYPE_PALETTE: + printf("Image %s has %d colors%s, using PNG_COLOR_TYPE_PALETTE\n", + imageName, paletteEntries, + hasTransparency ? " (with alpha)" : ""); + break; + case PNG_COLOR_TYPE_GRAY: + printf("Image %s is opaque gray, using PNG_COLOR_TYPE_GRAY\n", imageName); + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + printf("Image %s is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA\n", imageName); + break; + case PNG_COLOR_TYPE_RGB: + printf("Image %s is opaque RGB, using PNG_COLOR_TYPE_RGB\n", imageName); + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + printf("Image %s is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA\n", imageName); + break; + } } png_set_IHDR(write_ptr, write_info, imageInfo.width, imageInfo.height, @@ -1158,7 +1150,9 @@ static void write_png(const char* imageName, : (png_byte*)"npOl\0npTc"; // base 9 patch data - NOISY(printf("Adding 9-patch info...\n")); + if (kIsDebug) { + printf("Adding 9-patch info...\n"); + } strcpy((char*)unknowns[p_index].name, "npTc"); unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch(); unknowns[p_index].size = imageInfo.info9Patch.serializedSize(); @@ -1214,8 +1208,10 @@ static void write_png(const char* imageName, } png_write_image(write_ptr, rows); -// NOISY(printf("Final image data:\n")); -// dump_image(imageInfo.width, imageInfo.height, rows, color_type); + if (kIsDebug) { + printf("Final image data:\n"); + dump_image(imageInfo.width, imageInfo.height, rows, color_type); + } png_write_end(write_ptr, write_info); @@ -1231,13 +1227,50 @@ static void write_png(const char* imageName, &bit_depth, &color_type, &interlace_type, &compression_type, NULL); - NOISY(printf("Image written: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", - (int)width, (int)height, bit_depth, color_type, interlace_type, - compression_type)); + if (kIsDebug) { + printf("Image written: w=%d, h=%d, d=%d, colors=%d, inter=%d, comp=%d\n", + (int)width, (int)height, bit_depth, color_type, interlace_type, + compression_type); + } } -status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, - const sp<AaptFile>& file, String8* outNewLeafName) +static bool read_png_protected(png_structp read_ptr, String8& printableName, png_infop read_info, + const sp<AaptFile>& file, FILE* fp, image_info* imageInfo) { + if (setjmp(png_jmpbuf(read_ptr))) { + return false; + } + + png_init_io(read_ptr, fp); + + read_png(printableName.string(), read_ptr, read_info, imageInfo); + + const size_t nameLen = file->getPath().length(); + if (nameLen > 6) { + const char* name = file->getPath().string(); + if (name[nameLen-5] == '9' && name[nameLen-6] == '.') { + if (do_9patch(printableName.string(), imageInfo) != NO_ERROR) { + return false; + } + } + } + + return true; +} + +static bool write_png_protected(png_structp write_ptr, String8& printableName, png_infop write_info, + image_info* imageInfo, const Bundle* bundle) { + if (setjmp(png_jmpbuf(write_ptr))) { + return false; + } + + write_png(printableName.string(), write_ptr, write_info, *imageInfo, + bundle->getGrayscaleTolerance()); + + return true; +} + +status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets */, + const sp<AaptFile>& file, String8* /* outNewLeafName */) { String8 ext(file->getPath().getPathExtension()); @@ -1267,8 +1300,6 @@ status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, status_t error = UNKNOWN_ERROR; - const size_t nameLen = file->getPath().length(); - fp = fopen(file->getSourceFile().string(), "rb"); if (fp == NULL) { fprintf(stderr, "%s: ERROR: Unable to open PNG file\n", printableName.string()); @@ -1286,23 +1317,10 @@ status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, goto bail; } - if (setjmp(png_jmpbuf(read_ptr))) { + if (!read_png_protected(read_ptr, printableName, read_info, file, fp, &imageInfo)) { goto bail; } - png_init_io(read_ptr, fp); - - read_png(printableName.string(), read_ptr, read_info, &imageInfo); - - if (nameLen > 6) { - const char* name = file->getPath().string(); - if (name[nameLen-5] == '9' && name[nameLen-6] == '.') { - if (do_9patch(printableName.string(), &imageInfo) != NO_ERROR) { - goto bail; - } - } - } - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, (png_error_ptr)NULL, (png_error_ptr)NULL); if (!write_ptr) @@ -1319,14 +1337,10 @@ status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, png_set_write_fn(write_ptr, (void*)file.get(), png_write_aapt_file, png_flush_aapt_file); - if (setjmp(png_jmpbuf(write_ptr))) - { + if (!write_png_protected(write_ptr, printableName, write_info, &imageInfo, bundle)) { goto bail; } - write_png(printableName.string(), write_ptr, write_info, imageInfo, - bundle->getGrayscaleTolerance()); - error = NO_ERROR; if (bundle->getVerbose()) { |