SkPDFImage no longer caches a unpremul version of N32 bitmaps.

This reduces PDF memory overhead by 30% over all GMs.

This reduces PDF memory overhead by 41% over all SKPs in
chromium-skia-gm/playback_${SKP_VERSION}/skps.

BUG=skia:3030

Review URL: https://codereview.chromium.org/840653002
This commit is contained in:
halcanary 2015-01-08 11:05:35 -08:00 committed by Commit bot
parent 343c2f4dfb
commit 549f879d6a

View File

@ -133,37 +133,58 @@ static SkStream* extract_rgb565_image(const SkBitmap& bitmap,
return stream;
}
static uint32_t get_argb8888_neighbor_avg_color(const SkBitmap& bitmap,
int xOrig,
int yOrig);
static SkStream* extract_argb8888_data(const SkBitmap& bitmap,
const SkIRect& srcRect,
bool extractAlpha,
bool* isOpaque,
bool* isTransparent) {
SkStream* stream;
if (extractAlpha) {
stream = SkNEW_ARGS(SkMemoryStream,
(srcRect.width() * srcRect.height()));
} else {
stream = SkNEW_ARGS(SkMemoryStream,
(get_uncompressed_size(bitmap, srcRect)));
}
size_t streamSize = extractAlpha ? srcRect.width() * srcRect.height()
: get_uncompressed_size(bitmap, srcRect);
SkStream* stream = SkNEW_ARGS(SkMemoryStream, (streamSize));
uint8_t* dst = (uint8_t*)stream->getMemoryBase();
const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
uint32_t* src = bitmap.getAddr32(0, y);
for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
SkPMColor c = src[x];
U8CPU alpha = SkGetPackedA32(c);
if (extractAlpha) {
dst[0] = SkGetPackedA32(src[x]);
*isOpaque &= dst[0] == SK_AlphaOPAQUE;
*isTransparent &= dst[0] == SK_AlphaTRANSPARENT;
dst++;
*isOpaque &= alpha == SK_AlphaOPAQUE;
*isTransparent &= alpha == SK_AlphaTRANSPARENT;
*dst++ = alpha;
} else {
dst[0] = SkGetPackedR32(src[x]);
dst[1] = SkGetPackedG32(src[x]);
dst[2] = SkGetPackedB32(src[x]);
dst += 3;
if (SK_AlphaTRANSPARENT == alpha) {
// It is necessary to average the color component of
// transparent pixels with their surrounding neighbors
// since the PDF renderer may separately re-sample the
// alpha and color channels when the image is not
// displayed at its native resolution. Since an alpha of
// zero gives no information about the color component,
// the pathological case is a white image with sharp
// transparency bounds - the color channel goes to black,
// and the should-be-transparent pixels are rendered
// as grey because of the separate soft mask and color
// resizing.
c = get_argb8888_neighbor_avg_color(bitmap, x, y);
*dst++ = SkGetPackedR32(c);
*dst++ = SkGetPackedG32(c);
*dst++ = SkGetPackedB32(c);
} else {
SkUnPreMultiply::Scale s = scaleTable[alpha];
*dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c));
*dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedG32(c));
*dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c));
}
}
}
}
SkASSERT(dst == streamSize + (uint8_t*)stream->getMemoryBase());
return stream;
}
@ -464,10 +485,18 @@ SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
SkColorType colorType = bitmap.colorType();
if (alphaData.get() != NULL && (kN32_SkColorType == colorType ||
kARGB_4444_SkColorType == colorType)) {
SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect);
image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false,
SkIRect::MakeWH(srcRect.width(), srcRect.height()),
encoder));
if (kN32_SkColorType == colorType) {
image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false,
SkIRect::MakeWH(srcRect.width(),
srcRect.height()),
encoder));
} else {
SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect);
image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false,
SkIRect::MakeWH(srcRect.width(),
srcRect.height()),
encoder));
}
} else {
image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect, encoder));
}
@ -588,7 +617,6 @@ SkPDFImage::SkPDFImage(SkPDFImage& pdfImage)
bool SkPDFImage::populate(SkPDFCatalog* catalog) {
if (getState() == kUnused_State) {
// Initializing image data for the first time.
SkDynamicMemoryWStream dctCompressedWStream;
if (!skip_compression(catalog) && fEncoder &&
get_uncompressed_size(fBitmap, fSrcRect) > 1) {
SkBitmap subset;