Index: src/pdf/SkPDFImage.cpp |
diff --git a/src/pdf/SkPDFImage.cpp b/src/pdf/SkPDFImage.cpp |
index 73d85816aa7e070b4d022dcfe76af218597cf81a..65454fabc6a4b41fbd93d5ea495b0e89ce4676e1 100644 |
--- a/src/pdf/SkPDFImage.cpp |
+++ b/src/pdf/SkPDFImage.cpp |
@@ -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; |