| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2007 The Android Open Source Project | 2 * Copyright 2007 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
| 10 #include "SkImageEncoder.h" | 10 #include "SkImageEncoder.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 extern "C" { | 23 extern "C" { |
| 24 #include "jpeglib.h" | 24 #include "jpeglib.h" |
| 25 #include "jerror.h" | 25 #include "jerror.h" |
| 26 } | 26 } |
| 27 | 27 |
| 28 // These enable timing code that report milliseconds for an encoding/decoding | 28 // These enable timing code that report milliseconds for an encoding/decoding |
| 29 //#define TIME_ENCODE | 29 //#define TIME_ENCODE |
| 30 //#define TIME_DECODE | 30 //#define TIME_DECODE |
| 31 | 31 |
| 32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM | 32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM |
| 33 // disable for the moment, as we have some glitches when width != multiple of 4 | |
| 34 #define WE_CONVERT_TO_YUV | 33 #define WE_CONVERT_TO_YUV |
| 35 | 34 |
| 36 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer
s | 35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer
s |
| 37 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. | 36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. |
| 38 | 37 |
| 39 ////////////////////////////////////////////////////////////////////////// | 38 ////////////////////////////////////////////////////////////////////////// |
| 40 ////////////////////////////////////////////////////////////////////////// | 39 ////////////////////////////////////////////////////////////////////////// |
| 41 | 40 |
| 42 static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) { | 41 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { |
| 43 #ifdef SK_BUILD_FOR_ANDROID | 42 #ifdef SK_BUILD_FOR_ANDROID |
| 44 /* Check if the device indicates that it has a large amount of system memory | 43 /* Check if the device indicates that it has a large amount of system memory |
| 45 * if so, increase the memory allocation to 30MB instead of the default 5MB. | 44 * if so, increase the memory allocation to 30MB instead of the default 5MB. |
| 46 */ | 45 */ |
| 47 #ifdef ANDROID_LARGE_MEMORY_DEVICE | 46 #ifdef ANDROID_LARGE_MEMORY_DEVICE |
| 48 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; | 47 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; |
| 49 #else | 48 #else |
| 50 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; | 49 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; |
| 51 #endif | 50 #endif |
| 52 #endif // SK_BUILD_FOR_ANDROID | 51 #endif // SK_BUILD_FOR_ANDROID |
| 53 } | 52 } |
| 54 | 53 |
| 55 ////////////////////////////////////////////////////////////////////////// | 54 ////////////////////////////////////////////////////////////////////////// |
| 56 ////////////////////////////////////////////////////////////////////////// | 55 ////////////////////////////////////////////////////////////////////////// |
| 57 | 56 |
| 57 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr
c_mgr) { |
| 58 SkASSERT(cinfo != NULL); |
| 59 SkASSERT(src_mgr != NULL); |
| 60 jpeg_create_decompress(cinfo); |
| 61 overwrite_mem_buffer_size(cinfo); |
| 62 cinfo->src = src_mgr; |
| 63 } |
| 64 |
| 58 #ifdef SK_BUILD_FOR_ANDROID | 65 #ifdef SK_BUILD_FOR_ANDROID |
| 59 class SkJPEGImageIndex { | 66 class SkJPEGImageIndex { |
| 60 public: | 67 public: |
| 61 SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) | 68 SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder) |
| 62 : fSrcMgr(stream, decoder) | 69 : fSrcMgr(stream, decoder) |
| 63 , fInfoInitialized(false) | 70 , fInfoInitialized(false) |
| 64 , fHuffmanCreated(false) | 71 , fHuffmanCreated(false) |
| 65 , fDecompressStarted(false) | 72 , fDecompressStarted(false) |
| 66 { | 73 { |
| 67 SkDEBUGCODE(fReadHeaderSucceeded = false;) | 74 SkDEBUGCODE(fReadHeaderSucceeded = false;) |
| 68 } | 75 } |
| 69 | 76 |
| 70 ~SkJPEGImageIndex() { | 77 ~SkJPEGImageIndex() { |
| 71 if (fHuffmanCreated) { | 78 if (fHuffmanCreated) { |
| 79 // Set to false before calling the libjpeg function, in case |
| 80 // the libjpeg function calls longjmp. Our setjmp handler may |
| 81 // attempt to delete this SkJPEGImageIndex, thus entering this |
| 82 // destructor again. Setting fHuffmanCreated to false first |
| 83 // prevents an infinite loop. |
| 72 fHuffmanCreated = false; | 84 fHuffmanCreated = false; |
| 73 jpeg_destroy_huffman_index(&fHuffmanIndex); | 85 jpeg_destroy_huffman_index(&fHuffmanIndex); |
| 74 } | 86 } |
| 75 if (fDecompressStarted) { | 87 if (fDecompressStarted) { |
| 88 // Like fHuffmanCreated, set to false before calling libjpeg |
| 89 // function to prevent potential infinite loop. |
| 76 fDecompressStarted = false; | 90 fDecompressStarted = false; |
| 77 jpeg_finish_decompress(&fCInfo); | 91 jpeg_finish_decompress(&fCInfo); |
| 78 } | 92 } |
| 79 if (fInfoInitialized) { | 93 if (fInfoInitialized) { |
| 80 this->destroyInfo(); | 94 this->destroyInfo(); |
| 81 } | 95 } |
| 82 } | 96 } |
| 83 | 97 |
| 84 /** | 98 /** |
| 85 * Destroy the cinfo struct. | 99 * Destroy the cinfo struct. |
| 86 * After this call, if a huffman index was already built, it | 100 * After this call, if a huffman index was already built, it |
| 87 * can be used after calling initializeInfoAndReadHeader | 101 * can be used after calling initializeInfoAndReadHeader |
| 88 * again. Must not be called after startTileDecompress except | 102 * again. Must not be called after startTileDecompress except |
| 89 * in the destructor. | 103 * in the destructor. |
| 90 */ | 104 */ |
| 91 void destroyInfo() { | 105 void destroyInfo() { |
| 92 SkASSERT(fInfoInitialized); | 106 SkASSERT(fInfoInitialized); |
| 93 SkASSERT(!fDecompressStarted); | 107 SkASSERT(!fDecompressStarted); |
| 108 // Like fHuffmanCreated, set to false before calling libjpeg |
| 109 // function to prevent potential infinite loop. |
| 94 fInfoInitialized = false; | 110 fInfoInitialized = false; |
| 95 jpeg_destroy_decompress(&fCInfo); | 111 jpeg_destroy_decompress(&fCInfo); |
| 96 SkDEBUGCODE(fReadHeaderSucceeded = false;) | 112 SkDEBUGCODE(fReadHeaderSucceeded = false;) |
| 97 } | 113 } |
| 98 | 114 |
| 99 /** | 115 /** |
| 100 * Initialize the cinfo struct. | 116 * Initialize the cinfo struct. |
| 101 * Calls jpeg_create_decompress, makes customizations, and | 117 * Calls jpeg_create_decompress, makes customizations, and |
| 102 * finally calls jpeg_read_header. Returns true if jpeg_read_header | 118 * finally calls jpeg_read_header. Returns true if jpeg_read_header |
| 103 * returns JPEG_HEADER_OK. | 119 * returns JPEG_HEADER_OK. |
| 104 * If cinfo was already initialized, destroyInfo must be called to | 120 * If cinfo was already initialized, destroyInfo must be called to |
| 105 * destroy the old one. Must not be called after startTileDecompress. | 121 * destroy the old one. Must not be called after startTileDecompress. |
| 106 */ | 122 */ |
| 107 bool initializeInfoAndReadHeader() { | 123 bool initializeInfoAndReadHeader() { |
| 108 SkASSERT(!fInfoInitialized && !fDecompressStarted); | 124 SkASSERT(!fInfoInitialized && !fDecompressStarted); |
| 109 jpeg_create_decompress(&fCInfo); | 125 initialize_info(&fCInfo, &fSrcMgr); |
| 110 overwrite_mem_buffer_size(&fCInfo); | |
| 111 fCInfo.src = &fSrcMgr; | |
| 112 fInfoInitialized = true; | 126 fInfoInitialized = true; |
| 113 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true))
; | 127 const bool success = (JPEG_HEADER_OK == jpeg_read_header(&fCInfo, true))
; |
| 114 SkDEBUGCODE(fReadHeaderSucceeded = success;) | 128 SkDEBUGCODE(fReadHeaderSucceeded = success;) |
| 115 return success; | 129 return success; |
| 116 } | 130 } |
| 117 | 131 |
| 118 jpeg_decompress_struct* cinfo() { return &fCInfo; } | 132 jpeg_decompress_struct* cinfo() { return &fCInfo; } |
| 119 | 133 |
| 120 huffman_index* huffmanIndex() { return &fHuffmanIndex; } | 134 huffman_index* huffmanIndex() { return &fHuffmanIndex; } |
| 121 | 135 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 #endif | 200 #endif |
| 187 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 201 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 188 | 202 |
| 189 private: | 203 private: |
| 190 #ifdef SK_BUILD_FOR_ANDROID | 204 #ifdef SK_BUILD_FOR_ANDROID |
| 191 SkJPEGImageIndex* fImageIndex; | 205 SkJPEGImageIndex* fImageIndex; |
| 192 int fImageWidth; | 206 int fImageWidth; |
| 193 int fImageHeight; | 207 int fImageHeight; |
| 194 #endif | 208 #endif |
| 195 | 209 |
| 210 /** |
| 211 * Determine the appropriate bitmap config and out_color_space based on |
| 212 * both the preference of the caller and the jpeg_color_space on the |
| 213 * jpeg_decompress_struct passed in. |
| 214 * Must be called after jpeg_read_header. |
| 215 */ |
| 216 SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*); |
| 217 |
| 196 typedef SkImageDecoder INHERITED; | 218 typedef SkImageDecoder INHERITED; |
| 197 }; | 219 }; |
| 198 | 220 |
| 199 ////////////////////////////////////////////////////////////////////////// | 221 ////////////////////////////////////////////////////////////////////////// |
| 200 | 222 |
| 201 /* Automatically clean up after throwing an exception */ | 223 /* Automatically clean up after throwing an exception */ |
| 202 class JPEGAutoClean { | 224 class JPEGAutoClean { |
| 203 public: | 225 public: |
| 204 JPEGAutoClean(): cinfo_ptr(NULL) {} | 226 JPEGAutoClean(): cinfo_ptr(NULL) {} |
| 205 ~JPEGAutoClean() { | 227 ~JPEGAutoClean() { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K | 310 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K |
| 289 // The conversion from CMY->RGB remains the same | 311 // The conversion from CMY->RGB remains the same |
| 290 for (unsigned int x = 0; x < width; ++x, scanline += 4) { | 312 for (unsigned int x = 0; x < width; ++x, scanline += 4) { |
| 291 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); | 313 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]); |
| 292 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); | 314 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]); |
| 293 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); | 315 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]); |
| 294 scanline[3] = 255; | 316 scanline[3] = 255; |
| 295 } | 317 } |
| 296 } | 318 } |
| 297 | 319 |
| 320 /** |
| 321 * Common code for setting the error manager. |
| 322 */ |
| 323 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error
Manager) { |
| 324 SkASSERT(cinfo != NULL); |
| 325 SkASSERT(errorManager != NULL); |
| 326 cinfo->err = jpeg_std_error(errorManager); |
| 327 errorManager->error_exit = skjpeg_error_exit; |
| 328 } |
| 329 |
| 330 /** |
| 331 * Common code for turning off upsampling and smoothing. Turning these |
| 332 * off helps performance without showing noticable differences in the |
| 333 * resulting bitmap. |
| 334 */ |
| 335 static void turn_off_visual_optimizations(jpeg_decompress_struct* cinfo) { |
| 336 SkASSERT(cinfo != NULL); |
| 337 /* this gives about 30% performance improvement. In theory it may |
| 338 reduce the visual quality, in practice I'm not seeing a difference |
| 339 */ |
| 340 cinfo->do_fancy_upsampling = 0; |
| 341 |
| 342 /* this gives another few percents */ |
| 343 cinfo->do_block_smoothing = 0; |
| 344 } |
| 345 |
| 346 /** |
| 347 * Common code for setting the dct method. |
| 348 */ |
| 349 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct
* cinfo) { |
| 350 SkASSERT(cinfo != NULL); |
| 351 #ifdef DCT_IFAST_SUPPORTED |
| 352 if (decoder.getPreferQualityOverSpeed()) { |
| 353 cinfo->dct_method = JDCT_ISLOW; |
| 354 } else { |
| 355 cinfo->dct_method = JDCT_IFAST; |
| 356 } |
| 357 #else |
| 358 cinfo->dct_method = JDCT_ISLOW; |
| 359 #endif |
| 360 } |
| 361 |
| 362 SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin
fo) { |
| 363 SkASSERT(cinfo != NULL); |
| 364 |
| 365 SrcDepth srcDepth = k32Bit_SrcDepth; |
| 366 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) { |
| 367 srcDepth = k8BitGray_SrcDepth; |
| 368 } |
| 369 |
| 370 SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false); |
| 371 switch (config) { |
| 372 case SkBitmap::kA8_Config: |
| 373 // Only respect A8 config if the original is grayscale, |
| 374 // in which case we will treat the grayscale as alpha |
| 375 // values. |
| 376 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { |
| 377 config = SkBitmap::kARGB_8888_Config; |
| 378 } |
| 379 break; |
| 380 case SkBitmap::kARGB_8888_Config: |
| 381 // Fall through. |
| 382 case SkBitmap::kARGB_4444_Config: |
| 383 // Fall through. |
| 384 case SkBitmap::kRGB_565_Config: |
| 385 // These are acceptable destination configs. |
| 386 break; |
| 387 default: |
| 388 // Force all other configs to 8888. |
| 389 config = SkBitmap::kARGB_8888_Config; |
| 390 break; |
| 391 } |
| 392 |
| 393 switch (cinfo->jpeg_color_space) { |
| 394 case JCS_CMYK: |
| 395 // Fall through. |
| 396 case JCS_YCCK: |
| 397 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up |
| 398 // so libjpeg will give us CMYK samples back and we will later |
| 399 // manually convert them to RGB |
| 400 cinfo->out_color_space = JCS_CMYK; |
| 401 break; |
| 402 case JCS_GRAYSCALE: |
| 403 if (SkBitmap::kA8_Config == config) { |
| 404 cinfo->out_color_space = JCS_GRAYSCALE; |
| 405 break; |
| 406 } |
| 407 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB |
| 408 // config. Fall through to set to the default. |
| 409 default: |
| 410 cinfo->out_color_space = JCS_RGB; |
| 411 break; |
| 412 } |
| 413 return config; |
| 414 } |
| 415 |
| 416 #ifdef ANDROID_RGB |
| 417 /** |
| 418 * Based on the config and dither mode, adjust out_color_space and |
| 419 * dither_mode of cinfo. |
| 420 */ |
| 421 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, |
| 422 SkBitmap::Config config, |
| 423 const SkImageDecoder& decoder) { |
| 424 SkASSERT(cinfo != NULL); |
| 425 cinfo->dither_mode = JDITHER_NONE; |
| 426 if (JCS_CMYK == cinfo->out_color_space) { |
| 427 return; |
| 428 } |
| 429 switch(config) { |
| 430 case SkBitmap::kARGB_8888_Config: |
| 431 cinfo->out_color_space = JCS_RGBA_8888; |
| 432 break; |
| 433 case SkBitmap::kRGB_565_Config: |
| 434 cinfo->out_color_space = JCS_RGB_565; |
| 435 if (decoder.getDitherImage()) { |
| 436 cinfo->dither_mode = JDITHER_ORDERED; |
| 437 } |
| 438 break; |
| 439 default: |
| 440 break; |
| 441 } |
| 442 } |
| 443 #endif |
| 444 |
| 298 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { | 445 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { |
| 299 #ifdef TIME_DECODE | 446 #ifdef TIME_DECODE |
| 300 SkAutoTime atm("JPEG Decode"); | 447 SkAutoTime atm("JPEG Decode"); |
| 301 #endif | 448 #endif |
| 302 | 449 |
| 303 JPEGAutoClean autoClean; | 450 JPEGAutoClean autoClean; |
| 304 | 451 |
| 305 jpeg_decompress_struct cinfo; | 452 jpeg_decompress_struct cinfo; |
| 306 skjpeg_error_mgr errorManager; | |
| 307 skjpeg_source_mgr srcManager(stream, this); | 453 skjpeg_source_mgr srcManager(stream, this); |
| 308 | 454 |
| 309 cinfo.err = jpeg_std_error(&errorManager); | 455 skjpeg_error_mgr errorManager; |
| 310 errorManager.error_exit = skjpeg_error_exit; | 456 set_error_mgr(&cinfo, &errorManager); |
| 311 | 457 |
| 312 // All objects need to be instantiated before this setjmp call so that | 458 // All objects need to be instantiated before this setjmp call so that |
| 313 // they will be cleaned up properly if an error occurs. | 459 // they will be cleaned up properly if an error occurs. |
| 314 if (setjmp(errorManager.fJmpBuf)) { | 460 if (setjmp(errorManager.fJmpBuf)) { |
| 315 return return_false(cinfo, *bm, "setjmp"); | 461 return return_false(cinfo, *bm, "setjmp"); |
| 316 } | 462 } |
| 317 | 463 |
| 318 jpeg_create_decompress(&cinfo); | 464 initialize_info(&cinfo, &srcManager); |
| 319 autoClean.set(&cinfo); | 465 autoClean.set(&cinfo); |
| 320 | 466 |
| 321 overwrite_mem_buffer_size(&cinfo); | |
| 322 | |
| 323 //jpeg_stdio_src(&cinfo, file); | |
| 324 cinfo.src = &srcManager; | |
| 325 | |
| 326 int status = jpeg_read_header(&cinfo, true); | 467 int status = jpeg_read_header(&cinfo, true); |
| 327 if (status != JPEG_HEADER_OK) { | 468 if (status != JPEG_HEADER_OK) { |
| 328 return return_false(cinfo, *bm, "read_header"); | 469 return return_false(cinfo, *bm, "read_header"); |
| 329 } | 470 } |
| 330 | 471 |
| 331 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it | 472 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it |
| 332 can) much faster that we, just use their num/denom api to approximate | 473 can) much faster that we, just use their num/denom api to approximate |
| 333 the size. | 474 the size. |
| 334 */ | 475 */ |
| 335 int sampleSize = this->getSampleSize(); | 476 int sampleSize = this->getSampleSize(); |
| 336 | 477 |
| 337 #ifdef DCT_IFAST_SUPPORTED | 478 set_dct_method(*this, &cinfo); |
| 338 if (this->getPreferQualityOverSpeed()) { | |
| 339 cinfo.dct_method = JDCT_ISLOW; | |
| 340 } else { | |
| 341 cinfo.dct_method = JDCT_IFAST; | |
| 342 } | |
| 343 #else | |
| 344 cinfo.dct_method = JDCT_ISLOW; | |
| 345 #endif | |
| 346 | 479 |
| 347 cinfo.scale_num = 1; | 480 SkASSERT(1 == cinfo.scale_num); |
| 348 cinfo.scale_denom = sampleSize; | 481 cinfo.scale_denom = sampleSize; |
| 349 | 482 |
| 350 /* this gives about 30% performance improvement. In theory it may | 483 turn_off_visual_optimizations(&cinfo); |
| 351 reduce the visual quality, in practice I'm not seeing a difference | |
| 352 */ | |
| 353 cinfo.do_fancy_upsampling = 0; | |
| 354 | 484 |
| 355 /* this gives another few percents */ | 485 const SkBitmap::Config config = this->getBitmapConfig(&cinfo); |
| 356 cinfo.do_block_smoothing = 0; | |
| 357 | |
| 358 SrcDepth srcDepth = k32Bit_SrcDepth; | |
| 359 /* default format is RGB */ | |
| 360 if (cinfo.jpeg_color_space == JCS_CMYK) { | |
| 361 // libjpeg cannot convert from CMYK to RGB - here we set up | |
| 362 // so libjpeg will give us CMYK samples back and we will | |
| 363 // later manually convert them to RGB | |
| 364 cinfo.out_color_space = JCS_CMYK; | |
| 365 } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { | |
| 366 cinfo.out_color_space = JCS_GRAYSCALE; | |
| 367 srcDepth = k8BitGray_SrcDepth; | |
| 368 } else { | |
| 369 cinfo.out_color_space = JCS_RGB; | |
| 370 } | |
| 371 | |
| 372 SkBitmap::Config config = this->getPrefConfig(srcDepth, false); | |
| 373 // only these make sense for jpegs | |
| 374 if (SkBitmap::kA8_Config == config) { | |
| 375 if (cinfo.jpeg_color_space != JCS_GRAYSCALE) { | |
| 376 // Converting from a non grayscale image to A8 is | |
| 377 // not currently supported. | |
| 378 config = SkBitmap::kARGB_8888_Config; | |
| 379 // Change the output from jpeg back to RGB. | |
| 380 cinfo.out_color_space = JCS_RGB; | |
| 381 } | |
| 382 } else if (config != SkBitmap::kARGB_8888_Config && | |
| 383 config != SkBitmap::kARGB_4444_Config && | |
| 384 config != SkBitmap::kRGB_565_Config) { | |
| 385 config = SkBitmap::kARGB_8888_Config; | |
| 386 } | |
| 387 | 486 |
| 388 #ifdef ANDROID_RGB | 487 #ifdef ANDROID_RGB |
| 389 cinfo.dither_mode = JDITHER_NONE; | 488 adjust_out_color_space_and_dither(&cinfo, config, *this); |
| 390 if (SkBitmap::kARGB_8888_Config == config && JCS_CMYK != cinfo.out_color_spa
ce) { | |
| 391 cinfo.out_color_space = JCS_RGBA_8888; | |
| 392 } else if (SkBitmap::kRGB_565_Config == config && JCS_CMYK != cinfo.out_colo
r_space) { | |
| 393 cinfo.out_color_space = JCS_RGB_565; | |
| 394 if (this->getDitherImage()) { | |
| 395 cinfo.dither_mode = JDITHER_ORDERED; | |
| 396 } | |
| 397 } | |
| 398 #endif | 489 #endif |
| 399 | 490 |
| 400 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { | 491 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { |
| 401 bm->setConfig(config, cinfo.image_width, cinfo.image_height); | 492 bm->setConfig(config, cinfo.image_width, cinfo.image_height); |
| 402 bm->setIsOpaque(config != SkBitmap::kA8_Config); | 493 bm->setIsOpaque(config != SkBitmap::kA8_Config); |
| 403 return true; | 494 return true; |
| 404 } | 495 } |
| 405 | 496 |
| 406 /* image_width and image_height are the original dimensions, available | 497 /* image_width and image_height are the original dimensions, available |
| 407 after jpeg_read_header(). To see the scaled dimensions, we have to call | 498 after jpeg_read_header(). To see the scaled dimensions, we have to call |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 return true; | 636 return true; |
| 546 } | 637 } |
| 547 | 638 |
| 548 #ifdef SK_BUILD_FOR_ANDROID | 639 #ifdef SK_BUILD_FOR_ANDROID |
| 549 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
ght) { | 640 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei
ght) { |
| 550 | 641 |
| 551 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); | 642 SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (str
eam, this))); |
| 552 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); | 643 jpeg_decompress_struct* cinfo = imageIndex->cinfo(); |
| 553 | 644 |
| 554 skjpeg_error_mgr sk_err; | 645 skjpeg_error_mgr sk_err; |
| 555 cinfo->err = jpeg_std_error(&sk_err); | 646 set_error_mgr(cinfo, &sk_err); |
| 556 sk_err.error_exit = skjpeg_error_exit; | |
| 557 | 647 |
| 558 // All objects need to be instantiated before this setjmp call so that | 648 // All objects need to be instantiated before this setjmp call so that |
| 559 // they will be cleaned up properly if an error occurs. | 649 // they will be cleaned up properly if an error occurs. |
| 560 if (setjmp(sk_err.fJmpBuf)) { | 650 if (setjmp(sk_err.fJmpBuf)) { |
| 561 return false; | 651 return false; |
| 562 } | 652 } |
| 563 | 653 |
| 564 // create the cinfo used to create/build the huffmanIndex | 654 // create the cinfo used to create/build the huffmanIndex |
| 565 if (!imageIndex->initializeInfoAndReadHeader()) { | 655 if (!imageIndex->initializeInfoAndReadHeader()) { |
| 566 return false; | 656 return false; |
| 567 } | 657 } |
| 568 | 658 |
| 569 if (!imageIndex->buildHuffmanIndex()) { | 659 if (!imageIndex->buildHuffmanIndex()) { |
| 570 return false; | 660 return false; |
| 571 } | 661 } |
| 572 | 662 |
| 573 // destroy the cinfo used to create/build the huffman index | 663 // destroy the cinfo used to create/build the huffman index |
| 574 imageIndex->destroyInfo(); | 664 imageIndex->destroyInfo(); |
| 575 | 665 |
| 576 // Init decoder to image decode mode | 666 // Init decoder to image decode mode |
| 577 if (!imageIndex->initializeInfoAndReadHeader()) { | 667 if (!imageIndex->initializeInfoAndReadHeader()) { |
| 578 return false; | 668 return false; |
| 579 } | 669 } |
| 580 | 670 |
| 581 cinfo->out_color_space = JCS_RGBA_8888; | 671 // FIXME: This sets cinfo->out_color_space, which we may change later |
| 582 cinfo->do_fancy_upsampling = 0; | 672 // based on the config in onDecodeSubset. This should be fine, since |
| 583 cinfo->do_block_smoothing = 0; | 673 // jpeg_init_read_tile_scanline will check out_color_space again after |
| 674 // that change (when it calls jinit_color_deconverter). |
| 675 (void) this->getBitmapConfig(cinfo); |
| 676 |
| 677 turn_off_visual_optimizations(cinfo); |
| 584 | 678 |
| 585 // instead of jpeg_start_decompress() we start a tiled decompress | 679 // instead of jpeg_start_decompress() we start a tiled decompress |
| 586 if (!imageIndex->startTileDecompress()) { | 680 if (!imageIndex->startTileDecompress()) { |
| 587 return false; | 681 return false; |
| 588 } | 682 } |
| 589 | 683 |
| 590 SkASSERT(1 == cinfo->scale_num); | 684 SkASSERT(1 == cinfo->scale_num); |
| 591 *height = cinfo->output_height; | 685 fImageWidth = cinfo->output_width; |
| 592 *width = cinfo->output_width; | 686 fImageHeight = cinfo->output_height; |
| 593 fImageWidth = *width; | 687 |
| 594 fImageHeight = *height; | 688 if (width) { |
| 689 *width = fImageWidth; |
| 690 } |
| 691 if (height) { |
| 692 *height = fImageHeight; |
| 693 } |
| 595 | 694 |
| 596 SkDELETE(fImageIndex); | 695 SkDELETE(fImageIndex); |
| 597 fImageIndex = imageIndex.detach(); | 696 fImageIndex = imageIndex.detach(); |
| 598 | 697 |
| 599 return true; | 698 return true; |
| 600 } | 699 } |
| 601 | 700 |
| 602 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { | 701 bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { |
| 603 if (NULL == fImageIndex) { | 702 if (NULL == fImageIndex) { |
| 604 return false; | 703 return false; |
| 605 } | 704 } |
| 606 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); | 705 jpeg_decompress_struct* cinfo = fImageIndex->cinfo(); |
| 607 | 706 |
| 608 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); | 707 SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight); |
| 609 if (!rect.intersect(region)) { | 708 if (!rect.intersect(region)) { |
| 610 // If the requested region is entirely outside the image return false | 709 // If the requested region is entirely outside the image return false |
| 611 return false; | 710 return false; |
| 612 } | 711 } |
| 613 | 712 |
| 614 | 713 |
| 615 skjpeg_error_mgr errorManager; | 714 skjpeg_error_mgr errorManager; |
| 616 cinfo->err = jpeg_std_error(&errorManager); | 715 set_error_mgr(cinfo, &errorManager); |
| 617 errorManager.error_exit = skjpeg_error_exit; | 716 |
| 618 if (setjmp(errorManager.fJmpBuf)) { | 717 if (setjmp(errorManager.fJmpBuf)) { |
| 619 return false; | 718 return false; |
| 620 } | 719 } |
| 621 | 720 |
| 622 int requestedSampleSize = this->getSampleSize(); | 721 int requestedSampleSize = this->getSampleSize(); |
| 623 cinfo->scale_denom = requestedSampleSize; | 722 cinfo->scale_denom = requestedSampleSize; |
| 624 | 723 |
| 625 if (this->getPreferQualityOverSpeed()) { | 724 set_dct_method(*this, cinfo); |
| 626 cinfo->dct_method = JDCT_ISLOW; | |
| 627 } else { | |
| 628 cinfo->dct_method = JDCT_IFAST; | |
| 629 } | |
| 630 | 725 |
| 631 SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); | 726 const SkBitmap::Config config = this->getBitmapConfig(cinfo); |
| 632 if (config != SkBitmap::kARGB_8888_Config && | |
| 633 config != SkBitmap::kARGB_4444_Config && | |
| 634 config != SkBitmap::kRGB_565_Config) { | |
| 635 config = SkBitmap::kARGB_8888_Config; | |
| 636 } | |
| 637 | |
| 638 /* default format is RGB */ | |
| 639 cinfo->out_color_space = JCS_RGB; | |
| 640 | |
| 641 #ifdef ANDROID_RGB | 727 #ifdef ANDROID_RGB |
| 642 cinfo->dither_mode = JDITHER_NONE; | 728 adjust_out_color_space_and_dither(cinfo, config, *this); |
| 643 if (SkBitmap::kARGB_8888_Config == config) { | |
| 644 cinfo->out_color_space = JCS_RGBA_8888; | |
| 645 } else if (SkBitmap::kRGB_565_Config == config) { | |
| 646 cinfo->out_color_space = JCS_RGB_565; | |
| 647 if (this->getDitherImage()) { | |
| 648 cinfo->dither_mode = JDITHER_ORDERED; | |
| 649 } | |
| 650 } | |
| 651 #endif | 729 #endif |
| 652 | 730 |
| 653 int startX = rect.fLeft; | 731 int startX = rect.fLeft; |
| 654 int startY = rect.fTop; | 732 int startY = rect.fTop; |
| 655 int width = rect.width(); | 733 int width = rect.width(); |
| 656 int height = rect.height(); | 734 int height = rect.height(); |
| 657 | 735 |
| 658 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), | 736 jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), |
| 659 &startX, &startY, &width, &height); | 737 &startX, &startY, &width, &height); |
| 660 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); | 738 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 } | 1153 } |
| 1076 | 1154 |
| 1077 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { | 1155 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { |
| 1078 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; | 1156 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; |
| 1079 } | 1157 } |
| 1080 | 1158 |
| 1081 | 1159 |
| 1082 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); | 1160 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); |
| 1083 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg
); | 1161 static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg
); |
| 1084 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efact
ory); | 1162 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efact
ory); |
| OLD | NEW |