SkPDFBitmap.cpp revision 3f4671871fac8e5439440ce756d0666bc2a96f46
11b5c604d9d344537941b11b136348edfc39f236chalcanary/* 21b5c604d9d344537941b11b136348edfc39f236chalcanary * Copyright 2015 Google Inc. 31b5c604d9d344537941b11b136348edfc39f236chalcanary * 41b5c604d9d344537941b11b136348edfc39f236chalcanary * Use of this source code is governed by a BSD-style license that can be 51b5c604d9d344537941b11b136348edfc39f236chalcanary * found in the LICENSE file. 61b5c604d9d344537941b11b136348edfc39f236chalcanary */ 71b5c604d9d344537941b11b136348edfc39f236chalcanary 84f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary#include "SkPDFBitmap.h" 94f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary 101b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkColorPriv.h" 11a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary#include "SkData.h" 12d9e57158ebd9b1f8317f0d76ef0402cfce0b0253halcanary#include "SkDeflate.h" 134f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary#include "SkImage.h" 1496287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary#include "SkJpegInfo.h" 151b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkPDFCanon.h" 16b8d6af169bf631dcb68ba5a796436434ff78be65martina.kollarova#include "SkPDFTypes.h" 174f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary#include "SkPDFUtils.h" 181b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkStream.h" 191b5c604d9d344537941b11b136348edfc39f236chalcanary#include "SkUnPreMultiply.h" 201b5c604d9d344537941b11b136348edfc39f236chalcanary 217a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarybool image_compute_is_opaque(const SkImage* image) { 227a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary if (image->isOpaque()) { 237a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary return true; 247a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } 257a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary // keep output PDF small at cost of possible resource use. 267a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary SkBitmap bm; 274f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary // if image can not be read, treat as transparent. 284f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary return SkPDFUtils::ToBitmap(image, &bm) && SkBitmap::ComputeIsOpaque(bm); 297a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary} 307a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 311b5c604d9d344537941b11b136348edfc39f236chalcanary//////////////////////////////////////////////////////////////////////////////// 321b5c604d9d344537941b11b136348edfc39f236chalcanary 331b5c604d9d344537941b11b136348edfc39f236chalcanarystatic void pdf_stream_begin(SkWStream* stream) { 341b5c604d9d344537941b11b136348edfc39f236chalcanary static const char streamBegin[] = " stream\n"; 351b5c604d9d344537941b11b136348edfc39f236chalcanary stream->write(streamBegin, strlen(streamBegin)); 361b5c604d9d344537941b11b136348edfc39f236chalcanary} 371b5c604d9d344537941b11b136348edfc39f236chalcanary 381b5c604d9d344537941b11b136348edfc39f236chalcanarystatic void pdf_stream_end(SkWStream* stream) { 391b5c604d9d344537941b11b136348edfc39f236chalcanary static const char streamEnd[] = "\nendstream"; 401b5c604d9d344537941b11b136348edfc39f236chalcanary stream->write(streamEnd, strlen(streamEnd)); 411b5c604d9d344537941b11b136348edfc39f236chalcanary} 421b5c604d9d344537941b11b136348edfc39f236chalcanary 43db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary//////////////////////////////////////////////////////////////////////////////// 441b5c604d9d344537941b11b136348edfc39f236chalcanary 451b5c604d9d344537941b11b136348edfc39f236chalcanary// write a single byte to a stream n times. 461b5c604d9d344537941b11b136348edfc39f236chalcanarystatic void fill_stream(SkWStream* out, char value, size_t n) { 471b5c604d9d344537941b11b136348edfc39f236chalcanary char buffer[4096]; 481b5c604d9d344537941b11b136348edfc39f236chalcanary memset(buffer, value, sizeof(buffer)); 49db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (size_t i = 0; i < n / sizeof(buffer); ++i) { 50db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(buffer, sizeof(buffer)); 511b5c604d9d344537941b11b136348edfc39f236chalcanary } 52db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(buffer, n % sizeof(buffer)); 531b5c604d9d344537941b11b136348edfc39f236chalcanary} 541b5c604d9d344537941b11b136348edfc39f236chalcanary 55aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// TODO(reed@): Decide if these five functions belong in SkColorPriv.h 56aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic bool SkIsBGRA(SkColorType ct) { 57aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkASSERT(kBGRA_8888_SkColorType == ct || kRGBA_8888_SkColorType == ct); 58aa4ba90792a99eed96ac51006bd478d453a751c4halcanary return kBGRA_8888_SkColorType == ct; 59aa4ba90792a99eed96ac51006bd478d453a751c4halcanary} 60aa4ba90792a99eed96ac51006bd478d453a751c4halcanary 61aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// Interpret value as the given 4-byte SkColorType (BGRA_8888 or 62aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// RGBA_8888) and return the appropriate component. Each component 63aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// should be interpreted according to the associated SkAlphaType and 64aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// SkColorProfileType. 65aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetA32Component(uint32_t value, SkColorType ct) { 66aa4ba90792a99eed96ac51006bd478d453a751c4halcanary return (value >> (SkIsBGRA(ct) ? SK_BGRA_A32_SHIFT : SK_RGBA_A32_SHIFT)) & 0xFF; 67aa4ba90792a99eed96ac51006bd478d453a751c4halcanary} 68aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetR32Component(uint32_t value, SkColorType ct) { 69aa4ba90792a99eed96ac51006bd478d453a751c4halcanary return (value >> (SkIsBGRA(ct) ? SK_BGRA_R32_SHIFT : SK_RGBA_R32_SHIFT)) & 0xFF; 70aa4ba90792a99eed96ac51006bd478d453a751c4halcanary} 71aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetG32Component(uint32_t value, SkColorType ct) { 72aa4ba90792a99eed96ac51006bd478d453a751c4halcanary return (value >> (SkIsBGRA(ct) ? SK_BGRA_G32_SHIFT : SK_RGBA_G32_SHIFT)) & 0xFF; 73aa4ba90792a99eed96ac51006bd478d453a751c4halcanary} 74aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetB32Component(uint32_t value, SkColorType ct) { 75aa4ba90792a99eed96ac51006bd478d453a751c4halcanary return (value >> (SkIsBGRA(ct) ? SK_BGRA_B32_SHIFT : SK_RGBA_B32_SHIFT)) & 0xFF; 76aa4ba90792a99eed96ac51006bd478d453a751c4halcanary} 77aa4ba90792a99eed96ac51006bd478d453a751c4halcanary 78db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary// unpremultiply and extract R, G, B components. 79aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic void pmcolor_to_rgb24(uint32_t color, uint8_t* rgb, SkColorType ct) { 805b474d36238e38642add8d4b54cb9ac80935262bHal Canary SkPMColorAssert(color); 81aa4ba90792a99eed96ac51006bd478d453a751c4halcanary uint32_t s = SkUnPreMultiply::GetScale(SkGetA32Component(color, ct)); 82aa4ba90792a99eed96ac51006bd478d453a751c4halcanary rgb[0] = SkUnPreMultiply::ApplyScale(s, SkGetR32Component(color, ct)); 83aa4ba90792a99eed96ac51006bd478d453a751c4halcanary rgb[1] = SkUnPreMultiply::ApplyScale(s, SkGetG32Component(color, ct)); 84aa4ba90792a99eed96ac51006bd478d453a751c4halcanary rgb[2] = SkUnPreMultiply::ApplyScale(s, SkGetB32Component(color, ct)); 85db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary} 86db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 87db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary/* It is necessary to average the color component of transparent 88db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary pixels with their surrounding neighbors since the PDF renderer may 89db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary separately re-sample the alpha and color channels when the image is 90db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary not displayed at its native resolution. Since an alpha of zero 91db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary gives no information about the color component, the pathological 92db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case is a white image with sharp transparency bounds - the color 93db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary channel goes to black, and the should-be-transparent pixels are 94db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary rendered as grey because of the separate soft mask and color 95db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary resizing. e.g.: gm/bitmappremul.cpp */ 96db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void get_neighbor_avg_color(const SkBitmap& bm, 97db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int xOrig, 98db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int yOrig, 99aa4ba90792a99eed96ac51006bd478d453a751c4halcanary uint8_t rgb[3], 100aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkColorType ct) { 101db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary unsigned a = 0, r = 0, g = 0, b = 0; 102db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary // Clamp the range to the edge of the bitmap. 103db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int ymin = SkTMax(0, yOrig - 1); 104db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int ymax = SkTMin(yOrig + 1, bm.height() - 1); 105db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int xmin = SkTMax(0, xOrig - 1); 106db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary int xmax = SkTMin(xOrig + 1, bm.width() - 1); 107db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = ymin; y <= ymax; ++y) { 108aa4ba90792a99eed96ac51006bd478d453a751c4halcanary uint32_t* scanline = bm.getAddr32(0, y); 109db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int x = xmin; x <= xmax; ++x) { 110aa4ba90792a99eed96ac51006bd478d453a751c4halcanary uint32_t color = scanline[x]; 1115b474d36238e38642add8d4b54cb9ac80935262bHal Canary SkPMColorAssert(color); 112aa4ba90792a99eed96ac51006bd478d453a751c4halcanary a += SkGetA32Component(color, ct); 113aa4ba90792a99eed96ac51006bd478d453a751c4halcanary r += SkGetR32Component(color, ct); 114aa4ba90792a99eed96ac51006bd478d453a751c4halcanary g += SkGetG32Component(color, ct); 115aa4ba90792a99eed96ac51006bd478d453a751c4halcanary b += SkGetB32Component(color, ct); 1161b5c604d9d344537941b11b136348edfc39f236chalcanary } 1171b5c604d9d344537941b11b136348edfc39f236chalcanary } 118db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary if (a > 0) { 119db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary rgb[0] = SkToU8(255 * r / a); 120db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary rgb[1] = SkToU8(255 * g / a); 121db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary rgb[2] = SkToU8(255 * b / a); 1221b5c604d9d344537941b11b136348edfc39f236chalcanary } else { 123db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary rgb[0] = rgb[1] = rgb[2] = 0; 12486ad8d643624a55b02e529100bbe4e2940115fa1halcanary } 12586ad8d643624a55b02e529100bbe4e2940115fa1halcanary} 12686ad8d643624a55b02e529100bbe4e2940115fa1halcanary 127db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic size_t pixel_count(const SkBitmap& bm) { 128db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return SkToSizeT(bm.width()) * SkToSizeT(bm.height()); 129db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary} 130db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 1313f4671871fac8e5439440ce756d0666bc2a96f46Hal Canarystatic const SkBitmap& supported_colortype(const SkBitmap& input, SkBitmap* copy) { 1323f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary switch (input.colorType()) { 1333f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kUnknown_SkColorType: 1343f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary SkDEBUGFAIL("kUnknown_SkColorType"); 1353f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kAlpha_8_SkColorType: 1363f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kRGB_565_SkColorType: 1373f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kRGBA_8888_SkColorType: 1383f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kBGRA_8888_SkColorType: 1393f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kGray_8_SkColorType: 1403f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary return input; // supported 1413f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary default: 1423f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary // if other colortypes are introduced in the future, 1433f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary // they will hit this code. 1443f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary break; 145db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 1463f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary // Fallback for rarely used ARGB_4444 and ARGB_F16: do a wasteful tmp copy. 14768b8e3d50d0954eb5eeb7f625f06026c7fbd38c1Matt Sarett copy->allocPixels(input.info().makeColorType(kN32_SkColorType)); 14868b8e3d50d0954eb5eeb7f625f06026c7fbd38c1Matt Sarett SkAssertResult(input.readPixels(copy->info(), copy->getPixels(), copy->rowBytes(), 0, 0)); 149db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary copy->setImmutable(); 150db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return *copy; 151db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary} 152db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 153db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic size_t pdf_color_component_count(SkColorType ct) { 154db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary switch (ct) { 1553f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kUnknown_SkColorType: 1563f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary SkDEBUGFAIL("kUnknown_SkColorType"); 1573f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kAlpha_8_SkColorType: 1583f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary case kGray_8_SkColorType: 1593f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary return 1; 160db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kRGB_565_SkColorType: 161aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kRGBA_8888_SkColorType: 162aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kBGRA_8888_SkColorType: 1633f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary default: // converted to N32 164db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return 3; 165db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 166db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary} 167db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 168db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) { 169db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary if (!bitmap.getPixels()) { 170db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary size_t size = pixel_count(bitmap) * 171db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary pdf_color_component_count(bitmap.colorType()); 172db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary fill_stream(out, '\x00', size); 1731b5c604d9d344537941b11b136348edfc39f236chalcanary return; 1741b5c604d9d344537941b11b136348edfc39f236chalcanary } 175db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkBitmap copy; 1763f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary const SkBitmap& bm = supported_colortype(bitmap, ©); 177aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkColorType colorType = bm.colorType(); 1787b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary SkAlphaType alphaType = bm.alphaType(); 179aa4ba90792a99eed96ac51006bd478d453a751c4halcanary switch (colorType) { 180aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kRGBA_8888_SkColorType: 181aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kBGRA_8888_SkColorType: { 182aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkASSERT(3 == pdf_color_component_count(colorType)); 183db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); 184db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = 0; y < bm.height(); ++y) { 185aa4ba90792a99eed96ac51006bd478d453a751c4halcanary const uint32_t* src = bm.getAddr32(0, y); 186db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary uint8_t* dst = scanline.get(); 187db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int x = 0; x < bm.width(); ++x) { 1887b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary if (alphaType == kPremul_SkAlphaType) { 1897b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary uint32_t color = *src++; 1907b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary U8CPU alpha = SkGetA32Component(color, colorType); 1917b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary if (alpha != SK_AlphaTRANSPARENT) { 1927b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary pmcolor_to_rgb24(color, dst, colorType); 1937b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary } else { 1947b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary get_neighbor_avg_color(bm, x, y, dst, colorType); 1957b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary } 1967b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary dst += 3; 197db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } else { 1987b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary uint32_t color = *src++; 1997b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary *dst++ = SkGetR32Component(color, colorType); 2007b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary *dst++ = SkGetG32Component(color, colorType); 2017b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary *dst++ = SkGetB32Component(color, colorType); 202db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 203db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 204db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(scanline.get(), 3 * bm.width()); 2051b5c604d9d344537941b11b136348edfc39f236chalcanary } 206db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 2071b5c604d9d344537941b11b136348edfc39f236chalcanary } 208db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kRGB_565_SkColorType: { 209aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkASSERT(3 == pdf_color_component_count(colorType)); 210db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); 211db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = 0; y < bm.height(); ++y) { 212db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary const uint16_t* src = bm.getAddr16(0, y); 213db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary uint8_t* dst = scanline.get(); 214db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int x = 0; x < bm.width(); ++x) { 215db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary U16CPU color565 = *src++; 216db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary *dst++ = SkPacked16ToR32(color565); 217db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary *dst++ = SkPacked16ToG32(color565); 218db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary *dst++ = SkPacked16ToB32(color565); 219db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 220db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(scanline.get(), 3 * bm.width()); 221db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 222db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 223db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 224db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kAlpha_8_SkColorType: 225aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkASSERT(1 == pdf_color_component_count(colorType)); 226db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary fill_stream(out, '\x00', pixel_count(bm)); 227db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 228db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kGray_8_SkColorType: 229aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkASSERT(1 == pdf_color_component_count(colorType)); 230db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary // these two formats need no transformation to serialize. 231db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = 0; y < bm.height(); ++y) { 232db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(bm.getAddr8(0, y), bm.width()); 233db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 234db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 235db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kUnknown_SkColorType: 236db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kARGB_4444_SkColorType: 237db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary default: 238db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkDEBUGFAIL("unexpected color type"); 2391b5c604d9d344537941b11b136348edfc39f236chalcanary } 2401b5c604d9d344537941b11b136348edfc39f236chalcanary} 2411b5c604d9d344537941b11b136348edfc39f236chalcanary 242db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary//////////////////////////////////////////////////////////////////////////////// 243db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 244db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) { 245db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary if (!bitmap.getPixels()) { 246db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary fill_stream(out, '\xFF', pixel_count(bitmap)); 2471b5c604d9d344537941b11b136348edfc39f236chalcanary return; 2481b5c604d9d344537941b11b136348edfc39f236chalcanary } 249db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkBitmap copy; 2503f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary const SkBitmap& bm = supported_colortype(bitmap, ©); 251aa4ba90792a99eed96ac51006bd478d453a751c4halcanary SkColorType colorType = bm.colorType(); 252aa4ba90792a99eed96ac51006bd478d453a751c4halcanary switch (colorType) { 253aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kRGBA_8888_SkColorType: 254aa4ba90792a99eed96ac51006bd478d453a751c4halcanary case kBGRA_8888_SkColorType: { 255db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkAutoTMalloc<uint8_t> scanline(bm.width()); 256db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = 0; y < bm.height(); ++y) { 257db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary uint8_t* dst = scanline.get(); 258db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary const SkPMColor* src = bm.getAddr32(0, y); 259db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int x = 0; x < bm.width(); ++x) { 260aa4ba90792a99eed96ac51006bd478d453a751c4halcanary *dst++ = SkGetA32Component(*src++, colorType); 261db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 262db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(scanline.get(), bm.width()); 263db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 264db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 2651b5c604d9d344537941b11b136348edfc39f236chalcanary } 266db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kAlpha_8_SkColorType: 267db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary for (int y = 0; y < bm.height(); ++y) { 268db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary out->write(bm.getAddr8(0, y), bm.width()); 269db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 270db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 271db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kRGB_565_SkColorType: 272db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kGray_8_SkColorType: 273db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkDEBUGFAIL("color type has no alpha"); 274db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 275db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kARGB_4444_SkColorType: 276db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkDEBUGFAIL("4444 color type should have been converted to N32"); 277db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary return; 278db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary case kUnknown_SkColorType: 279db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary default: 280db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary SkDEBUGFAIL("unexpected color type"); 2811b5c604d9d344537941b11b136348edfc39f236chalcanary } 2821b5c604d9d344537941b11b136348edfc39f236chalcanary} 2831b5c604d9d344537941b11b136348edfc39f236chalcanary 2847a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarystatic void emit_image_xobject(SkWStream* stream, 2857a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary const SkImage* image, 2867a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary bool alpha, 2878103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary const sk_sp<SkPDFObject>& smask, 288530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary const SkPDFObjNumMap& objNumMap) { 2897a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary SkBitmap bitmap; 2904f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary if (!SkPDFUtils::ToBitmap(image, &bitmap)) { 2914f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary // no pixels or wrong size: fill with zeros. 2924f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary bitmap.setInfo(SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType())); 2934f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary } 29437c46cad21632cfc1411b08d73af37a1fffe2944halcanary 29537c46cad21632cfc1411b08d73af37a1fffe2944halcanary // Write to a temporary buffer to get the compressed length. 29637c46cad21632cfc1411b08d73af37a1fffe2944halcanary SkDynamicMemoryWStream buffer; 29737c46cad21632cfc1411b08d73af37a1fffe2944halcanary SkDeflateWStream deflateWStream(&buffer); 2987a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary if (alpha) { 2997a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary bitmap_alpha_to_a8(bitmap, &deflateWStream); 3007a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } else { 3017a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary bitmap_to_pdf_pixels(bitmap, &deflateWStream); 3027a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } 3036fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary deflateWStream.finalize(); // call before buffer.bytesWritten(). 30437c46cad21632cfc1411b08d73af37a1fffe2944halcanary 3051b5c604d9d344537941b11b136348edfc39f236chalcanary SkPDFDict pdfDict("XObject"); 3061b5c604d9d344537941b11b136348edfc39f236chalcanary pdfDict.insertName("Subtype", "Image"); 3077a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertInt("Width", bitmap.width()); 3087a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertInt("Height", bitmap.height()); 3097a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary if (alpha) { 3107a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertName("ColorSpace", "DeviceGray"); 3117a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } else if (1 == pdf_color_component_count(bitmap.colorType())) { 312db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary pdfDict.insertName("ColorSpace", "DeviceGray"); 313db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } else { 314db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary pdfDict.insertName("ColorSpace", "DeviceRGB"); 315db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary } 3167a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary if (smask) { 3178103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary pdfDict.insertObjRef("SMask", smask); 3181b5c604d9d344537941b11b136348edfc39f236chalcanary } 3197a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertInt("BitsPerComponent", 8); 320db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary pdfDict.insertName("Filter", "FlateDecode"); 3216fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary pdfDict.insertInt("Length", buffer.bytesWritten()); 322530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary pdfDict.emitObject(stream, objNumMap); 32337c46cad21632cfc1411b08d73af37a1fffe2944halcanary 32437c46cad21632cfc1411b08d73af37a1fffe2944halcanary pdf_stream_begin(stream); 3256fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary buffer.writeToAndReset(stream); 32637c46cad21632cfc1411b08d73af37a1fffe2944halcanary pdf_stream_end(stream); 3271b5c604d9d344537941b11b136348edfc39f236chalcanary} 3281b5c604d9d344537941b11b136348edfc39f236chalcanary 3291b5c604d9d344537941b11b136348edfc39f236chalcanary//////////////////////////////////////////////////////////////////////////////// 330db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary 3317a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarynamespace { 3327a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary// This SkPDFObject only outputs the alpha layer of the given bitmap. 33370d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFAlphaBitmap final : public SkPDFObject { 3347a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarypublic: 335a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary PDFAlphaBitmap(sk_sp<SkImage> image) : fImage(std::move(image)) { SkASSERT(fImage); } 3367a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary void emitObject(SkWStream* stream, 337530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary const SkPDFObjNumMap& objNumMap) const override { 338bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary SkASSERT(fImage); 339530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap); 3401b5c604d9d344537941b11b136348edfc39f236chalcanary } 341bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary void drop() override { fImage = nullptr; } 3427a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3437a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryprivate: 344a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary sk_sp<SkImage> fImage; 3457a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary}; 3467a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3477a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary} // namespace 3487a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3497a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary//////////////////////////////////////////////////////////////////////////////// 3507a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3517a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarynamespace { 35270d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFDefaultBitmap final : public SkPDFObject { 3537a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarypublic: 35434422610ac22adceeabb66023120f27b96cae953halcanary void emitObject(SkWStream* stream, 355530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary const SkPDFObjNumMap& objNumMap) const override { 356bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary SkASSERT(fImage); 357530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap); 3587a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } 359530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary void addResources(SkPDFObjNumMap* catalog) const override { 360530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary catalog->addObjectRecursively(fSMask.get()); 3617a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary } 362bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary void drop() override { fImage = nullptr; fSMask = nullptr; } 363a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary PDFDefaultBitmap(sk_sp<SkImage> image, sk_sp<SkPDFObject> smask) 364a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary : fImage(std::move(image)), fSMask(std::move(smask)) { SkASSERT(fImage); } 3657a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3667a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryprivate: 367a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary sk_sp<SkImage> fImage; 368bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary sk_sp<SkPDFObject> fSMask; 3697a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary}; 3707a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary} // namespace 3717a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary 3727a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary//////////////////////////////////////////////////////////////////////////////// 3731b5c604d9d344537941b11b136348edfc39f236chalcanary 374a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanarynamespace { 375a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary/** 3767a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary * This PDFObject assumes that its constructor was handed YUV or 3777a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary * Grayscale JFIF Jpeg-encoded data that can be directly embedded 3787a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary * into a PDF. 379a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary */ 38070d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFJpegBitmap final : public SkPDFObject { 381a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanarypublic: 3827a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary SkISize fSize; 38348810a023705ffac466adb93efdb3861cf2e197ahalcanary sk_sp<SkData> fData; 38496287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary bool fIsYUV; 3857a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary PDFJpegBitmap(SkISize size, SkData* data, bool isYUV) 386bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary : fSize(size), fData(SkRef(data)), fIsYUV(isYUV) { SkASSERT(data); } 387530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary void emitObject(SkWStream*, const SkPDFObjNumMap&) const override; 388bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary void drop() override { fData = nullptr; } 389a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary}; 390a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary 391a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanaryvoid PDFJpegBitmap::emitObject(SkWStream* stream, 392530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary const SkPDFObjNumMap& objNumMap) const { 393bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary SkASSERT(fData); 394a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary SkPDFDict pdfDict("XObject"); 395a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdfDict.insertName("Subtype", "Image"); 3967a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertInt("Width", fSize.width()); 3977a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary pdfDict.insertInt("Height", fSize.height()); 39896287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary if (fIsYUV) { 39996287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary pdfDict.insertName("ColorSpace", "DeviceRGB"); 40096287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary } else { 40196287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary pdfDict.insertName("ColorSpace", "DeviceGray"); 40296287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary } 403a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdfDict.insertInt("BitsPerComponent", 8); 404a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdfDict.insertName("Filter", "DCTDecode"); 405a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdfDict.insertInt("ColorTransform", 0); 406a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdfDict.insertInt("Length", SkToInt(fData->size())); 407530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary pdfDict.emitObject(stream, objNumMap); 408a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdf_stream_begin(stream); 409a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary stream->write(fData->data(), fData->size()); 410a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary pdf_stream_end(stream); 411a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary} 412a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary} // namespace 413a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary 414a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary//////////////////////////////////////////////////////////////////////////////// 415a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary 416a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanarysk_sp<SkPDFObject> SkPDFCreateBitmapObject(sk_sp<SkImage> image, 417a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary SkPixelSerializer* pixelSerializer) { 418a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary SkASSERT(image); 4196409f84fc3ae5e3b2df9eb0a900957fce404ad5cMike Reed sk_sp<SkData> data = image->refEncodedData(); 4207a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary SkJFIFInfo info; 421fcad44bbb1e0384620e7b738a0f5904c940a6861halcanary if (data && SkIsJFIF(data.get(), &info) && 4227363e13a07f8b6a9d4ba82ff7b13526f0a89eaeehalcanary (!pixelSerializer || 4237363e13a07f8b6a9d4ba82ff7b13526f0a89eaeehalcanary pixelSerializer->useEncodedData(data->data(), data->size()))) { 4247363e13a07f8b6a9d4ba82ff7b13526f0a89eaeehalcanary // If there is a SkPixelSerializer, give it a chance to 4257363e13a07f8b6a9d4ba82ff7b13526f0a89eaeehalcanary // re-encode the JPEG with more compression by returning false 4267363e13a07f8b6a9d4ba82ff7b13526f0a89eaeehalcanary // from useEncodedData. 4277a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary bool yuv = info.fType == SkJFIFInfo::kYCbCr; 4287a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary if (info.fSize == image->dimensions()) { // Sanity check. 4297a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary // hold on to data, not image. 4307a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary #ifdef SK_PDF_IMAGE_STATS 4317a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary gJpegImageObjects.fetch_add(1); 4327a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary #endif 433a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv); 434a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary } 435a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary } 436712fdf7603c62820b21174da9b0a2071c174936bhalcanary 437712fdf7603c62820b21174da9b0a2071c174936bhalcanary if (pixelSerializer) { 438712fdf7603c62820b21174da9b0a2071c174936bhalcanary SkBitmap bm; 4394edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed SkPixmap pmap; 4404f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary if (SkPDFUtils::ToBitmap(image.get(), &bm) && bm.peekPixels(&pmap)) { 4416409f84fc3ae5e3b2df9eb0a900957fce404ad5cMike Reed data = pixelSerializer->encodeToData(pmap); 442fcad44bbb1e0384620e7b738a0f5904c940a6861halcanary if (data && SkIsJFIF(data.get(), &info)) { 443712fdf7603c62820b21174da9b0a2071c174936bhalcanary bool yuv = info.fType == SkJFIFInfo::kYCbCr; 444712fdf7603c62820b21174da9b0a2071c174936bhalcanary if (info.fSize == image->dimensions()) { // Sanity check. 445a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv); 446712fdf7603c62820b21174da9b0a2071c174936bhalcanary } 447712fdf7603c62820b21174da9b0a2071c174936bhalcanary } 448712fdf7603c62820b21174da9b0a2071c174936bhalcanary } 449712fdf7603c62820b21174da9b0a2071c174936bhalcanary } 450712fdf7603c62820b21174da9b0a2071c174936bhalcanary 451a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary sk_sp<SkPDFObject> smask; 452a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary if (!image_compute_is_opaque(image.get())) { 453a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary smask = sk_make_sp<PDFAlphaBitmap>(image); 454a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary } 4557a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary #ifdef SK_PDF_IMAGE_STATS 4567a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary gRegularImageObjects.fetch_add(1); 4577a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary #endif 458a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary return sk_make_sp<PDFDefaultBitmap>(std::move(image), std::move(smask)); 4591b5c604d9d344537941b11b136348edfc39f236chalcanary} 460