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
10a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.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
33c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canarystatic const char kStreamBegin[] = " stream\n";
341b5c604d9d344537941b11b136348edfc39f236chalcanary
35c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canarystatic const char kStreamEnd[] = "\nendstream";
361b5c604d9d344537941b11b136348edfc39f236chalcanary
37db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary////////////////////////////////////////////////////////////////////////////////
381b5c604d9d344537941b11b136348edfc39f236chalcanary
391b5c604d9d344537941b11b136348edfc39f236chalcanary// write a single byte to a stream n times.
401b5c604d9d344537941b11b136348edfc39f236chalcanarystatic void fill_stream(SkWStream* out, char value, size_t n) {
411b5c604d9d344537941b11b136348edfc39f236chalcanary    char buffer[4096];
421b5c604d9d344537941b11b136348edfc39f236chalcanary    memset(buffer, value, sizeof(buffer));
43db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    for (size_t i = 0; i < n / sizeof(buffer); ++i) {
44db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        out->write(buffer, sizeof(buffer));
451b5c604d9d344537941b11b136348edfc39f236chalcanary    }
46db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    out->write(buffer, n % sizeof(buffer));
471b5c604d9d344537941b11b136348edfc39f236chalcanary}
481b5c604d9d344537941b11b136348edfc39f236chalcanary
49a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark// TODO(reed@): Decide if these five functions belong in SkColorData.h
50aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic bool SkIsBGRA(SkColorType ct) {
51aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    SkASSERT(kBGRA_8888_SkColorType == ct || kRGBA_8888_SkColorType == ct);
52aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    return kBGRA_8888_SkColorType == ct;
53aa4ba90792a99eed96ac51006bd478d453a751c4halcanary}
54aa4ba90792a99eed96ac51006bd478d453a751c4halcanary
55aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// Interpret value as the given 4-byte SkColorType (BGRA_8888 or
56aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// RGBA_8888) and return the appropriate component.  Each component
57aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// should be interpreted according to the associated SkAlphaType and
58aa4ba90792a99eed96ac51006bd478d453a751c4halcanary// SkColorProfileType.
59aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetA32Component(uint32_t value, SkColorType ct) {
60aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    return (value >> (SkIsBGRA(ct) ? SK_BGRA_A32_SHIFT : SK_RGBA_A32_SHIFT)) & 0xFF;
61aa4ba90792a99eed96ac51006bd478d453a751c4halcanary}
62aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetR32Component(uint32_t value, SkColorType ct) {
63aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    return (value >> (SkIsBGRA(ct) ? SK_BGRA_R32_SHIFT : SK_RGBA_R32_SHIFT)) & 0xFF;
64aa4ba90792a99eed96ac51006bd478d453a751c4halcanary}
65aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetG32Component(uint32_t value, SkColorType ct) {
66aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    return (value >> (SkIsBGRA(ct) ? SK_BGRA_G32_SHIFT : SK_RGBA_G32_SHIFT)) & 0xFF;
67aa4ba90792a99eed96ac51006bd478d453a751c4halcanary}
68aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic U8CPU SkGetB32Component(uint32_t value, SkColorType ct) {
69aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    return (value >> (SkIsBGRA(ct) ? SK_BGRA_B32_SHIFT : SK_RGBA_B32_SHIFT)) & 0xFF;
70aa4ba90792a99eed96ac51006bd478d453a751c4halcanary}
71aa4ba90792a99eed96ac51006bd478d453a751c4halcanary
72db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary// unpremultiply and extract R, G, B components.
73aa4ba90792a99eed96ac51006bd478d453a751c4halcanarystatic void pmcolor_to_rgb24(uint32_t color, uint8_t* rgb, SkColorType ct) {
745b474d36238e38642add8d4b54cb9ac80935262bHal Canary    SkPMColorAssert(color);
75aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    uint32_t s = SkUnPreMultiply::GetScale(SkGetA32Component(color, ct));
76aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    rgb[0] = SkUnPreMultiply::ApplyScale(s, SkGetR32Component(color, ct));
77aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    rgb[1] = SkUnPreMultiply::ApplyScale(s, SkGetG32Component(color, ct));
78aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    rgb[2] = SkUnPreMultiply::ApplyScale(s, SkGetB32Component(color, ct));
79db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary}
80db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
81db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary/* It is necessary to average the color component of transparent
82db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   pixels with their surrounding neighbors since the PDF renderer may
83db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   separately re-sample the alpha and color channels when the image is
84db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   not displayed at its native resolution. Since an alpha of zero
85db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   gives no information about the color component, the pathological
86db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   case is a white image with sharp transparency bounds - the color
87db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   channel goes to black, and the should-be-transparent pixels are
88db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   rendered as grey because of the separate soft mask and color
89db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary   resizing. e.g.: gm/bitmappremul.cpp */
90db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void get_neighbor_avg_color(const SkBitmap& bm,
91db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                                   int xOrig,
92db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                                   int yOrig,
93aa4ba90792a99eed96ac51006bd478d453a751c4halcanary                                   uint8_t rgb[3],
94aa4ba90792a99eed96ac51006bd478d453a751c4halcanary                                   SkColorType ct) {
95db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    unsigned a = 0, r = 0, g = 0, b = 0;
96db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    // Clamp the range to the edge of the bitmap.
97db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    int ymin = SkTMax(0, yOrig - 1);
98db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    int ymax = SkTMin(yOrig + 1, bm.height() - 1);
99db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    int xmin = SkTMax(0, xOrig - 1);
100db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    int xmax = SkTMin(xOrig + 1, bm.width() - 1);
101db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    for (int y = ymin; y <= ymax; ++y) {
102aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        uint32_t* scanline = bm.getAddr32(0, y);
103db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        for (int x = xmin; x <= xmax; ++x) {
104aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            uint32_t color = scanline[x];
1055b474d36238e38642add8d4b54cb9ac80935262bHal Canary            SkPMColorAssert(color);
106aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            a += SkGetA32Component(color, ct);
107aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            r += SkGetR32Component(color, ct);
108aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            g += SkGetG32Component(color, ct);
109aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            b += SkGetB32Component(color, ct);
1101b5c604d9d344537941b11b136348edfc39f236chalcanary        }
1111b5c604d9d344537941b11b136348edfc39f236chalcanary    }
112db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    if (a > 0) {
113db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        rgb[0] = SkToU8(255 * r / a);
114db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        rgb[1] = SkToU8(255 * g / a);
115db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        rgb[2] = SkToU8(255 * b / a);
1161b5c604d9d344537941b11b136348edfc39f236chalcanary    } else {
117db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        rgb[0] = rgb[1] = rgb[2] = 0;
11886ad8d643624a55b02e529100bbe4e2940115fa1halcanary    }
11986ad8d643624a55b02e529100bbe4e2940115fa1halcanary}
12086ad8d643624a55b02e529100bbe4e2940115fa1halcanary
121db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic size_t pixel_count(const SkBitmap& bm) {
122db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    return SkToSizeT(bm.width()) * SkToSizeT(bm.height());
123db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary}
124db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
1253f4671871fac8e5439440ce756d0666bc2a96f46Hal Canarystatic const SkBitmap& supported_colortype(const SkBitmap& input, SkBitmap* copy) {
1263f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary    switch (input.colorType()) {
1273f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kUnknown_SkColorType:
1283f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            SkDEBUGFAIL("kUnknown_SkColorType");
1293f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kAlpha_8_SkColorType:
1303f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kRGB_565_SkColorType:
1313f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kRGBA_8888_SkColorType:
1323f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kBGRA_8888_SkColorType:
1333f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kGray_8_SkColorType:
1343f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            return input;  // supported
1353f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        default:
1363f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            // if other colortypes are introduced in the future,
1373f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            // they will hit this code.
1383f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            break;
139db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    }
1403f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary    // Fallback for rarely used ARGB_4444 and ARGB_F16: do a wasteful tmp copy.
14168b8e3d50d0954eb5eeb7f625f06026c7fbd38c1Matt Sarett    copy->allocPixels(input.info().makeColorType(kN32_SkColorType));
14268b8e3d50d0954eb5eeb7f625f06026c7fbd38c1Matt Sarett    SkAssertResult(input.readPixels(copy->info(), copy->getPixels(), copy->rowBytes(), 0, 0));
143db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    copy->setImmutable();
144db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    return *copy;
145db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary}
146db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
147db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic size_t pdf_color_component_count(SkColorType ct) {
148db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    switch (ct) {
1493f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kUnknown_SkColorType:
1503f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            SkDEBUGFAIL("kUnknown_SkColorType");
1513f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kAlpha_8_SkColorType:
1523f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        case kGray_8_SkColorType:
1533f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary            return 1;
154db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kRGB_565_SkColorType:
155aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kRGBA_8888_SkColorType:
156aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kBGRA_8888_SkColorType:
1573f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary        default:  // converted to N32
158db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return 3;
159db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    }
160db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary}
161db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
162db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) {
163db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    if (!bitmap.getPixels()) {
164db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        size_t size = pixel_count(bitmap) *
165db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                      pdf_color_component_count(bitmap.colorType());
166db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        fill_stream(out, '\x00', size);
1671b5c604d9d344537941b11b136348edfc39f236chalcanary        return;
1681b5c604d9d344537941b11b136348edfc39f236chalcanary    }
169db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    SkBitmap copy;
1703f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary    const SkBitmap& bm = supported_colortype(bitmap, &copy);
171aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    SkColorType colorType = bm.colorType();
1727b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary    SkAlphaType alphaType = bm.alphaType();
173aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    switch (colorType) {
174aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kRGBA_8888_SkColorType:
175aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kBGRA_8888_SkColorType: {
176aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            SkASSERT(3 == pdf_color_component_count(colorType));
177db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkAutoTMalloc<uint8_t> scanline(3 * bm.width());
178db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            for (int y = 0; y < bm.height(); ++y) {
179aa4ba90792a99eed96ac51006bd478d453a751c4halcanary                const uint32_t* src = bm.getAddr32(0, y);
180db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                uint8_t* dst = scanline.get();
181db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                for (int x = 0; x < bm.width(); ++x) {
1827b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                    if (alphaType == kPremul_SkAlphaType) {
1837b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        uint32_t color = *src++;
1847b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        U8CPU alpha = SkGetA32Component(color, colorType);
1857b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        if (alpha != SK_AlphaTRANSPARENT) {
1867b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                            pmcolor_to_rgb24(color, dst, colorType);
1877b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        } else {
1887b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                            get_neighbor_avg_color(bm, x, y, dst, colorType);
1897b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        }
1907b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        dst += 3;
191db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    } else {
1927b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        uint32_t color = *src++;
1937b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        *dst++ = SkGetR32Component(color, colorType);
1947b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        *dst++ = SkGetG32Component(color, colorType);
1957b9eabb392902e6e8f4206ba8aa041524258fd0fhalcanary                        *dst++ = SkGetB32Component(color, colorType);
196db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    }
197db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                }
198db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                out->write(scanline.get(), 3 * bm.width());
1991b5c604d9d344537941b11b136348edfc39f236chalcanary            }
200db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
2011b5c604d9d344537941b11b136348edfc39f236chalcanary        }
202db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kRGB_565_SkColorType: {
203aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            SkASSERT(3 == pdf_color_component_count(colorType));
204db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkAutoTMalloc<uint8_t> scanline(3 * bm.width());
205db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            for (int y = 0; y < bm.height(); ++y) {
206db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                const uint16_t* src = bm.getAddr16(0, y);
207db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                uint8_t* dst = scanline.get();
208db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                for (int x = 0; x < bm.width(); ++x) {
209db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    U16CPU color565 = *src++;
210db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    *dst++ = SkPacked16ToR32(color565);
211db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    *dst++ = SkPacked16ToG32(color565);
212db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                    *dst++ = SkPacked16ToB32(color565);
213db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                }
214db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                out->write(scanline.get(), 3 * bm.width());
215db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            }
216db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
217db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        }
218db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kAlpha_8_SkColorType:
219aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            SkASSERT(1 == pdf_color_component_count(colorType));
220db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            fill_stream(out, '\x00', pixel_count(bm));
221db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
222db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kGray_8_SkColorType:
223aa4ba90792a99eed96ac51006bd478d453a751c4halcanary            SkASSERT(1 == pdf_color_component_count(colorType));
224db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            // these two formats need no transformation to serialize.
225db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            for (int y = 0; y < bm.height(); ++y) {
226db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                out->write(bm.getAddr8(0, y), bm.width());
227db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            }
228db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
229db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kUnknown_SkColorType:
230db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kARGB_4444_SkColorType:
231db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        default:
232db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkDEBUGFAIL("unexpected color type");
2331b5c604d9d344537941b11b136348edfc39f236chalcanary    }
2341b5c604d9d344537941b11b136348edfc39f236chalcanary}
2351b5c604d9d344537941b11b136348edfc39f236chalcanary
236db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary////////////////////////////////////////////////////////////////////////////////
237db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
238db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanarystatic void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) {
239db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    if (!bitmap.getPixels()) {
240db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        fill_stream(out, '\xFF', pixel_count(bitmap));
2411b5c604d9d344537941b11b136348edfc39f236chalcanary        return;
2421b5c604d9d344537941b11b136348edfc39f236chalcanary    }
243db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    SkBitmap copy;
2443f4671871fac8e5439440ce756d0666bc2a96f46Hal Canary    const SkBitmap& bm = supported_colortype(bitmap, &copy);
245aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    SkColorType colorType = bm.colorType();
246aa4ba90792a99eed96ac51006bd478d453a751c4halcanary    switch (colorType) {
247aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kRGBA_8888_SkColorType:
248aa4ba90792a99eed96ac51006bd478d453a751c4halcanary        case kBGRA_8888_SkColorType: {
249db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkAutoTMalloc<uint8_t> scanline(bm.width());
250db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            for (int y = 0; y < bm.height(); ++y) {
251db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                uint8_t* dst = scanline.get();
252db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                const SkPMColor* src = bm.getAddr32(0, y);
253db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                for (int x = 0; x < bm.width(); ++x) {
254aa4ba90792a99eed96ac51006bd478d453a751c4halcanary                    *dst++ = SkGetA32Component(*src++, colorType);
255db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                }
256db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                out->write(scanline.get(), bm.width());
257db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            }
258db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
2591b5c604d9d344537941b11b136348edfc39f236chalcanary        }
260db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kAlpha_8_SkColorType:
261db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            for (int y = 0; y < bm.height(); ++y) {
262db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary                out->write(bm.getAddr8(0, y), bm.width());
263db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            }
264db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
265db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kRGB_565_SkColorType:
266db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kGray_8_SkColorType:
267db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkDEBUGFAIL("color type has no alpha");
268db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
269db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kARGB_4444_SkColorType:
270db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkDEBUGFAIL("4444 color type should have been converted to N32");
271db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            return;
272db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        case kUnknown_SkColorType:
273db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        default:
274db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary            SkDEBUGFAIL("unexpected color type");
2751b5c604d9d344537941b11b136348edfc39f236chalcanary    }
2761b5c604d9d344537941b11b136348edfc39f236chalcanary}
2771b5c604d9d344537941b11b136348edfc39f236chalcanary
2787a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarystatic void emit_image_xobject(SkWStream* stream,
2797a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                               const SkImage* image,
2807a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary                               bool alpha,
2818103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary                               const sk_sp<SkPDFObject>& smask,
282530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary                               const SkPDFObjNumMap& objNumMap) {
2837a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkBitmap bitmap;
2844f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary    if (!SkPDFUtils::ToBitmap(image, &bitmap)) {
2854f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary        // no pixels or wrong size: fill with zeros.
2864f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary        bitmap.setInfo(SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType()));
2874f29c20f20ce62150998786be8b9f8a81a901d72Hal Canary    }
28837c46cad21632cfc1411b08d73af37a1fffe2944halcanary
28937c46cad21632cfc1411b08d73af37a1fffe2944halcanary    // Write to a temporary buffer to get the compressed length.
29037c46cad21632cfc1411b08d73af37a1fffe2944halcanary    SkDynamicMemoryWStream buffer;
29137c46cad21632cfc1411b08d73af37a1fffe2944halcanary    SkDeflateWStream deflateWStream(&buffer);
2927a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    if (alpha) {
2937a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        bitmap_alpha_to_a8(bitmap, &deflateWStream);
2947a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    } else {
2957a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        bitmap_to_pdf_pixels(bitmap, &deflateWStream);
2967a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    }
2976fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary    deflateWStream.finalize();  // call before buffer.bytesWritten().
29837c46cad21632cfc1411b08d73af37a1fffe2944halcanary
2991b5c604d9d344537941b11b136348edfc39f236chalcanary    SkPDFDict pdfDict("XObject");
3001b5c604d9d344537941b11b136348edfc39f236chalcanary    pdfDict.insertName("Subtype", "Image");
3017a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    pdfDict.insertInt("Width", bitmap.width());
3027a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    pdfDict.insertInt("Height", bitmap.height());
3037a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    if (alpha) {
3047a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        pdfDict.insertName("ColorSpace", "DeviceGray");
3057a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    } else if (1 == pdf_color_component_count(bitmap.colorType())) {
306db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        pdfDict.insertName("ColorSpace", "DeviceGray");
307db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    } else {
308db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary        pdfDict.insertName("ColorSpace", "DeviceRGB");
309db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    }
3107a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    if (smask) {
3118103a34300c5de2e85793a96c4738a33fc6eb46dhalcanary        pdfDict.insertObjRef("SMask", smask);
3121b5c604d9d344537941b11b136348edfc39f236chalcanary    }
3137a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    pdfDict.insertInt("BitsPerComponent", 8);
314db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary    pdfDict.insertName("Filter", "FlateDecode");
3156fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary    pdfDict.insertInt("Length", buffer.bytesWritten());
316530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary    pdfDict.emitObject(stream, objNumMap);
31737c46cad21632cfc1411b08d73af37a1fffe2944halcanary
318c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canary    stream->writeText(kStreamBegin);
3196fee59b514c5f7b7ff34d63b294759dd0c1d4858Hal Canary    buffer.writeToAndReset(stream);
320c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canary    stream->writeText(kStreamEnd);
3211b5c604d9d344537941b11b136348edfc39f236chalcanary}
3221b5c604d9d344537941b11b136348edfc39f236chalcanary
3231b5c604d9d344537941b11b136348edfc39f236chalcanary////////////////////////////////////////////////////////////////////////////////
324db0dcc7436375e5d59c27f9011f09b64de407c9dhalcanary
3257a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarynamespace {
3267a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary// This SkPDFObject only outputs the alpha layer of the given bitmap.
32770d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFAlphaBitmap final : public SkPDFObject {
3287a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarypublic:
329a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    PDFAlphaBitmap(sk_sp<SkImage> image) : fImage(std::move(image)) { SkASSERT(fImage); }
3307a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    void emitObject(SkWStream*  stream,
331530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary                    const SkPDFObjNumMap& objNumMap) const override {
332bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary        SkASSERT(fImage);
333530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary        emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap);
3341b5c604d9d344537941b11b136348edfc39f236chalcanary    }
335bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary    void drop() override { fImage = nullptr; }
3367a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3377a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryprivate:
338a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    sk_sp<SkImage> fImage;
3397a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary};
3407a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3417a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary}  // namespace
3427a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3437a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary////////////////////////////////////////////////////////////////////////////////
3447a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3457a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarynamespace {
34670d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFDefaultBitmap final : public SkPDFObject {
3477a14b310d6c618fa2151d93a43b29f9599adc32ahalcanarypublic:
34834422610ac22adceeabb66023120f27b96cae953halcanary    void emitObject(SkWStream* stream,
349530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary                    const SkPDFObjNumMap& objNumMap) const override {
350bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary        SkASSERT(fImage);
351530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary        emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap);
3527a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    }
353530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary    void addResources(SkPDFObjNumMap* catalog) const override {
354530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary        catalog->addObjectRecursively(fSMask.get());
3557a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    }
356bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary    void drop() override { fImage = nullptr; fSMask = nullptr; }
357a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    PDFDefaultBitmap(sk_sp<SkImage> image, sk_sp<SkPDFObject> smask)
358a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary        : fImage(std::move(image)), fSMask(std::move(smask)) { SkASSERT(fImage); }
3597a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3607a14b310d6c618fa2151d93a43b29f9599adc32ahalcanaryprivate:
361a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    sk_sp<SkImage> fImage;
362bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary    sk_sp<SkPDFObject> fSMask;
3637a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary};
3647a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary}  // namespace
3657a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary
3667a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary////////////////////////////////////////////////////////////////////////////////
3671b5c604d9d344537941b11b136348edfc39f236chalcanary
368a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanarynamespace {
369a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary/**
3707a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary *  This PDFObject assumes that its constructor was handed YUV or
3717a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary *  Grayscale JFIF Jpeg-encoded data that can be directly embedded
3727a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary *  into a PDF.
373a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary */
37470d1554d8ea08ddb887550f98b9cfd0afd395d65halcanaryclass PDFJpegBitmap final : public SkPDFObject {
375a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanarypublic:
3767a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkISize fSize;
37748810a023705ffac466adb93efdb3861cf2e197ahalcanary    sk_sp<SkData> fData;
37896287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary    bool fIsYUV;
3797a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    PDFJpegBitmap(SkISize size, SkData* data, bool isYUV)
380bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary        : fSize(size), fData(SkRef(data)), fIsYUV(isYUV) { SkASSERT(data); }
381530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary    void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
382bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary    void drop() override { fData = nullptr; }
383a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary};
384a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary
385a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanaryvoid PDFJpegBitmap::emitObject(SkWStream* stream,
386530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary                               const SkPDFObjNumMap& objNumMap) const {
387bae235eb07cdfeb6dd92efa2b2143fa9e91d9d04halcanary    SkASSERT(fData);
388a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    SkPDFDict pdfDict("XObject");
389a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    pdfDict.insertName("Subtype", "Image");
3907a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    pdfDict.insertInt("Width", fSize.width());
3917a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    pdfDict.insertInt("Height", fSize.height());
39296287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary    if (fIsYUV) {
39396287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary        pdfDict.insertName("ColorSpace", "DeviceRGB");
39496287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary    } else {
39596287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary        pdfDict.insertName("ColorSpace", "DeviceGray");
39696287f7af7ff6aaa48b8d28ec6b7b79836da2d7chalcanary    }
397a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    pdfDict.insertInt("BitsPerComponent", 8);
398a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    pdfDict.insertName("Filter", "DCTDecode");
399a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    pdfDict.insertInt("ColorTransform", 0);
400a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    pdfDict.insertInt("Length", SkToInt(fData->size()));
401530032a18e373ee673ae96fdbfa1fae6292f8f08halcanary    pdfDict.emitObject(stream, objNumMap);
402c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canary    stream->writeText(kStreamBegin);
403a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    stream->write(fData->data(), fData->size());
404c172f9b894455f2d262a5b1edf067764d70b1b62Hal Canary    stream->writeText(kStreamEnd);
405a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary}
406a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary}  // namespace
407a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary
408a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary////////////////////////////////////////////////////////////////////////////////
409a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary
4102e3f2e9b484a7e139bb221db4f7ec9edadeb4416Mike Reedsk_sp<SkPDFObject> SkPDFCreateBitmapObject(sk_sp<SkImage> image, int encodingQuality) {
411a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    SkASSERT(image);
412a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    SkASSERT(encodingQuality >= 0);
4136409f84fc3ae5e3b2df9eb0a900957fce404ad5cMike Reed    sk_sp<SkData> data = image->refEncodedData();
4147a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    SkJFIFInfo info;
415a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    if (data && SkIsJFIF(data.get(), &info)) {
4167a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        bool yuv = info.fType == SkJFIFInfo::kYCbCr;
4177a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary        if (info.fSize == image->dimensions()) {  // Sanity check.
4187a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary            // hold on to data, not image.
4197a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary            #ifdef SK_PDF_IMAGE_STATS
4207a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary            gJpegImageObjects.fetch_add(1);
4217a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary            #endif
422a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary            return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv);
423a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary        }
424a8448bc3dfe0f2e768838b4416fb3ebf823b694ehalcanary    }
425712fdf7603c62820b21174da9b0a2071c174936bhalcanary
426a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    const bool isOpaque = image_compute_is_opaque(image.get());
427a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed
428a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    if (encodingQuality <= 100 && isOpaque) {
429a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed        data = image->encodeToData(SkEncodedImageFormat::kJPEG, encodingQuality);
430a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed        if (data && SkIsJFIF(data.get(), &info)) {
431a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed            bool yuv = info.fType == SkJFIFInfo::kYCbCr;
432a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed            if (info.fSize == image->dimensions()) {  // Sanity check.
433a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed                return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv);
434a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed            }
435a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed        }
436a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    }
437712fdf7603c62820b21174da9b0a2071c174936bhalcanary
438a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    sk_sp<SkPDFObject> smask;
439a4daf193196c6da63b1c16e3490cad3c5ca6bf8bMike Reed    if (!isOpaque) {
440a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary        smask = sk_make_sp<PDFAlphaBitmap>(image);
441a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    }
4427a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    #ifdef SK_PDF_IMAGE_STATS
4437a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    gRegularImageObjects.fetch_add(1);
4447a14b310d6c618fa2151d93a43b29f9599adc32ahalcanary    #endif
445a50151dcb5a0b8bfdef383e363e519c91d2d2c7ahalcanary    return sk_make_sp<PDFDefaultBitmap>(std::move(image), std::move(smask));
4461b5c604d9d344537941b11b136348edfc39f236chalcanary}
447