1/*
2 * Copyright 2007 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "SkImageDecoder.h"
10#include "SkImageEncoder.h"
11#include "SkJpegUtility.h"
12#include "SkColorPriv.h"
13#include "SkDither.h"
14#include "SkMSAN.h"
15#include "SkScaledBitmapSampler.h"
16#include "SkStream.h"
17#include "SkTemplates.h"
18#include "SkTime.h"
19#include "SkUtils.h"
20#include "SkRTConf.h"
21#include "SkRect.h"
22#include "SkCanvas.h"
23
24
25#include <stdio.h>
26extern "C" {
27    #include "jpeglib.h"
28    #include "jerror.h"
29}
30
31// These enable timing code that report milliseconds for an encoding/decoding
32//#define TIME_ENCODE
33//#define TIME_DECODE
34
35// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
36// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
37
38#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
39#define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
40SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
41                "images.jpeg.suppressDecoderWarnings",
42                DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
43                "Suppress most JPG warnings when calling decode functions.");
44SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
45                "images.jpeg.suppressDecoderErrors",
46                DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
47                "Suppress most JPG error messages when decode "
48                "function fails.");
49
50//////////////////////////////////////////////////////////////////////////
51//////////////////////////////////////////////////////////////////////////
52
53static void do_nothing_emit_message(jpeg_common_struct*, int) {
54    /* do nothing */
55}
56static void do_nothing_output_message(j_common_ptr) {
57    /* do nothing */
58}
59
60static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) {
61    SkASSERT(cinfo != nullptr);
62    SkASSERT(src_mgr != nullptr);
63    jpeg_create_decompress(cinfo);
64    cinfo->src = src_mgr;
65    /* To suppress warnings with a SK_DEBUG binary, set the
66     * environment variable "skia_images_jpeg_suppressDecoderWarnings"
67     * to "true".  Inside a program that links to skia:
68     * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
69    if (c_suppressJPEGImageDecoderWarnings) {
70        cinfo->err->emit_message = &do_nothing_emit_message;
71    }
72    /* To suppress error messages with a SK_DEBUG binary, set the
73     * environment variable "skia_images_jpeg_suppressDecoderErrors"
74     * to "true".  Inside a program that links to skia:
75     * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
76    if (c_suppressJPEGImageDecoderErrors) {
77        cinfo->err->output_message = &do_nothing_output_message;
78    }
79}
80
81class SkJPEGImageDecoder : public SkImageDecoder {
82public:
83
84    Format getFormat() const override {
85        return kJPEG_Format;
86    }
87
88protected:
89    Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
90    bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
91                            void* planes[3], size_t rowBytes[3],
92                            SkYUVColorSpace* colorSpace) override;
93
94private:
95
96    /**
97     *  Determine the appropriate bitmap colortype and out_color_space based on
98     *  both the preference of the caller and the jpeg_color_space on the
99     *  jpeg_decompress_struct passed in.
100     *  Must be called after jpeg_read_header.
101     */
102    SkColorType getBitmapColorType(jpeg_decompress_struct*);
103
104    typedef SkImageDecoder INHERITED;
105};
106
107//////////////////////////////////////////////////////////////////////////
108
109/* Automatically clean up after throwing an exception */
110class JPEGAutoClean {
111public:
112    JPEGAutoClean(): cinfo_ptr(nullptr) {}
113    ~JPEGAutoClean() {
114        if (cinfo_ptr) {
115            jpeg_destroy_decompress(cinfo_ptr);
116        }
117    }
118    void set(jpeg_decompress_struct* info) {
119        cinfo_ptr = info;
120    }
121private:
122    jpeg_decompress_struct* cinfo_ptr;
123};
124
125///////////////////////////////////////////////////////////////////////////////
126
127/*  If we need to better match the request, we might examine the image and
128     output dimensions, and determine if the downsampling jpeg provided is
129     not sufficient. If so, we can recompute a modified sampleSize value to
130     make up the difference.
131
132     To skip this additional scaling, just set sampleSize = 1; below.
133 */
134static int recompute_sampleSize(int sampleSize,
135                                const jpeg_decompress_struct& cinfo) {
136    return sampleSize * cinfo.output_width / cinfo.image_width;
137}
138
139static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
140    /* These are initialized to 0, so if they have non-zero values, we assume
141       they are "valid" (i.e. have been computed by libjpeg)
142     */
143    return 0 != cinfo.output_width && 0 != cinfo.output_height;
144}
145
146static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
147    for (int i = 0; i < count; i++) {
148        JSAMPLE* rowptr = (JSAMPLE*)buffer;
149        int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
150        if (1 != row_count) {
151            return false;
152        }
153    }
154    return true;
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
159// This guy exists just to aid in debugging, as it allows debuggers to just
160// set a break-point in one place to see all error exists.
161static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
162                         int width, int height, const char caller[]) {
163    if (!(c_suppressJPEGImageDecoderErrors)) {
164        char buffer[JMSG_LENGTH_MAX];
165        cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
166        SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
167                 cinfo.err->msg_code, buffer, caller, width, height);
168    }
169}
170
171static bool return_false(const jpeg_decompress_struct& cinfo,
172                         const char caller[]) {
173    print_jpeg_decoder_errors(cinfo, 0, 0, caller);
174    return false;
175}
176
177static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo,
178                                             const SkBitmap& bm, const char caller[]) {
179    print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
180    return SkImageDecoder::kFailure;
181}
182
183///////////////////////////////////////////////////////////////////////////////
184
185// Convert a scanline of CMYK samples to RGBX in place. Note that this
186// method moves the "scanline" pointer in its processing
187static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
188    // At this point we've received CMYK pixels from libjpeg. We
189    // perform a crude conversion to RGB (based on the formulae
190    // from easyrgb.com):
191    //  CMYK -> CMY
192    //    C = ( C * (1 - K) + K )      // for each CMY component
193    //  CMY -> RGB
194    //    R = ( 1 - C ) * 255          // for each RGB component
195    // Unfortunately we are seeing inverted CMYK so all the original terms
196    // are 1-. This yields:
197    //  CMYK -> CMY
198    //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
199    // The conversion from CMY->RGB remains the same
200    for (unsigned int x = 0; x < width; ++x, scanline += 4) {
201        scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
202        scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
203        scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
204        scanline[3] = 255;
205    }
206}
207
208/**
209 *  Common code for setting the error manager.
210 */
211static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) {
212    SkASSERT(cinfo != nullptr);
213    SkASSERT(errorManager != nullptr);
214    cinfo->err = jpeg_std_error(errorManager);
215    errorManager->error_exit = skjpeg_error_exit;
216}
217
218/**
219 * Common code for setting the dct method.
220 */
221static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) {
222    SkASSERT(cinfo != nullptr);
223    cinfo->dct_method = JDCT_ISLOW;
224}
225
226SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
227    SkASSERT(cinfo != nullptr);
228
229    SrcDepth srcDepth = k32Bit_SrcDepth;
230    if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
231        srcDepth = k8BitGray_SrcDepth;
232    }
233
234    SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
235    switch (colorType) {
236        case kAlpha_8_SkColorType:
237            // Only respect A8 colortype if the original is grayscale,
238            // in which case we will treat the grayscale as alpha
239            // values.
240            if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
241                colorType = kN32_SkColorType;
242            }
243            break;
244        case kN32_SkColorType:
245            // Fall through.
246        case kARGB_4444_SkColorType:
247            // Fall through.
248        case kRGB_565_SkColorType:
249            // These are acceptable destination colortypes.
250            break;
251        default:
252            // Force all other colortypes to 8888.
253            colorType = kN32_SkColorType;
254            break;
255    }
256
257    switch (cinfo->jpeg_color_space) {
258        case JCS_CMYK:
259            // Fall through.
260        case JCS_YCCK:
261            // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
262            // so libjpeg will give us CMYK samples back and we will later
263            // manually convert them to RGB
264            cinfo->out_color_space = JCS_CMYK;
265            break;
266        case JCS_GRAYSCALE:
267            if (kAlpha_8_SkColorType == colorType) {
268                cinfo->out_color_space = JCS_GRAYSCALE;
269                break;
270            }
271            // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
272            // colortype. Fall through to set to the default.
273        default:
274            cinfo->out_color_space = JCS_RGB;
275            break;
276    }
277    return colorType;
278}
279
280/**
281 *  Based on the colortype and dither mode, adjust out_color_space and
282 *  dither_mode of cinfo. Only does work in ANDROID_RGB
283 */
284static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
285                                              SkColorType colorType,
286                                              const SkImageDecoder& decoder) {
287    SkASSERT(cinfo != nullptr);
288#ifdef ANDROID_RGB
289    cinfo->dither_mode = JDITHER_NONE;
290    if (JCS_CMYK == cinfo->out_color_space) {
291        return;
292    }
293    switch (colorType) {
294        case kN32_SkColorType:
295            cinfo->out_color_space = JCS_RGBA_8888;
296            break;
297        case kRGB_565_SkColorType:
298            cinfo->out_color_space = JCS_RGB_565;
299            if (decoder.getDitherImage()) {
300                cinfo->dither_mode = JDITHER_ORDERED;
301            }
302            break;
303        default:
304            break;
305    }
306#endif
307}
308
309/**
310   Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
311   Used when decoding fails partway through reading scanlines to fill
312   remaining lines. */
313static void fill_below_level(int y, SkBitmap* bitmap) {
314    SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
315    SkCanvas canvas(*bitmap);
316    canvas.clipRect(SkRect::Make(rect));
317    canvas.drawColor(SK_ColorWHITE);
318}
319
320/**
321 *  Get the config and bytes per pixel of the source data. Return
322 *  whether the data is supported.
323 */
324static bool get_src_config(const jpeg_decompress_struct& cinfo,
325                           SkScaledBitmapSampler::SrcConfig* sc,
326                           int* srcBytesPerPixel) {
327    SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr);
328    if (JCS_CMYK == cinfo.out_color_space) {
329        // In this case we will manually convert the CMYK values to RGB
330        *sc = SkScaledBitmapSampler::kRGBX;
331        // The CMYK work-around relies on 4 components per pixel here
332        *srcBytesPerPixel = 4;
333    } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
334        *sc = SkScaledBitmapSampler::kRGB;
335        *srcBytesPerPixel = 3;
336#ifdef ANDROID_RGB
337    } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
338        *sc = SkScaledBitmapSampler::kRGBX;
339        *srcBytesPerPixel = 4;
340    } else if (JCS_RGB_565 == cinfo.out_color_space) {
341        *sc = SkScaledBitmapSampler::kRGB_565;
342        *srcBytesPerPixel = 2;
343#endif
344    } else if (1 == cinfo.out_color_components &&
345               JCS_GRAYSCALE == cinfo.out_color_space) {
346        *sc = SkScaledBitmapSampler::kGray;
347        *srcBytesPerPixel = 1;
348    } else {
349        return false;
350    }
351    return true;
352}
353
354SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
355#ifdef TIME_DECODE
356    SkAutoTime atm("JPEG Decode");
357#endif
358
359    JPEGAutoClean autoClean;
360
361    jpeg_decompress_struct  cinfo;
362    skjpeg_source_mgr       srcManager(stream, this);
363
364    skjpeg_error_mgr errorManager;
365    set_error_mgr(&cinfo, &errorManager);
366
367    // All objects need to be instantiated before this setjmp call so that
368    // they will be cleaned up properly if an error occurs.
369    if (setjmp(errorManager.fJmpBuf)) {
370        return return_failure(cinfo, *bm, "setjmp");
371    }
372
373    initialize_info(&cinfo, &srcManager);
374    autoClean.set(&cinfo);
375
376    int status = jpeg_read_header(&cinfo, true);
377    if (status != JPEG_HEADER_OK) {
378        return return_failure(cinfo, *bm, "read_header");
379    }
380
381    /*  Try to fulfill the requested sampleSize. Since jpeg can do it (when it
382        can) much faster that we, just use their num/denom api to approximate
383        the size.
384    */
385    int sampleSize = this->getSampleSize();
386
387    set_dct_method(*this, &cinfo);
388
389    SkASSERT(1 == cinfo.scale_num);
390    cinfo.scale_denom = sampleSize;
391
392    const SkColorType colorType = this->getBitmapColorType(&cinfo);
393    const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
394                                      kPremul_SkAlphaType : kOpaque_SkAlphaType;
395
396    adjust_out_color_space_and_dither(&cinfo, colorType, *this);
397
398    if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
399        // Assume an A8 bitmap is not opaque to avoid the check of each
400        // individual pixel. It is very unlikely to be opaque, since
401        // an opaque A8 bitmap would not be very interesting.
402        // Otherwise, a jpeg image is opaque.
403        bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
404                                                     colorType, alphaType));
405        return success ? kSuccess : kFailure;
406    }
407
408    /*  image_width and image_height are the original dimensions, available
409        after jpeg_read_header(). To see the scaled dimensions, we have to call
410        jpeg_start_decompress(), and then read output_width and output_height.
411    */
412    if (!jpeg_start_decompress(&cinfo)) {
413        /*  If we failed here, we may still have enough information to return
414            to the caller if they just wanted (subsampled bounds). If sampleSize
415            was 1, then we would have already returned. Thus we just check if
416            we're in kDecodeBounds_Mode, and that we have valid output sizes.
417
418            One reason to fail here is that we have insufficient stream data
419            to complete the setup. However, output dimensions seem to get
420            computed very early, which is why this special check can pay off.
421         */
422        if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
423            SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
424                                       recompute_sampleSize(sampleSize, cinfo));
425            // Assume an A8 bitmap is not opaque to avoid the check of each
426            // individual pixel. It is very unlikely to be opaque, since
427            // an opaque A8 bitmap would not be very interesting.
428            // Otherwise, a jpeg image is opaque.
429            bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
430                                                         colorType, alphaType));
431            return success ? kSuccess : kFailure;
432        } else {
433            return return_failure(cinfo, *bm, "start_decompress");
434        }
435    }
436    sampleSize = recompute_sampleSize(sampleSize, cinfo);
437
438    SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
439    // Assume an A8 bitmap is not opaque to avoid the check of each
440    // individual pixel. It is very unlikely to be opaque, since
441    // an opaque A8 bitmap would not be very interesting.
442    // Otherwise, a jpeg image is opaque.
443    bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
444                                  colorType, alphaType));
445    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
446        return kSuccess;
447    }
448    if (!this->allocPixelRef(bm, nullptr)) {
449        return return_failure(cinfo, *bm, "allocPixelRef");
450    }
451
452    SkAutoLockPixels alp(*bm);
453
454#ifdef ANDROID_RGB
455    /* short-circuit the SkScaledBitmapSampler when possible, as this gives
456       a significant performance boost.
457    */
458    if (sampleSize == 1 &&
459        ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
460         (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
461    {
462        JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
463        INT32 const bpr =  bm->rowBytes();
464
465        while (cinfo.output_scanline < cinfo.output_height) {
466            int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
467            if (0 == row_count) {
468                // if row_count == 0, then we didn't get a scanline,
469                // so return early.  We will return a partial image.
470                fill_below_level(cinfo.output_scanline, bm);
471                cinfo.output_scanline = cinfo.output_height;
472                jpeg_finish_decompress(&cinfo);
473                return kPartialSuccess;
474            }
475            if (this->shouldCancelDecode()) {
476                return return_failure(cinfo, *bm, "shouldCancelDecode");
477            }
478            rowptr += bpr;
479        }
480        jpeg_finish_decompress(&cinfo);
481        return kSuccess;
482    }
483#endif
484
485    // check for supported formats
486    SkScaledBitmapSampler::SrcConfig sc;
487    int srcBytesPerPixel;
488
489    if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
490        return return_failure(cinfo, *bm, "jpeg colorspace");
491    }
492
493    if (!sampler.begin(bm, sc, *this)) {
494        return return_failure(cinfo, *bm, "sampler.begin");
495    }
496
497    SkAutoTMalloc<uint8_t> srcStorage(cinfo.output_width * srcBytesPerPixel);
498    uint8_t* srcRow = srcStorage.get();
499
500    //  Possibly skip initial rows [sampler.srcY0]
501    if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
502        return return_failure(cinfo, *bm, "skip rows");
503    }
504
505    // now loop through scanlines until y == bm->height() - 1
506    for (int y = 0;; y++) {
507        JSAMPLE* rowptr = (JSAMPLE*)srcRow;
508        int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
509        sk_msan_mark_initialized(srcRow, srcRow + cinfo.output_width * srcBytesPerPixel,
510                                 "skbug.com/4550");
511        if (0 == row_count) {
512            // if row_count == 0, then we didn't get a scanline,
513            // so return early.  We will return a partial image.
514            fill_below_level(y, bm);
515            cinfo.output_scanline = cinfo.output_height;
516            jpeg_finish_decompress(&cinfo);
517            return kPartialSuccess;
518        }
519        if (this->shouldCancelDecode()) {
520            return return_failure(cinfo, *bm, "shouldCancelDecode");
521        }
522
523        if (JCS_CMYK == cinfo.out_color_space) {
524            convert_CMYK_to_RGB(srcRow, cinfo.output_width);
525        }
526
527
528        sampler.next(srcRow);
529        if (bm->height() - 1 == y) {
530            // we're done
531            break;
532        }
533
534        if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
535            return return_failure(cinfo, *bm, "skip rows");
536        }
537    }
538
539    // we formally skip the rest, so we don't get a complaint from libjpeg
540    if (!skip_src_rows(&cinfo, srcRow,
541                       cinfo.output_height - cinfo.output_scanline)) {
542        return return_failure(cinfo, *bm, "skip rows");
543    }
544    jpeg_finish_decompress(&cinfo);
545
546    return kSuccess;
547}
548
549///////////////////////////////////////////////////////////////////////////////
550
551enum SizeType {
552    kSizeForMemoryAllocation_SizeType,
553    kActualSize_SizeType
554};
555
556static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int component,
557                                SizeType sizeType) {
558    if (sizeType == kSizeForMemoryAllocation_SizeType) {
559        return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DCTSIZE,
560                             info.cur_comp_info[component]->height_in_blocks * DCTSIZE);
561    }
562    return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
563                         info.cur_comp_info[component]->downsampled_height);
564}
565
566static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
567    return (info.jpeg_color_space == JCS_YCbCr)
568        && (DCTSIZE == 8)
569        && (info.num_components == 3)
570        && (info.comps_in_scan >= info.num_components)
571        && (info.scale_denom <= 8)
572        && (info.cur_comp_info[0])
573        && (info.cur_comp_info[1])
574        && (info.cur_comp_info[2])
575        && (info.cur_comp_info[1]->h_samp_factor == 1)
576        && (info.cur_comp_info[1]->v_samp_factor == 1)
577        && (info.cur_comp_info[2]->h_samp_factor == 1)
578        && (info.cur_comp_info[2]->v_samp_factor == 1);
579}
580
581static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
582                                    SizeType sizeType) {
583    SkASSERT(appears_to_be_yuv(cinfo));
584    for (int i = 0; i < 3; ++i) {
585        componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
586    }
587}
588
589static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size_t rowBytes[3]) {
590    SkASSERT(appears_to_be_yuv(cinfo));
591    // U size and V size have to be the same if we're calling output_raw_data()
592    SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeType);
593    SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeType));
594
595    JSAMPARRAY bufferraw[3];
596    JSAMPROW bufferraw2[32];
597    bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
598    bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
599    bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
600    int yWidth = cinfo.output_width;
601    int yHeight = cinfo.output_height;
602    int yMaxH = yHeight - 1;
603    int v = cinfo.cur_comp_info[0]->v_samp_factor;
604    int uvMaxH = uvSize.height() - 1;
605    JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
606    JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
607    JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
608    size_t rowBytesY = rowBytes[0];
609    size_t rowBytesU = rowBytes[1];
610    size_t rowBytesV = rowBytes[2];
611
612    int yScanlinesToRead = DCTSIZE * v;
613    SkAutoMalloc lastRowStorage(rowBytesY * 4);
614    JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
615    JSAMPROW uLastRow = yLastRow + rowBytesY;
616    JSAMPROW vLastRow = uLastRow + rowBytesY;
617    JSAMPROW dummyRow = vLastRow + rowBytesY;
618
619    while (cinfo.output_scanline < cinfo.output_height) {
620        // Request 8 or 16 scanlines: returns 0 or more scanlines.
621        bool hasYLastRow(false), hasUVLastRow(false);
622        // Assign 8 or 16 rows of memory to read the Y channel.
623        for (int i = 0; i < yScanlinesToRead; ++i) {
624            int scanline = (cinfo.output_scanline + i);
625            if (scanline < yMaxH) {
626                bufferraw2[i] = &outputY[scanline * rowBytesY];
627            } else if (scanline == yMaxH) {
628                bufferraw2[i] = yLastRow;
629                hasYLastRow = true;
630            } else {
631                bufferraw2[i] = dummyRow;
632            }
633        }
634        int scaledScanline = cinfo.output_scanline / v;
635        // Assign 8 rows of memory to read the U and V channels.
636        for (int i = 0; i < 8; ++i) {
637            int scanline = (scaledScanline + i);
638            if (scanline < uvMaxH) {
639                bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
640                bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
641            } else if (scanline == uvMaxH) {
642                bufferraw2[16 + i] = uLastRow;
643                bufferraw2[24 + i] = vLastRow;
644                hasUVLastRow = true;
645            } else {
646                bufferraw2[16 + i] = dummyRow;
647                bufferraw2[24 + i] = dummyRow;
648            }
649        }
650        JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanlinesToRead);
651
652        if (scanlinesRead == 0) {
653            return false;
654        }
655
656        if (hasYLastRow) {
657            memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
658        }
659        if (hasUVLastRow) {
660            memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
661            memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
662        }
663    }
664
665    cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
666
667    return true;
668}
669
670bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
671                                            void* planes[3], size_t rowBytes[3],
672                                            SkYUVColorSpace* colorSpace) {
673#ifdef TIME_DECODE
674    SkAutoTime atm("JPEG YUV8 Decode");
675#endif
676    if (this->getSampleSize() != 1) {
677        return false; // Resizing not supported
678    }
679
680    JPEGAutoClean autoClean;
681
682    jpeg_decompress_struct  cinfo;
683    skjpeg_source_mgr       srcManager(stream, this);
684
685    skjpeg_error_mgr errorManager;
686    set_error_mgr(&cinfo, &errorManager);
687
688    // All objects need to be instantiated before this setjmp call so that
689    // they will be cleaned up properly if an error occurs.
690    if (setjmp(errorManager.fJmpBuf)) {
691        return return_false(cinfo, "setjmp YUV8");
692    }
693
694    initialize_info(&cinfo, &srcManager);
695    autoClean.set(&cinfo);
696
697    int status = jpeg_read_header(&cinfo, true);
698    if (status != JPEG_HEADER_OK) {
699        return return_false(cinfo, "read_header YUV8");
700    }
701
702    if (!appears_to_be_yuv(cinfo)) {
703        // It's not an error to not be encoded in YUV, so no need to use return_false()
704        return false;
705    }
706
707    cinfo.out_color_space = JCS_YCbCr;
708    cinfo.raw_data_out = TRUE;
709
710    if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size only
711        update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_SizeType);
712        return true;
713    }
714
715    set_dct_method(*this, &cinfo);
716
717    SkASSERT(1 == cinfo.scale_num);
718    cinfo.scale_denom = 1;
719
720#ifdef ANDROID_RGB
721    cinfo.dither_mode = JDITHER_NONE;
722#endif
723
724    /*  image_width and image_height are the original dimensions, available
725        after jpeg_read_header(). To see the scaled dimensions, we have to call
726        jpeg_start_decompress(), and then read output_width and output_height.
727    */
728    if (!jpeg_start_decompress(&cinfo)) {
729        return return_false(cinfo, "start_decompress YUV8");
730    }
731
732    // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
733    // Again, not really an error.
734    if (!appears_to_be_yuv(cinfo)) {
735        return false;
736    }
737
738    if (!output_raw_data(cinfo, planes, rowBytes)) {
739        return return_false(cinfo, "output_raw_data");
740    }
741
742    update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
743    jpeg_finish_decompress(&cinfo);
744
745    if (nullptr != colorSpace) {
746        *colorSpace = kJPEG_SkYUVColorSpace;
747    }
748
749    return true;
750}
751
752///////////////////////////////////////////////////////////////////////////////
753
754typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
755                              const void* SK_RESTRICT src, int width,
756                              const SkPMColor* SK_RESTRICT ctable);
757
758static void Write_32_RGB(uint8_t* SK_RESTRICT dst,
759                         const void* SK_RESTRICT srcRow, int width,
760                         const SkPMColor*) {
761    const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
762    while (--width >= 0) {
763        uint32_t c = *src++;
764        dst[0] = SkGetPackedR32(c);
765        dst[1] = SkGetPackedG32(c);
766        dst[2] = SkGetPackedB32(c);
767        dst += 3;
768    }
769}
770
771static void Write_4444_RGB(uint8_t* SK_RESTRICT dst,
772                           const void* SK_RESTRICT srcRow, int width,
773                           const SkPMColor*) {
774    const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
775    while (--width >= 0) {
776        SkPMColor16 c = *src++;
777        dst[0] = SkPacked4444ToR32(c);
778        dst[1] = SkPacked4444ToG32(c);
779        dst[2] = SkPacked4444ToB32(c);
780        dst += 3;
781    }
782}
783
784static void Write_16_RGB(uint8_t* SK_RESTRICT dst,
785                         const void* SK_RESTRICT srcRow, int width,
786                         const SkPMColor*) {
787    const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
788    while (--width >= 0) {
789        uint16_t c = *src++;
790        dst[0] = SkPacked16ToR32(c);
791        dst[1] = SkPacked16ToG32(c);
792        dst[2] = SkPacked16ToB32(c);
793        dst += 3;
794    }
795}
796
797static void Write_Index_RGB(uint8_t* SK_RESTRICT dst,
798                            const void* SK_RESTRICT srcRow, int width,
799                            const SkPMColor* SK_RESTRICT ctable) {
800    const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
801    while (--width >= 0) {
802        uint32_t c = ctable[*src++];
803        dst[0] = SkGetPackedR32(c);
804        dst[1] = SkGetPackedG32(c);
805        dst[2] = SkGetPackedB32(c);
806        dst += 3;
807    }
808}
809
810static WriteScanline ChooseWriter(const SkBitmap& bm) {
811    switch (bm.colorType()) {
812        case kN32_SkColorType:
813            return Write_32_RGB;
814        case kRGB_565_SkColorType:
815            return Write_16_RGB;
816        case kARGB_4444_SkColorType:
817            return Write_4444_RGB;
818        case kIndex_8_SkColorType:
819            return Write_Index_RGB;
820        default:
821            return nullptr;
822    }
823}
824
825class SkJPEGImageEncoder : public SkImageEncoder {
826protected:
827    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
828#ifdef TIME_ENCODE
829        SkAutoTime atm("JPEG Encode");
830#endif
831
832        SkAutoLockPixels alp(bm);
833        if (nullptr == bm.getPixels()) {
834            return false;
835        }
836
837        jpeg_compress_struct    cinfo;
838        skjpeg_error_mgr        sk_err;
839        skjpeg_destination_mgr  sk_wstream(stream);
840
841        // allocate these before set call setjmp
842        SkAutoTMalloc<uint8_t>  oneRow;
843
844        cinfo.err = jpeg_std_error(&sk_err);
845        sk_err.error_exit = skjpeg_error_exit;
846        if (setjmp(sk_err.fJmpBuf)) {
847            return false;
848        }
849
850        // Keep after setjmp or mark volatile.
851        const WriteScanline writer = ChooseWriter(bm);
852        if (nullptr == writer) {
853            return false;
854        }
855
856        jpeg_create_compress(&cinfo);
857        cinfo.dest = &sk_wstream;
858        cinfo.image_width = bm.width();
859        cinfo.image_height = bm.height();
860        cinfo.input_components = 3;
861        // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turbo?
862        cinfo.in_color_space = JCS_RGB;
863
864        // The gamma value is ignored by libjpeg-turbo.
865        cinfo.input_gamma = 1;
866
867        jpeg_set_defaults(&cinfo);
868
869        // Tells libjpeg-turbo to compute optimal Huffman coding tables
870        // for the image.  This improves compression at the cost of
871        // slower encode performance.
872        cinfo.optimize_coding = TRUE;
873        jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
874
875        jpeg_start_compress(&cinfo, TRUE);
876
877        const int       width = bm.width();
878        uint8_t*        oneRowP = oneRow.reset(width * 3);
879
880        const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readColors() : nullptr;
881        const void*      srcRow = bm.getPixels();
882
883        while (cinfo.next_scanline < cinfo.image_height) {
884            JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
885
886            writer(oneRowP, srcRow, width, colors);
887            row_pointer[0] = oneRowP;
888            (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
889            srcRow = (const void*)((const char*)srcRow + bm.rowBytes());
890        }
891
892        jpeg_finish_compress(&cinfo);
893        jpeg_destroy_compress(&cinfo);
894
895        return true;
896    }
897};
898
899///////////////////////////////////////////////////////////////////////////////
900DEFINE_DECODER_CREATOR(JPEGImageDecoder);
901DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
902///////////////////////////////////////////////////////////////////////////////
903
904static bool is_jpeg(SkStreamRewindable* stream) {
905    static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
906    static const size_t HEADER_SIZE = sizeof(gHeader);
907
908    char buffer[HEADER_SIZE];
909    size_t len = stream->read(buffer, HEADER_SIZE);
910
911    if (len != HEADER_SIZE) {
912        return false;   // can't read enough
913    }
914    if (memcmp(buffer, gHeader, HEADER_SIZE)) {
915        return false;
916    }
917    return true;
918}
919
920
921static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
922    if (is_jpeg(stream)) {
923        return new SkJPEGImageDecoder;
924    }
925    return nullptr;
926}
927
928static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
929    if (is_jpeg(stream)) {
930        return SkImageDecoder::kJPEG_Format;
931    }
932    return SkImageDecoder::kUnknown_Format;
933}
934
935static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
936    return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
937}
938
939static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
940static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
941static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
942