180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2007 The Android Open Source Project 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageDecoder.h" 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkImageEncoder.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkJpegUtility.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDither.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScaledBitmapSampler.h" 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h" 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplates.h" 17e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkTime.h" 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h" 19e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkRect.h" 20e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkCanvas.h" 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdio.h> 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruextern "C" { 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #include "jpeglib.h" 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #include "jerror.h" 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// These enable timing code that report milliseconds for an encoding/decoding 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//#define TIME_ENCODE 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//#define TIME_DECODE 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this enables our rgb->yuv code, which is faster than libjpeg on ARM 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define WE_CONVERT_TO_YUV 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 35e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers 36e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. 37e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////// 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////// 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 41e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { 42e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 43e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger /* Check if the device indicates that it has a large amount of system memory 44e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * if so, increase the memory allocation to 30MB instead of the default 5MB. 45e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger */ 46e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_LARGE_MEMORY_DEVICE 47e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 48e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#else 49e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; 50e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 51e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif // SK_BUILD_FOR_ANDROID 52e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 53e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 54e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger////////////////////////////////////////////////////////////////////////// 55e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger////////////////////////////////////////////////////////////////////////// 56e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 57e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* src_mgr) { 58e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 59e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(src_mgr != NULL); 60e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger jpeg_create_decompress(cinfo); 61e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger overwrite_mem_buffer_size(cinfo); 62e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->src = src_mgr; 63e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 64e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 65e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 66e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerclass SkJPEGImageIndex { 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 68e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) 69e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger : fSrcMgr(stream, decoder) 70e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger , fInfoInitialized(false) 71e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger , fHuffmanCreated(false) 72e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger , fDecompressStarted(false) 73e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger { 74e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkDEBUGCODE(fReadHeaderSucceeded = false;) 75e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 76e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 77e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger ~SkJPEGImageIndex() { 78e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (fHuffmanCreated) { 79e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Set to false before calling the libjpeg function, in case 80e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // the libjpeg function calls longjmp. Our setjmp handler may 81e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // attempt to delete this SkJPEGImageIndex, thus entering this 82e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // destructor again. Setting fHuffmanCreated to false first 83e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // prevents an infinite loop. 84e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fHuffmanCreated = false; 85e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger jpeg_destroy_huffman_index(&fHuffmanIndex); 86e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 87e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (fDecompressStarted) { 88e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Like fHuffmanCreated, set to false before calling libjpeg 89e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // function to prevent potential infinite loop. 90e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fDecompressStarted = false; 91e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger jpeg_finish_decompress(&fCInfo); 92e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 93e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (fInfoInitialized) { 94e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger this->destroyInfo(); 95e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 96e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 97e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 98e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /** 99e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Destroy the cinfo struct. 100e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * After this call, if a huffman index was already built, it 101e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * can be used after calling initializeInfoAndReadHeader 102e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * again. Must not be called after startTileDecompress except 103e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * in the destructor. 104e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 105e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger void destroyInfo() { 106e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(fInfoInitialized); 107e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(!fDecompressStarted); 108e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Like fHuffmanCreated, set to false before calling libjpeg 109e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // function to prevent potential infinite loop. 110e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fInfoInitialized = false; 111e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_destroy_decompress(&fCInfo); 112e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkDEBUGCODE(fReadHeaderSucceeded = false;) 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 115e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger /** 116e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Initialize the cinfo struct. 117e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Calls jpeg_create_decompress, makes customizations, and 118e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * finally calls jpeg_read_header. Returns true if jpeg_read_header 119e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * returns JPEG_HEADER_OK. 120e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * If cinfo was already initialized, destroyInfo must be called to 121e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * destroy the old one. Must not be called after startTileDecompress. 122e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger */ 123e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool initializeInfoAndReadHeader() { 124e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(!fInfoInitialized && !fDecompressStarted); 125e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger initialize_info(&fCInfo, &fSrcMgr); 126e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fInfoInitialized = true; 127e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true)); 128e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkDEBUGCODE(fReadHeaderSucceeded = success;) 129e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return success; 130e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 132e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_decompress_struct* cinfo() { return &fCInfo; } 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 134e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger huffman_index* huffmanIndex() { return &fHuffmanIndex; } 135e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 136e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /** 137e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Build the index to be used for tile based decoding. 138e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Must only be called after a successful call to 139e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * initializeInfoAndReadHeader and must not be called more 140e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * than once. 141e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 142e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool buildHuffmanIndex() { 143e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(fReadHeaderSucceeded); 144e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(!fHuffmanCreated); 145e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger jpeg_create_huffman_index(&fCInfo, &fHuffmanIndex); 146e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(1 == fCInfo.scale_num && 1 == fCInfo.scale_denom); 1474495d5ff20e5a4923d708fa335371f0c8e9b2752Leon Scroggins III fHuffmanCreated = jpeg_build_huffman_index(&fCInfo, &fHuffmanIndex); 1484495d5ff20e5a4923d708fa335371f0c8e9b2752Leon Scroggins III return fHuffmanCreated; 149e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 150e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 151e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /** 152e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Start tile based decoding. Must only be called after a 153e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * successful call to buildHuffmanIndex, and must only be 154e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * called once. 155e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 156e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool startTileDecompress() { 157e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(fHuffmanCreated); 158e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(fReadHeaderSucceeded); 159e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(!fDecompressStarted); 160e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (jpeg_start_tile_decompress(&fCInfo)) { 161e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fDecompressStarted = true; 162e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return true; 163e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 164e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return false; 165e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 166e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 167e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerprivate: 168e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger skjpeg_source_mgr fSrcMgr; 169e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_decompress_struct fCInfo; 170e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger huffman_index fHuffmanIndex; 171e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool fInfoInitialized; 172e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool fHuffmanCreated; 173e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool fDecompressStarted; 174e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkDEBUGCODE(bool fReadHeaderSucceeded;) 175e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}; 176e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 178e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerclass SkJPEGImageDecoder : public SkImageDecoder { 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 180e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 181e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkJPEGImageDecoder() { 182e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger fImageIndex = NULL; 183e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger fImageWidth = 0; 184e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger fImageHeight = 0; 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 186e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 187e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger virtual ~SkJPEGImageDecoder() { 188e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkDELETE(fImageIndex); 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 190e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif 191e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 192e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger virtual Format getFormat() const { 193e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return kJPEG_Format; 194e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 195e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 196e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerprotected: 197e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 198e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE; 1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE; 200e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 201e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 202e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 204e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 205e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkJPEGImageIndex* fImageIndex; 206e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int fImageWidth; 207e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int fImageHeight; 208e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif 209e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 210e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /** 211e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Determine the appropriate bitmap config and out_color_space based on 212e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * both the preference of the caller and the jpeg_color_space on the 213e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * jpeg_decompress_struct passed in. 214e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Must be called after jpeg_read_header. 215e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 216e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*); 217e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 218e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger typedef SkImageDecoder INHERITED; 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 221e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger////////////////////////////////////////////////////////////////////////// 222e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Automatically clean up after throwing an exception */ 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass JPEGAutoClean { 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JPEGAutoClean(): cinfo_ptr(NULL) {} 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ~JPEGAutoClean() { 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (cinfo_ptr) { 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_destroy_decompress(cinfo_ptr); 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void set(jpeg_decompress_struct* info) { 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo_ptr = info; 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_decompress_struct* cinfo_ptr; 23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* If we need to better match the request, we might examine the image and 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru output dimensions, and determine if the downsampling jpeg provided is 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru not sufficient. If so, we can recompute a modified sampleSize value to 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru make up the difference. 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru To skip this additional scaling, just set sampleSize = 1; below. 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic int recompute_sampleSize(int sampleSize, 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const jpeg_decompress_struct& cinfo) { 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return sampleSize * cinfo.output_width / cinfo.image_width; 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* These are initialized to 0, so if they have non-zero values, we assume 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru they are "valid" (i.e. have been computed by libjpeg) 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 257e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return 0 != cinfo.output_width && 0 != cinfo.output_height; 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 260e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstatic bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) { 26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < count; i++) { 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JSAMPLE* rowptr = (JSAMPLE*)buffer; 26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 264e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (1 != row_count) { 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 271e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 272e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstatic bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, 273e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger huffman_index *index, void* buffer, int count) { 274e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger for (int i = 0; i < count; i++) { 275e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger JSAMPLE* rowptr = (JSAMPLE*)buffer; 276e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); 277e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (1 != row_count) { 278e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 279e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 280e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 281e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return true; 282e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 283e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 284e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This guy exists just to aid in debugging, as it allows debuggers to just 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// set a break-point in one place to see all error exists. 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool return_false(const jpeg_decompress_struct& cinfo, 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkBitmap& bm, const char msg[]) { 289e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef SK_DEBUG 29058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n", cinfo.err->msg_code, 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg, 29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm.width(), bm.height()); 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; // must always return false 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Convert a scanline of CMYK samples to RGBX in place. Note that this 29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// method moves the "scanline" pointer in its processing 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) { 30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // At this point we've received CMYK pixels from libjpeg. We 30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // perform a crude conversion to RGB (based on the formulae 30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // from easyrgb.com): 30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // CMYK -> CMY 30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // C = ( C * (1 - K) + K ) // for each CMY component 30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // CMY -> RGB 30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // R = ( 1 - C ) * 255 // for each RGB component 30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Unfortunately we are seeing inverted CMYK so all the original terms 30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // are 1-. This yields: 30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // CMYK -> CMY 31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K 31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // The conversion from CMY->RGB remains the same 31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (unsigned int x = 0; x < width; ++x, scanline += 4) { 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); 31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); 31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); 31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru scanline[3] = 255; 31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 320e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/** 321e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Common code for setting the error manager. 322e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 323e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* errorManager) { 324e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 325e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(errorManager != NULL); 326e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->err = jpeg_std_error(errorManager); 327e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger errorManager->error_exit = skjpeg_error_exit; 328e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 329e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 330e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/** 331e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Common code for turning off upsampling and smoothing. Turning these 332e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * off helps performance without showing noticable differences in the 333e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * resulting bitmap. 334e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 335e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { 336e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 337e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /* this gives about 30% performance improvement. In theory it may 338e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger reduce the visual quality, in practice I'm not seeing a difference 339e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 340e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->do_fancy_upsampling = 0; 341e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 342e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger /* this gives another few percents */ 343e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->do_block_smoothing = 0; 344e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 345e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 346e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/** 347e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Common code for setting the dct method. 348e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 349e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct* cinfo) { 350e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 351e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef DCT_IFAST_SUPPORTED 352e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (decoder.getPreferQualityOverSpeed()) { 353e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->dct_method = JDCT_ISLOW; 354e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } else { 355e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->dct_method = JDCT_IFAST; 356e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 357e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#else 358e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->dct_method = JDCT_ISLOW; 359e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif 360e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 361e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 362e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cinfo) { 363e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 364e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 365e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SrcDepth srcDepth = k32Bit_SrcDepth; 366e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { 367e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger srcDepth = k8BitGray_SrcDepth; 368e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 369e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 370e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false); 371e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger switch (config) { 372e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kA8_Config: 373e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Only respect A8 config if the original is grayscale, 374e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // in which case we will treat the grayscale as alpha 375e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // values. 376e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { 377e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger config = SkBitmap::kARGB_8888_Config; 378e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 379e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 380e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kARGB_8888_Config: 381e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Fall through. 382e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kARGB_4444_Config: 383e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Fall through. 384e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kRGB_565_Config: 385e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // These are acceptable destination configs. 386e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 387e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger default: 388e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Force all other configs to 8888. 389e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger config = SkBitmap::kARGB_8888_Config; 390e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 391e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 392e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 393e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger switch (cinfo->jpeg_color_space) { 394e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case JCS_CMYK: 395e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // Fall through. 396e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case JCS_YCCK: 397e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up 398e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // so libjpeg will give us CMYK samples back and we will later 399e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // manually convert them to RGB 400e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->out_color_space = JCS_CMYK; 401e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 402e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case JCS_GRAYSCALE: 403e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (SkBitmap::kA8_Config == config) { 404e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->out_color_space = JCS_GRAYSCALE; 405e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 406e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 407e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB 408e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // config. Fall through to set to the default. 409e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger default: 410e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->out_color_space = JCS_RGB; 411e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 412e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 413e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return config; 414e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 415e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 416e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef ANDROID_RGB 417e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger/** 418e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * Based on the config and dither mode, adjust out_color_space and 419e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger * dither_mode of cinfo. 420e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger */ 421e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerstatic void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, 422e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkBitmap::Config config, 423e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger const SkImageDecoder& decoder) { 424e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(cinfo != NULL); 425e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->dither_mode = JDITHER_NONE; 426e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (JCS_CMYK == cinfo->out_color_space) { 427e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return; 428e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 429e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger switch(config) { 430e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kARGB_8888_Config: 431e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->out_color_space = JCS_RGBA_8888; 432e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 433e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger case SkBitmap::kRGB_565_Config: 434e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->out_color_space = JCS_RGB_565; 435e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (decoder.getDitherImage()) { 436e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger cinfo->dither_mode = JDITHER_ORDERED; 437e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 438e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 439e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger default: 440e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger break; 441e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 442e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger} 443e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#endif 444e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TIME_DECODE 447e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoTime atm("JPEG Decode"); 44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JPEGAutoClean autoClean; 45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_decompress_struct cinfo; 453e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger skjpeg_source_mgr srcManager(stream, this); 45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 455e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger skjpeg_error_mgr errorManager; 456e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger set_error_mgr(&cinfo, &errorManager); 45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // All objects need to be instantiated before this setjmp call so that 45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // they will be cleaned up properly if an error occurs. 460e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (setjmp(errorManager.fJmpBuf)) { 46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "setjmp"); 46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 464e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger initialize_info(&cinfo, &srcManager); 46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru autoClean.set(&cinfo); 46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status = jpeg_read_header(&cinfo, true); 46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (status != JPEG_HEADER_OK) { 46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "read_header"); 47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru can) much faster that we, just use their num/denom api to approximate 47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru the size. 47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int sampleSize = this->getSampleSize(); 47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 478e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger set_dct_method(*this, &cinfo); 479e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 480e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(1 == cinfo.scale_num); 48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.scale_denom = sampleSize; 48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 483e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger turn_off_visual_optimizations(&cinfo); 48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 485e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger const SkBitmap::Config config = this->getBitmapConfig(&cinfo); 48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB 488e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger adjust_out_color_space_and_dither(&cinfo, config, *this); 48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 491e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { 49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm->setConfig(config, cinfo.image_width, cinfo.image_height); 49358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger bm->setIsOpaque(config != SkBitmap::kA8_Config); 49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* image_width and image_height are the original dimensions, available 49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru after jpeg_read_header(). To see the scaled dimensions, we have to call 49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_start_decompress(), and then read output_width and output_height. 50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!jpeg_start_decompress(&cinfo)) { 50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* If we failed here, we may still have enough information to return 50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to the caller if they just wanted (subsampled bounds). If sampleSize 50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru was 1, then we would have already returned. Thus we just check if 50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru we're in kDecodeBounds_Mode, and that we have valid output sizes. 50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru One reason to fail here is that we have insufficient stream data 50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to complete the setup. However, output dimensions seem to get 50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru computed very early, which is why this special check can pay off. 51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 511e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) { 51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru recompute_sampleSize(sampleSize, cinfo)); 51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight()); 51558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger bm->setIsOpaque(config != SkBitmap::kA8_Config); 51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "start_decompress"); 51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sampleSize = recompute_sampleSize(sampleSize, cinfo); 52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // should we allow the Chooser (if present) to pick a config for us??? 524e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) { 52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "chooseFromOneChoice"); 52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 528e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); 52958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 53058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger bm->setIsOpaque(config != SkBitmap::kA8_Config); 53158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (SkImageDecoder::kDecodeBounds_Mode == mode) { 53258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return true; 53358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 53458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!this->allocPixelRef(bm, NULL)) { 53558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return return_false(cinfo, *bm, "allocPixelRef"); 536e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 537e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 538e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoLockPixels alp(*bm); 539e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB 54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* short-circuit the SkScaledBitmapSampler when possible, as this gives 54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru a significant performance boost. 54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (sampleSize == 1 && 54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ((config == SkBitmap::kARGB_8888_Config && 54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.out_color_space == JCS_RGBA_8888) || 54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (config == SkBitmap::kRGB_565_Config && 54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.out_color_space == JCS_RGB_565))) 54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru { 55058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru INT32 const bpr = bm->rowBytes(); 55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (cinfo.output_scanline < cinfo.output_height) { 55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if row_count == 0, then we didn't get a scanline, so abort. 55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if we supported partial images, we might return true in this case 55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == row_count) { 55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "read_scanlines"); 55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->shouldCancelDecode()) { 56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "shouldCancelDecode"); 56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rowptr += bpr; 56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_finish_decompress(&cinfo); 56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // check for supported formats 57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkScaledBitmapSampler::SrcConfig sc; 57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (JCS_CMYK == cinfo.out_color_space) { 57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // In this case we will manually convert the CMYK values to RGB 57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sc = SkScaledBitmapSampler::kRGBX; 57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { 57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sc = SkScaledBitmapSampler::kRGB; 57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef ANDROID_RGB 57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else if (JCS_RGBA_8888 == cinfo.out_color_space) { 57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sc = SkScaledBitmapSampler::kRGBX; 58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else if (JCS_RGB_565 == cinfo.out_color_space) { 58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sc = SkScaledBitmapSampler::kRGB_565; 58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else if (1 == cinfo.out_color_components && 58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JCS_GRAYSCALE == cinfo.out_color_space) { 58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sc = SkScaledBitmapSampler::kGray; 58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "jpeg colorspace"); 58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 59034835907d8ed21079a9ee09e0e16082a98637d42Leon Scroggins III if (!sampler.begin(bm, sc, *this)) { 59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "sampler.begin"); 59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // The CMYK work-around relies on 4 components per pixel here 595e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoMalloc srcStorage(cinfo.output_width * 4); 596e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger uint8_t* srcRow = (uint8_t*)srcStorage.get(); 59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Possibly skip initial rows [sampler.srcY0] 59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "skip rows"); 60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // now loop through scanlines until y == bm->height() - 1 60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int y = 0;; y++) { 60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JSAMPLE* rowptr = (JSAMPLE*)srcRow; 60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0 == row_count) { 60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "read_scanlines"); 60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->shouldCancelDecode()) { 61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "shouldCancelDecode"); 61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (JCS_CMYK == cinfo.out_color_space) { 61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru convert_CMYK_to_RGB(srcRow, cinfo.output_width); 61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sampler.next(srcRow); 61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (bm->height() - 1 == y) { 62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we're done 62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "skip rows"); 62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // we formally skip the rest, so we don't get a complaint from libjpeg 63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!skip_src_rows(&cinfo, srcRow, 63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.output_height - cinfo.output_scanline)) { 63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return return_false(cinfo, *bm, "skip rows"); 63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_finish_decompress(&cinfo); 63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 639e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 640e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerbool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) { 641e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 642e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this))); 643e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_decompress_struct* cinfo = imageIndex->cinfo(); 644e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 645e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger skjpeg_error_mgr sk_err; 646e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger set_error_mgr(cinfo, &sk_err); 647e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 648e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // All objects need to be instantiated before this setjmp call so that 649e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // they will be cleaned up properly if an error occurs. 650e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (setjmp(sk_err.fJmpBuf)) { 651e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 652e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 653e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 654e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // create the cinfo used to create/build the huffmanIndex 655e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (!imageIndex->initializeInfoAndReadHeader()) { 656e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 657e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 658e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 659e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (!imageIndex->buildHuffmanIndex()) { 660e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 661e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 662e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 663e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // destroy the cinfo used to create/build the huffman index 664e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger imageIndex->destroyInfo(); 665e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 666e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // Init decoder to image decode mode 667e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (!imageIndex->initializeInfoAndReadHeader()) { 668e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 669e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 670e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 671e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // FIXME: This sets cinfo->out_color_space, which we may change later 672e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // based on the config in onDecodeSubset. This should be fine, since 673e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // jpeg_init_read_tile_scanline will check out_color_space again after 674e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger // that change (when it calls jinit_color_deconverter). 675e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger (void) this->getBitmapConfig(cinfo); 676e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 677e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger turn_off_visual_optimizations(cinfo); 678e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 679e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // instead of jpeg_start_decompress() we start a tiled decompress 680e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (!imageIndex->startTileDecompress()) { 681e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger return false; 682e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 683e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 684e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger SkASSERT(1 == cinfo->scale_num); 685e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fImageWidth = cinfo->output_width; 686e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fImageHeight = cinfo->output_height; 687e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 688e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (width) { 689e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *width = fImageWidth; 690e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 691e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger if (height) { 692e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger *height = fImageHeight; 693e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger } 694e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 695e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkDELETE(fImageIndex); 696e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger fImageIndex = imageIndex.detach(); 697e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 698e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return true; 699e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 700e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 7017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { 702e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (NULL == fImageIndex) { 703e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 704e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 705e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); 706e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 707e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); 708e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!rect.intersect(region)) { 709e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // If the requested region is entirely outside the image return false 710e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 711e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 712e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 713e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 714e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger skjpeg_error_mgr errorManager; 715e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger set_error_mgr(cinfo, &errorManager); 716e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger 717e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (setjmp(errorManager.fJmpBuf)) { 718e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 719e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 720e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 721e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int requestedSampleSize = this->getSampleSize(); 722e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cinfo->scale_denom = requestedSampleSize; 723e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 724e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger set_dct_method(*this, cinfo); 725e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 726e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger const SkBitmap::Config config = this->getBitmapConfig(cinfo); 727e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB 728e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger adjust_out_color_space_and_dither(cinfo, config, *this); 729e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 730e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 731e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int startX = rect.fLeft; 732e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int startY = rect.fTop; 733e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int width = rect.width(); 734e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int height = rect.height(); 735e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 736e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), 737e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger &startX, &startY, &width, &height); 738e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 739e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size); 740e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 741e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 742e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 743e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkBitmap bitmap; 744e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 745e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bitmap.setIsOpaque(true); 746e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 747e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // Check ahead of time if the swap(dest, src) is possible or not. 748e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // If yes, then we will stick to AllocPixelRef since it's cheaper with the 749e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // swap happening. If no, then we will use alloc to allocate pixels to 750e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // prevent garbage collection. 751e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int w = rect.width() / actualSampleSize; 752e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int h = rect.height() / actualSampleSize; 753e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bool swapOnly = (rect == region) && bm->isNull() && 754e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger (w == bitmap.width()) && (h == bitmap.height()) && 755e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger ((startX - rect.x()) / actualSampleSize == 0) && 756e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger ((startY - rect.y()) / actualSampleSize == 0); 757e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (swapOnly) { 758e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!this->allocPixelRef(&bitmap, NULL)) { 759e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "allocPixelRef"); 760e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 761e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 762e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!bitmap.allocPixels()) { 763e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "allocPixels"); 764e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 765e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 766e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 767e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoLockPixels alp(bitmap); 768e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 769e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB 770e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger /* short-circuit the SkScaledBitmapSampler when possible, as this gives 771e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger a significant performance boost. 772e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger */ 773e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (skiaSampleSize == 1 && 774e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger ((config == SkBitmap::kARGB_8888_Config && 775e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cinfo->out_color_space == JCS_RGBA_8888) || 776e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger (config == SkBitmap::kRGB_565_Config && 777e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cinfo->out_color_space == JCS_RGB_565))) 778e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger { 779e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); 780e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger INT32 const bpr = bitmap.rowBytes(); 781e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int rowTotalCount = 0; 782e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 783e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger while (rowTotalCount < height) { 784e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int rowCount = jpeg_read_tile_scanline(cinfo, 785e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger fImageIndex->huffmanIndex(), 786e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger &rowptr); 787e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // if row_count == 0, then we didn't get a scanline, so abort. 788e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // if we supported partial images, we might return true in this case 789e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (0 == rowCount) { 790e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "read_scanlines"); 791e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 792e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (this->shouldCancelDecode()) { 793e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "shouldCancelDecode"); 794e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 795e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger rowTotalCount += rowCount; 796e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger rowptr += bpr; 797e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 798e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 799e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (swapOnly) { 800e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bm->swap(bitmap); 801e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 802e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 803e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger region.width(), region.height(), startX, startY); 804e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 805e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return true; 806e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 807e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 808e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 809e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // check for supported formats 810e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScaledBitmapSampler::SrcConfig sc; 811e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (JCS_CMYK == cinfo->out_color_space) { 812e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // In this case we will manually convert the CMYK values to RGB 813e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sc = SkScaledBitmapSampler::kRGBX; 814e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) { 815e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sc = SkScaledBitmapSampler::kRGB; 816e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef ANDROID_RGB 817e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else if (JCS_RGBA_8888 == cinfo->out_color_space) { 818e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sc = SkScaledBitmapSampler::kRGBX; 819e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else if (JCS_RGB_565 == cinfo->out_color_space) { 820e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sc = SkScaledBitmapSampler::kRGB_565; 821e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 822e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else if (1 == cinfo->out_color_components && 823e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger JCS_GRAYSCALE == cinfo->out_color_space) { 824e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sc = SkScaledBitmapSampler::kGray; 825e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 826e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, *bm, "jpeg colorspace"); 827e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 828e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 82934835907d8ed21079a9ee09e0e16082a98637d42Leon Scroggins III if (!sampler.begin(&bitmap, sc, *this)) { 830e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "sampler.begin"); 831e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 832e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 833e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // The CMYK work-around relies on 4 components per pixel here 834e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoMalloc srcStorage(width * 4); 835e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger uint8_t* srcRow = (uint8_t*)srcStorage.get(); 836e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 837e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // Possibly skip initial rows [sampler.srcY0] 838e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) { 839e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "skip rows"); 840e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 841e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 842e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // now loop through scanlines until y == bitmap->height() - 1 843e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger for (int y = 0;; y++) { 844e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger JSAMPLE* rowptr = (JSAMPLE*)srcRow; 845e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr); 846e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (0 == row_count) { 847e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "read_scanlines"); 848e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 849e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (this->shouldCancelDecode()) { 850e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "shouldCancelDecode"); 851e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 852e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 853e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (JCS_CMYK == cinfo->out_color_space) { 854e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger convert_CMYK_to_RGB(srcRow, width); 855e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 856e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 857e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sampler.next(srcRow); 858e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (bitmap.height() - 1 == y) { 859e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // we're done 860e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger break; 861e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 862e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 863e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, 864e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger sampler.srcDY() - 1)) { 865e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return return_false(*cinfo, bitmap, "skip rows"); 866e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 867e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 868e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (swapOnly) { 869e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bm->swap(bitmap); 870e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 871e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(), 872e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger region.width(), region.height(), startX, startY); 873e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 874e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return true; 875e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 876e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 877e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h" 88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// taken from jcolor.c in libjpeg 88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 // 16bit - precise but slow 88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYR 19595 // 0.299 88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYG 38470 // 0.587 88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYB 7471 // 0.114 88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUR -11059 // -0.16874 88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUG -21709 // -0.33126 89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUB 32768 // 0.5 89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVR 32768 // 0.5 89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVG -27439 // -0.41869 89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVB -5329 // -0.08131 89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CSHIFT 16 89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else // 8bit - fast, slightly less precise 89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYR 77 // 0.299 89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYG 150 // 0.587 90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CYB 29 // 0.114 90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUR -43 // -0.16874 90380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUG -85 // -0.33126 90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CUB 128 // 0.5 90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVR 128 // 0.5 90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVG -107 // -0.41869 90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CVB -21 // -0.08131 90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CSHIFT 8 91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_32(uint8_t dst[], SkPMColor c) { 91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int r = SkGetPackedR32(c); 91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int g = SkGetPackedG32(c); 91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int b = SkGetPackedB32(c); 91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT; 91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT; 92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT; 92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkToU8(y); 92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkToU8(u + 128); 92480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkToU8(v + 128); 92580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 92680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 92780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_4444(uint8_t dst[], U16CPU c) { 92880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int r = SkGetPackedR4444(c); 92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int g = SkGetPackedG4444(c); 93080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int b = SkGetPackedB4444(c); 93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4); 93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4); 93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4); 93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 93680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkToU8(y); 93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkToU8(u + 128); 93880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkToU8(v + 128); 93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void rgb2yuv_16(uint8_t dst[], U16CPU c) { 94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int r = SkGetPackedR16(c); 94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int g = SkGetPackedG16(c); 94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int b = SkGetPackedB16(c); 94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2); 94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2); 94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2); 94980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkToU8(y); 95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkToU8(u + 128); 95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkToU8(v + 128); 95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT src, int width, 95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor* SK_RESTRICT ctable); 96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_32_YUV(uint8_t* SK_RESTRICT dst, 96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT srcRow, int width, 96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor*) { 96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--width >= 0) { 96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV 96780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rgb2yuv_32(dst, *src++); 96880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 96980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t c = *src++; 97080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkGetPackedR32(c); 97180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkGetPackedG32(c); 97280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkGetPackedB32(c); 97380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += 3; 97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_4444_YUV(uint8_t* SK_RESTRICT dst, 97980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT srcRow, int width, 98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor*) { 98180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--width >= 0) { 98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV 98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rgb2yuv_4444(dst, *src++); 98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor16 c = *src++; 98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkPacked4444ToR32(c); 98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkPacked4444ToG32(c); 98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkPacked4444ToB32(c); 99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += 3; 99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 99380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_16_YUV(uint8_t* SK_RESTRICT dst, 99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT srcRow, int width, 99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor*) { 99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--width >= 0) { 100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV 100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rgb2yuv_16(dst, *src++); 100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint16_t c = *src++; 100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkPacked16ToR32(c); 100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkPacked16ToG32(c); 100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkPacked16ToB32(c); 100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += 3; 100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 101180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 101280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void Write_Index_YUV(uint8_t* SK_RESTRICT dst, 101380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* SK_RESTRICT srcRow, int width, 101480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor* SK_RESTRICT ctable) { 101580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 101680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--width >= 0) { 101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV 101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rgb2yuv_32(dst, ctable[*src++]); 101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t c = ctable[*src++]; 102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[0] = SkGetPackedR32(c); 102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[1] = SkGetPackedG32(c); 102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst[2] = SkGetPackedB32(c); 102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dst += 3; 102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic WriteScanline ChooseWriter(const SkBitmap& bm) { 103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (bm.config()) { 103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kARGB_8888_Config: 103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return Write_32_YUV; 103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kRGB_565_Config: 103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return Write_16_YUV; 103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kARGB_4444_Config: 103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return Write_4444_YUV; 103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kIndex8_Config: 103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return Write_Index_YUV; 103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkJPEGImageEncoder : public SkImageEncoder { 104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected: 104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TIME_ENCODE 1048e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkAutoTime atm("JPEG Encode"); 104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoLockPixels alp(bm); 105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == bm.getPixels()) { 105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_compress_struct cinfo; 105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru skjpeg_error_mgr sk_err; 105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru skjpeg_destination_mgr sk_wstream(stream); 105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // allocate these before set call setjmp 106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMalloc oneRow; 106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoLockColors ctLocker; 106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.err = jpeg_std_error(&sk_err); 106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sk_err.error_exit = skjpeg_error_exit; 106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (setjmp(sk_err.fJmpBuf)) { 106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 107058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // Keep after setjmp or mark volatile. 107158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const WriteScanline writer = ChooseWriter(bm); 107258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (NULL == writer) { 107358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return false; 107458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 107558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 107658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger jpeg_create_compress(&cinfo); 107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.dest = &sk_wstream; 107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.image_width = bm.width(); 107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.image_height = bm.height(); 108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.input_components = 3; 108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef WE_CONVERT_TO_YUV 108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.in_color_space = JCS_YCbCr; 108380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.in_color_space = JCS_RGB; 108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.input_gamma = 1; 108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_set_defaults(&cinfo); 108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 10907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#ifdef DCT_IFAST_SUPPORTED 109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru cinfo.dct_method = JDCT_IFAST; 10927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif 109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_start_compress(&cinfo, TRUE); 109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const int width = bm.width(); 109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3); 109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const SkPMColor* colors = ctLocker.lockColors(bm); 110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const void* srcRow = bm.getPixels(); 110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (cinfo.next_scanline < cinfo.image_height) { 110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru writer(oneRowP, srcRow, width, colors); 110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru row_pointer[0] = oneRowP; 110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_finish_compress(&cinfo); 111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru jpeg_destroy_compress(&cinfo); 111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_DECODER_CREATOR(JPEGImageDecoder); 112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruDEFINE_ENCODER_CREATOR(JPEGImageEncoder); 112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic bool is_jpeg(SkStream* stream) { 112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF }; 112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const size_t HEADER_SIZE = sizeof(gHeader); 112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char buffer[HEADER_SIZE]; 112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t len = stream->read(buffer, HEADER_SIZE); 112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (len != HEADER_SIZE) { 11317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; // can't read enough 113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (memcmp(buffer, gHeader, HEADER_SIZE)) { 11347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 11357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 11367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 11377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 11387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 11397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTRegistry.h" 11407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 11417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) { 11427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (is_jpeg(stream)) { 11437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkNEW(SkJPEGImageDecoder); 11447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 11457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return NULL; 11467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 11477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 11487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkImageDecoder::Format get_format_jpeg(SkStream* stream) { 11497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (is_jpeg(stream)) { 11507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkImageDecoder::kJPEG_Format; 115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkImageDecoder::kUnknown_Format; 115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); 11617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg); 116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory); 1163