// Note: SkColorTable claims to store SkPMColors, which is not necessarily // the case here. bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, int* ctableCount) { int numColors; png_color* palette; if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) { return false; } // Note: These are not necessarily SkPMColors. SkPMColor colorPtr[256]; png_bytep alphas; int numColorsWithAlpha = 0; if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr)) { // Choose which function to use to create the color table. If the final destination's // colortype is unpremultiplied, the color table will store unpremultiplied colors. PackColorProc proc = choose_pack_color_proc(premultiply, dstColorType); for (int i = 0; i < numColorsWithAlpha; i++) { // We don't have a function in SkOpts that combines a set of alphas with a set // of RGBs. We could write one, but it's hardly worth it, given that this // is such a small fraction of the total decode time. colorPtr[i] = proc(alphas[i], palette->red, palette->green, palette->blue); palette++; } } if (numColorsWithAlpha < numColors) { // The optimized code depends on a 3-byte png_color struct with the colors // in RGB order. These checks make sure it is safe to use. static_assert(3 == sizeof(png_color), "png_color struct has changed. Opts are broken."); #ifdef SK_DEBUG SkASSERT(&palette->red < &palette->green); SkASSERT(&palette->green < &palette->blue); #endif if (is_rgba(dstColorType)) { SkOpts::RGB_to_RGB1(colorPtr + numColorsWithAlpha, palette, numColors - numColorsWithAlpha); } else { SkOpts::RGB_to_BGR1(colorPtr + numColorsWithAlpha, palette, numColors - numColorsWithAlpha); } } // Pad the color table with the last color in the table (or black) in the case that // invalid pixel indices exceed the number of colors in the table. const int maxColors = 1 << fBitDepth; if (numColors < maxColors) { SkPMColor lastColor = numColors > 0 ? colorPtr[numColors - 1] : SK_ColorBLACK; sk_memset32(colorPtr + numColors, lastColor, maxColors - numColors); } // Set the new color count. if (ctableCount != nullptr) { *ctableCount = maxColors; } fColorTable.reset(new SkColorTable(colorPtr, maxColors)); return true; }
// Note: SkColorTable claims to store SkPMColors, which is not necessarily the case here. bool SkPngCodec::createColorTable(const SkImageInfo& dstInfo, int* ctableCount) { int numColors; png_color* palette; if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) { return false; } // Contents depend on tableColorType and our choice of if/when to premultiply: // { kPremul, kUnpremul, kOpaque } x { RGBA, BGRA } SkPMColor colorTable[256]; SkColorType tableColorType = fColorXform ? kRGBA_8888_SkColorType : dstInfo.colorType(); png_bytep alphas; int numColorsWithAlpha = 0; if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr)) { // If we are performing a color xform, it will handle the premultiply. Otherwise, // we'll do it here. bool premultiply = !fColorXform && needs_premul(dstInfo, this->getInfo()); // Choose which function to use to create the color table. If the final destination's // colortype is unpremultiplied, the color table will store unpremultiplied colors. PackColorProc proc = choose_pack_color_proc(premultiply, tableColorType); for (int i = 0; i < numColorsWithAlpha; i++) { // We don't have a function in SkOpts that combines a set of alphas with a set // of RGBs. We could write one, but it's hardly worth it, given that this // is such a small fraction of the total decode time. colorTable[i] = proc(alphas[i], palette->red, palette->green, palette->blue); palette++; } } if (numColorsWithAlpha < numColors) { // The optimized code depends on a 3-byte png_color struct with the colors // in RGB order. These checks make sure it is safe to use. static_assert(3 == sizeof(png_color), "png_color struct has changed. Opts are broken."); #ifdef SK_DEBUG SkASSERT(&palette->red < &palette->green); SkASSERT(&palette->green < &palette->blue); #endif if (is_rgba(tableColorType)) { SkOpts::RGB_to_RGB1(colorTable + numColorsWithAlpha, palette, numColors - numColorsWithAlpha); } else { SkOpts::RGB_to_BGR1(colorTable + numColorsWithAlpha, palette, numColors - numColorsWithAlpha); } } // If we are not decoding to F16, we can color xform now and store the results // in the color table. if (fColorXform && kRGBA_F16_SkColorType != dstInfo.colorType()) { SkColorType xformColorType = is_rgba(dstInfo.colorType()) ? kRGBA_8888_SkColorType : kBGRA_8888_SkColorType; SkAlphaType xformAlphaType = xform_alpha_type(dstInfo.alphaType(), this->getInfo().alphaType()); fColorXform->apply(colorTable, colorTable, numColors, xformColorType, xformAlphaType); } // Pad the color table with the last color in the table (or black) in the case that // invalid pixel indices exceed the number of colors in the table. const int maxColors = 1 << fBitDepth; if (numColors < maxColors) { SkPMColor lastColor = numColors > 0 ? colorTable[numColors - 1] : SK_ColorBLACK; sk_memset32(colorTable + numColors, lastColor, maxColors - numColors); } // Set the new color count. if (ctableCount != nullptr) { *ctableCount = maxColors; } fColorTable.reset(new SkColorTable(colorTable, maxColors)); return true; }