1 /* 2 * Copyright 2007, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "SkImageDecoder.h" 18 #include "SkImageEncoder.h" 19 #include "SkJpegUtility.h" 20 #include "SkColorPriv.h" 21 #include "SkDither.h" 22 #include "SkScaledBitmapSampler.h" 23 #include "SkStream.h" 24 #include "SkTemplates.h" 25 #include "SkUtils.h" 26 #include "SkRect.h" 27 #include "SkCanvas.h" 28 29 #include <stdio.h> 30 extern "C" { 31 #include "jpeglib.h" 32 #include "jerror.h" 33 } 34 35 #ifdef ANDROID 36 #include <cutils/properties.h> 37 38 // Key to lookup the size of memory buffer set in system property 39 static const char KEY_MEM_CAP[] = "ro.media.dec.jpeg.memcap"; 40 #endif 41 42 // this enables timing code to report milliseconds for an encode 43 //#define TIME_ENCODE 44 //#define TIME_DECODE 45 46 // this enables our rgb->yuv code, which is faster than libjpeg on ARM 47 // disable for the moment, as we have some glitches when width != multiple of 4 48 #define WE_CONVERT_TO_YUV 49 50 ////////////////////////////////////////////////////////////////////////// 51 ////////////////////////////////////////////////////////////////////////// 52 53 class SkJPEGImageIndex { 54 public: 55 SkJPEGImageIndex() {} 56 virtual ~SkJPEGImageIndex() { 57 jpeg_destroy_huffman_index(index); 58 delete cinfo->src; 59 jpeg_finish_decompress(cinfo); 60 jpeg_destroy_decompress(cinfo); 61 free(cinfo); 62 } 63 jpeg_decompress_struct *cinfo; 64 huffman_index *index; 65 }; 66 67 68 class SkJPEGImageDecoder : public SkImageDecoder { 69 public: 70 SkJPEGImageDecoder() { 71 index = NULL; 72 } 73 ~SkJPEGImageDecoder() { 74 if (index) 75 delete index; 76 } 77 virtual Format getFormat() const { 78 return kJPEG_Format; 79 } 80 protected: 81 virtual bool onBuildTileIndex(SkStream *stream, 82 int *width, int *height); 83 virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect); 84 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); 85 private: 86 SkJPEGImageIndex *index; 87 }; 88 89 ////////////////////////////////////////////////////////////////////////// 90 91 #include "SkTime.h" 92 93 class AutoTimeMillis { 94 public: 95 AutoTimeMillis(const char label[]) : fLabel(label) { 96 if (!fLabel) { 97 fLabel = ""; 98 } 99 fNow = SkTime::GetMSecs(); 100 } 101 ~AutoTimeMillis() { 102 SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow); 103 } 104 private: 105 const char* fLabel; 106 SkMSec fNow; 107 }; 108 109 /* Automatically clean up after throwing an exception */ 110 class JPEGAutoClean { 111 public: 112 JPEGAutoClean(): cinfo_ptr(NULL) {} 113 ~JPEGAutoClean() { 114 if (cinfo_ptr) { 115 jpeg_destroy_decompress(cinfo_ptr); 116 } 117 } 118 void set(jpeg_decompress_struct* info) { 119 cinfo_ptr = info; 120 } 121 private: 122 jpeg_decompress_struct* cinfo_ptr; 123 }; 124 125 #ifdef ANDROID 126 /* Check if the memory cap property is set. 127 If so, use the memory size for jpeg decode. 128 */ 129 static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) { 130 #ifdef ANDROID_LARGE_MEMORY_DEVICE 131 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 132 #else 133 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; 134 #endif 135 } 136 #endif 137 138 139 /////////////////////////////////////////////////////////////////////////////// 140 141 /* If we need to better match the request, we might examine the image and 142 output dimensions, and determine if the downsampling jpeg provided is 143 not sufficient. If so, we can recompute a modified sampleSize value to 144 make up the difference. 145 146 To skip this additional scaling, just set sampleSize = 1; below. 147 */ 148 static int recompute_sampleSize(int sampleSize, 149 const jpeg_decompress_struct& cinfo) { 150 return sampleSize * cinfo.output_width / cinfo.image_width; 151 } 152 153 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) { 154 /* These are initialized to 0, so if they have non-zero values, we assume 155 they are "valid" (i.e. have been computed by libjpeg) 156 */ 157 return cinfo.output_width != 0 && cinfo.output_height != 0; 158 } 159 160 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, 161 int count) { 162 for (int i = 0; i < count; i++) { 163 JSAMPLE* rowptr = (JSAMPLE*)buffer; 164 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1); 165 if (row_count != 1) { 166 return false; 167 } 168 } 169 return true; 170 } 171 172 static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo, 173 huffman_index *index, void* buffer, 174 int count) { 175 for (int i = 0; i < count; i++) { 176 JSAMPLE* rowptr = (JSAMPLE*)buffer; 177 int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr); 178 if (row_count != 1) { 179 return false; 180 } 181 } 182 return true; 183 } 184 185 // This guy exists just to aid in debugging, as it allows debuggers to just 186 // set a break-point in one place to see all error exists. 187 static bool return_false(const jpeg_decompress_struct& cinfo, 188 const SkBitmap& bm, const char msg[]) { 189 #ifdef SK_DEBUG 190 SkDebugf("libjpeg error %d <%s> from %s [%d %d]", cinfo.err->msg_code, 191 cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg, 192 bm.width(), bm.height()); 193 #endif 194 return false; // must always return false 195 } 196 197 bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 198 #ifdef TIME_DECODE 199 AutoTimeMillis atm("JPEG Decode"); 200 #endif 201 202 SkAutoMalloc srcStorage; 203 JPEGAutoClean autoClean; 204 205 jpeg_decompress_struct cinfo; 206 skjpeg_error_mgr sk_err; 207 skjpeg_source_mgr sk_stream(stream, this, false); 208 209 cinfo.err = jpeg_std_error(&sk_err); 210 sk_err.error_exit = skjpeg_error_exit; 211 212 // All objects need to be instantiated before this setjmp call so that 213 // they will be cleaned up properly if an error occurs. 214 if (setjmp(sk_err.fJmpBuf)) { 215 return return_false(cinfo, *bm, "setjmp"); 216 } 217 218 jpeg_create_decompress(&cinfo); 219 autoClean.set(&cinfo); 220 221 #ifdef ANDROID 222 overwrite_mem_buffer_size(&cinfo); 223 #endif 224 225 //jpeg_stdio_src(&cinfo, file); 226 cinfo.src = &sk_stream; 227 228 int status = jpeg_read_header(&cinfo, true); 229 if (status != JPEG_HEADER_OK) { 230 return return_false(cinfo, *bm, "read_header"); 231 } 232 233 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it 234 can) much faster that we, just use their num/denom api to approximate 235 the size. 236 */ 237 int sampleSize = this->getSampleSize(); 238 239 if (this->getPreferQualityOverSpeed()) { 240 cinfo.dct_method = JDCT_ISLOW; 241 } else { 242 cinfo.dct_method = JDCT_IFAST; 243 } 244 245 cinfo.scale_num = 1; 246 cinfo.scale_denom = sampleSize; 247 248 /* this gives about 30% performance improvement. In theory it may 249 reduce the visual quality, in practice I'm not seeing a difference 250 */ 251 cinfo.do_fancy_upsampling = 0; 252 253 /* this gives another few percents */ 254 cinfo.do_block_smoothing = 0; 255 256 /* default format is RGB */ 257 cinfo.out_color_space = JCS_RGB; 258 259 SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); 260 // only these make sense for jpegs 261 if (config != SkBitmap::kARGB_8888_Config && 262 config != SkBitmap::kARGB_4444_Config && 263 config != SkBitmap::kRGB_565_Config) { 264 config = SkBitmap::kARGB_8888_Config; 265 } 266 267 #ifdef ANDROID_RGB 268 cinfo.dither_mode = JDITHER_NONE; 269 if (config == SkBitmap::kARGB_8888_Config) { 270 cinfo.out_color_space = JCS_RGBA_8888; 271 } else if (config == SkBitmap::kRGB_565_Config) { 272 cinfo.out_color_space = JCS_RGB_565; 273 if (this->getDitherImage()) { 274 cinfo.dither_mode = JDITHER_ORDERED; 275 } 276 } 277 #endif 278 279 if (sampleSize == 1 && mode == SkImageDecoder::kDecodeBounds_Mode) { 280 bm->setConfig(config, cinfo.image_width, cinfo.image_height); 281 bm->setIsOpaque(true); 282 return true; 283 } 284 285 /* image_width and image_height are the original dimensions, available 286 after jpeg_read_header(). To see the scaled dimensions, we have to call 287 jpeg_start_decompress(), and then read output_width and output_height. 288 */ 289 if (!jpeg_start_decompress(&cinfo)) { 290 /* If we failed here, we may still have enough information to return 291 to the caller if they just wanted (subsampled bounds). If sampleSize 292 was 1, then we would have already returned. Thus we just check if 293 we're in kDecodeBounds_Mode, and that we have valid output sizes. 294 295 One reason to fail here is that we have insufficient stream data 296 to complete the setup. However, output dimensions seem to get 297 computed very early, which is why this special check can pay off. 298 */ 299 if (SkImageDecoder::kDecodeBounds_Mode == mode && 300 valid_output_dimensions(cinfo)) { 301 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height, 302 recompute_sampleSize(sampleSize, cinfo)); 303 bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight()); 304 bm->setIsOpaque(true); 305 return true; 306 } else { 307 return return_false(cinfo, *bm, "start_decompress"); 308 } 309 } 310 sampleSize = recompute_sampleSize(sampleSize, cinfo); 311 312 // should we allow the Chooser (if present) to pick a config for us??? 313 if (!this->chooseFromOneChoice(config, cinfo.output_width, 314 cinfo.output_height)) { 315 return return_false(cinfo, *bm, "chooseFromOneChoice"); 316 } 317 318 #ifdef ANDROID_RGB 319 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 320 a significant performance boost. 321 */ 322 if (sampleSize == 1 && 323 ((config == SkBitmap::kARGB_8888_Config && 324 cinfo.out_color_space == JCS_RGBA_8888) || 325 (config == SkBitmap::kRGB_565_Config && 326 cinfo.out_color_space == JCS_RGB_565))) 327 { 328 bm->lockPixels(); 329 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 330 bm->unlockPixels(); 331 bool reuseBitmap = (rowptr != NULL); 332 if (reuseBitmap && ((int) cinfo.output_width != bm->width() || 333 (int) cinfo.output_height != bm->height())) { 334 // Dimensions must match 335 return false; 336 } 337 338 if (!reuseBitmap) { 339 bm->setConfig(config, cinfo.output_width, cinfo.output_height); 340 bm->setIsOpaque(true); 341 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 342 return true; 343 } 344 if (!this->allocPixelRef(bm, NULL)) { 345 return return_false(cinfo, *bm, "allocPixelRef"); 346 } 347 } else if (SkImageDecoder::kDecodeBounds_Mode == mode) { 348 return true; 349 } 350 SkAutoLockPixels alp(*bm); 351 rowptr = (JSAMPLE*)bm->getPixels(); 352 INT32 const bpr = bm->rowBytes(); 353 354 while (cinfo.output_scanline < cinfo.output_height) { 355 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 356 // if row_count == 0, then we didn't get a scanline, so abort. 357 // if we supported partial images, we might return true in this case 358 if (0 == row_count) { 359 return return_false(cinfo, *bm, "read_scanlines"); 360 } 361 if (this->shouldCancelDecode()) { 362 return return_false(cinfo, *bm, "shouldCancelDecode"); 363 } 364 rowptr += bpr; 365 } 366 if (reuseBitmap) { 367 bm->notifyPixelsChanged(); 368 } 369 jpeg_finish_decompress(&cinfo); 370 return true; 371 } 372 #endif 373 374 // check for supported formats 375 SkScaledBitmapSampler::SrcConfig sc; 376 if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) { 377 sc = SkScaledBitmapSampler::kRGB; 378 #ifdef ANDROID_RGB 379 } else if (JCS_RGBA_8888 == cinfo.out_color_space) { 380 sc = SkScaledBitmapSampler::kRGBX; 381 } else if (JCS_RGB_565 == cinfo.out_color_space) { 382 sc = SkScaledBitmapSampler::kRGB_565; 383 #endif 384 } else if (1 == cinfo.out_color_components && 385 JCS_GRAYSCALE == cinfo.out_color_space) { 386 sc = SkScaledBitmapSampler::kGray; 387 } else { 388 return return_false(cinfo, *bm, "jpeg colorspace"); 389 } 390 391 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, 392 sampleSize); 393 394 bm->lockPixels(); 395 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 396 bool reuseBitmap = (rowptr != NULL); 397 bm->unlockPixels(); 398 if (reuseBitmap && (sampler.scaledWidth() != bm->width() || 399 sampler.scaledHeight() != bm->height())) { 400 // Dimensions must match 401 return false; 402 } 403 404 if (!reuseBitmap) { 405 bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 406 // jpegs are always opaque (i.e. have no per-pixel alpha) 407 bm->setIsOpaque(true); 408 409 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 410 return true; 411 } 412 if (!this->allocPixelRef(bm, NULL)) { 413 return return_false(cinfo, *bm, "allocPixelRef"); 414 } 415 } else if (SkImageDecoder::kDecodeBounds_Mode == mode) { 416 return true; 417 } 418 419 SkAutoLockPixels alp(*bm); 420 if (!sampler.begin(bm, sc, this->getDitherImage())) { 421 return return_false(cinfo, *bm, "sampler.begin"); 422 } 423 424 uint8_t* srcRow = (uint8_t*)srcStorage.alloc(cinfo.output_width * 4); 425 426 // Possibly skip initial rows [sampler.srcY0] 427 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 428 return return_false(cinfo, *bm, "skip rows"); 429 } 430 431 // now loop through scanlines until y == bm->height() - 1 432 for (int y = 0;; y++) { 433 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 434 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 435 if (0 == row_count) { 436 return return_false(cinfo, *bm, "read_scanlines"); 437 } 438 if (this->shouldCancelDecode()) { 439 return return_false(cinfo, *bm, "shouldCancelDecode"); 440 } 441 442 sampler.next(srcRow); 443 if (bm->height() - 1 == y) { 444 // we're done 445 break; 446 } 447 448 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) { 449 return return_false(cinfo, *bm, "skip rows"); 450 } 451 } 452 453 // we formally skip the rest, so we don't get a complaint from libjpeg 454 if (!skip_src_rows(&cinfo, srcRow, 455 cinfo.output_height - cinfo.output_scanline)) { 456 return return_false(cinfo, *bm, "skip rows"); 457 } 458 if (reuseBitmap) { 459 bm->notifyPixelsChanged(); 460 } 461 jpeg_finish_decompress(&cinfo); 462 463 // SkDebugf("------------------- bm2 size %d [%d %d] %d\n", bm->getSize(), bm->width(), bm->height(), bm->config()); 464 return true; 465 } 466 467 bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, 468 int *width, int *height) { 469 SkAutoMalloc srcStorage; 470 SkJPEGImageIndex *index = new SkJPEGImageIndex; 471 472 jpeg_decompress_struct *cinfo = (jpeg_decompress_struct*) 473 malloc(sizeof(jpeg_decompress_struct)); 474 skjpeg_error_mgr sk_err; 475 skjpeg_source_mgr *sk_stream = 476 new skjpeg_source_mgr(stream, this, true); 477 if (cinfo == NULL || sk_stream == NULL) { 478 return false; 479 } 480 481 cinfo->err = jpeg_std_error(&sk_err); 482 sk_err.error_exit = skjpeg_error_exit; 483 484 // All objects need to be instantiated before this setjmp call so that 485 // they will be cleaned up properly if an error occurs. 486 if (setjmp(sk_err.fJmpBuf)) { 487 return false; 488 } 489 490 jpeg_create_decompress(cinfo); 491 cinfo->do_fancy_upsampling = 0; 492 cinfo->do_block_smoothing = 0; 493 494 #ifdef ANDROID 495 overwrite_mem_buffer_size(cinfo); 496 #endif 497 498 cinfo->src = sk_stream; 499 int status = jpeg_read_header(cinfo, true); 500 if (status != JPEG_HEADER_OK) { 501 return false; 502 } 503 index->index = (huffman_index*)malloc(sizeof(huffman_index)); 504 jpeg_create_huffman_index(cinfo, index->index); 505 506 cinfo->scale_num = 1; 507 cinfo->scale_denom = 1; 508 if (!jpeg_build_huffman_index(cinfo, index->index)) { 509 return false; 510 } 511 if (fReporter) 512 fReporter->reportMemory(index->index->mem_used); 513 jpeg_destroy_decompress(cinfo); 514 515 516 // Init decoder to image decode mode 517 jpeg_create_decompress(cinfo); 518 519 #ifdef ANDROID 520 overwrite_mem_buffer_size(cinfo); 521 #endif 522 523 cinfo->src = sk_stream; 524 status = jpeg_read_header(cinfo,true); 525 if (status != JPEG_HEADER_OK) { 526 return false; 527 } 528 cinfo->out_color_space = JCS_RGBA_8888; 529 cinfo->do_fancy_upsampling = 0; 530 cinfo->do_block_smoothing = 0; 531 //jpeg_start_decompress(cinfo); 532 jpeg_start_tile_decompress(cinfo); 533 534 cinfo->scale_num = 1; 535 index->cinfo = cinfo; 536 *height = cinfo->output_height; 537 *width = cinfo->output_width; 538 539 this->index = index; 540 return true; 541 } 542 543 bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) { 544 if (index == NULL) { 545 return false; 546 } 547 int startX = region.fLeft; 548 int startY = region.fTop; 549 int width = region.width(); 550 int height = region.height(); 551 jpeg_decompress_struct *cinfo = index->cinfo; 552 SkAutoMalloc srcStorage; 553 skjpeg_error_mgr sk_err; 554 cinfo->err = jpeg_std_error(&sk_err); 555 sk_err.error_exit = skjpeg_error_exit; 556 if (setjmp(sk_err.fJmpBuf)) { 557 return false; 558 } 559 int requestedSampleSize = this->getSampleSize(); 560 cinfo->scale_denom = requestedSampleSize; 561 562 if (this->getPreferQualityOverSpeed()) { 563 cinfo->dct_method = JDCT_ISLOW; 564 } else { 565 cinfo->dct_method = JDCT_IFAST; 566 } 567 568 SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); 569 if (config != SkBitmap::kARGB_8888_Config && 570 config != SkBitmap::kARGB_4444_Config && 571 config != SkBitmap::kRGB_565_Config) { 572 config = SkBitmap::kARGB_8888_Config; 573 } 574 575 /* default format is RGB */ 576 cinfo->out_color_space = JCS_RGB; 577 578 #ifdef ANDROID_RGB 579 cinfo->dither_mode = JDITHER_NONE; 580 if (config == SkBitmap::kARGB_8888_Config) { 581 cinfo->out_color_space = JCS_RGBA_8888; 582 } else if (config == SkBitmap::kRGB_565_Config) { 583 cinfo->out_color_space = JCS_RGB_565; 584 if (this->getDitherImage()) { 585 cinfo->dither_mode = JDITHER_ORDERED; 586 } 587 } 588 #endif 589 590 int oriStartX = startX; 591 int oriStartY = startY; 592 int oriWidth = width; 593 int oriHeight = height; 594 jpeg_init_read_tile_scanline(cinfo, index->index, 595 &startX, &startY, &width, &height); 596 int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo); 597 int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size); 598 599 SkBitmap *bitmap = new SkBitmap; 600 SkAutoTDelete<SkBitmap> adb(bitmap); 601 602 #ifdef ANDROID_RGB 603 /* short-circuit the SkScaledBitmapSampler when possible, as this gives 604 a significant performance boost. 605 */ 606 if (skiaSampleSize == 1 && 607 ((config == SkBitmap::kARGB_8888_Config && 608 cinfo->out_color_space == JCS_RGBA_8888) || 609 (config == SkBitmap::kRGB_565_Config && 610 cinfo->out_color_space == JCS_RGB_565))) 611 { 612 bitmap->setConfig(config, cinfo->output_width, height); 613 bitmap->setIsOpaque(true); 614 if (!this->allocPixelRef(bitmap, NULL)) { 615 return return_false(*cinfo, *bitmap, "allocPixelRef"); 616 } 617 SkAutoLockPixels alp(*bitmap); 618 JSAMPLE* rowptr = (JSAMPLE*)bitmap->getPixels(); 619 INT32 const bpr = bitmap->rowBytes(); 620 int row_total_count = 0; 621 622 while (row_total_count < height) { 623 int row_count = jpeg_read_tile_scanline(cinfo, 624 index->index, &rowptr); 625 // if row_count == 0, then we didn't get a scanline, so abort. 626 // if we supported partial images, we might return true in this case 627 if (0 == row_count) { 628 return return_false(*cinfo, *bitmap, "read_scanlines"); 629 } 630 if (this->shouldCancelDecode()) { 631 return return_false(*cinfo, *bitmap, "shouldCancelDecode"); 632 } 633 row_total_count += row_count; 634 rowptr += bpr; 635 } 636 cropBitmap(bm, bitmap, actualSampleSize, oriStartX, oriStartY, 637 oriWidth, oriHeight, startX, startY); 638 return true; 639 } 640 #endif 641 // check for supported formats 642 SkScaledBitmapSampler::SrcConfig sc; 643 if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) { 644 sc = SkScaledBitmapSampler::kRGB; 645 #ifdef ANDROID_RGB 646 } else if (JCS_RGBA_8888 == cinfo->out_color_space) { 647 sc = SkScaledBitmapSampler::kRGBX; 648 } else if (JCS_RGB_565 == cinfo->out_color_space) { 649 sc = SkScaledBitmapSampler::kRGB_565; 650 #endif 651 } else if (1 == cinfo->out_color_components && 652 JCS_GRAYSCALE == cinfo->out_color_space) { 653 sc = SkScaledBitmapSampler::kGray; 654 } else { 655 return return_false(*cinfo, *bm, "jpeg colorspace"); 656 } 657 658 SkScaledBitmapSampler sampler(width, height, skiaSampleSize); 659 660 bitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); 661 bitmap->setIsOpaque(true); 662 663 if (!this->allocPixelRef(bitmap, NULL)) { 664 return return_false(*cinfo, *bitmap, "allocPixelRef"); 665 } 666 667 SkAutoLockPixels alp(*bitmap); 668 if (!sampler.begin(bitmap, sc, this->getDitherImage())) { 669 return return_false(*cinfo, *bitmap, "sampler.begin"); 670 } 671 672 uint8_t* srcRow = (uint8_t*)srcStorage.alloc(width * 4); 673 674 // Possibly skip initial rows [sampler.srcY0] 675 if (!skip_src_rows_tile(cinfo, index->index, srcRow, sampler.srcY0())) { 676 return return_false(*cinfo, *bitmap, "skip rows"); 677 } 678 679 // now loop through scanlines until y == bitmap->height() - 1 680 for (int y = 0;; y++) { 681 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 682 int row_count = jpeg_read_tile_scanline(cinfo, index->index, &rowptr); 683 if (0 == row_count) { 684 return return_false(*cinfo, *bitmap, "read_scanlines"); 685 } 686 if (this->shouldCancelDecode()) { 687 return return_false(*cinfo, *bitmap, "shouldCancelDecode"); 688 } 689 690 sampler.next(srcRow); 691 if (bitmap->height() - 1 == y) { 692 // we're done 693 break; 694 } 695 696 if (!skip_src_rows_tile(cinfo, index->index, srcRow, 697 sampler.srcDY() - 1)) { 698 return return_false(*cinfo, *bitmap, "skip rows"); 699 } 700 } 701 cropBitmap(bm, bitmap, actualSampleSize, oriStartX, oriStartY, 702 oriWidth, oriHeight, startX, startY); 703 return true; 704 } 705 706 /////////////////////////////////////////////////////////////////////////////// 707 708 #include "SkColorPriv.h" 709 710 // taken from jcolor.c in libjpeg 711 #if 0 // 16bit - precise but slow 712 #define CYR 19595 // 0.299 713 #define CYG 38470 // 0.587 714 #define CYB 7471 // 0.114 715 716 #define CUR -11059 // -0.16874 717 #define CUG -21709 // -0.33126 718 #define CUB 32768 // 0.5 719 720 #define CVR 32768 // 0.5 721 #define CVG -27439 // -0.41869 722 #define CVB -5329 // -0.08131 723 724 #define CSHIFT 16 725 #else // 8bit - fast, slightly less precise 726 #define CYR 77 // 0.299 727 #define CYG 150 // 0.587 728 #define CYB 29 // 0.114 729 730 #define CUR -43 // -0.16874 731 #define CUG -85 // -0.33126 732 #define CUB 128 // 0.5 733 734 #define CVR 128 // 0.5 735 #define CVG -107 // -0.41869 736 #define CVB -21 // -0.08131 737 738 #define CSHIFT 8 739 #endif 740 741 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) { 742 int r = SkGetPackedR32(c); 743 int g = SkGetPackedG32(c); 744 int b = SkGetPackedB32(c); 745 746 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT; 747 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT; 748 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT; 749 750 dst[0] = SkToU8(y); 751 dst[1] = SkToU8(u + 128); 752 dst[2] = SkToU8(v + 128); 753 } 754 755 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) { 756 int r = SkGetPackedR4444(c); 757 int g = SkGetPackedG4444(c); 758 int b = SkGetPackedB4444(c); 759 760 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4); 761 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4); 762 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4); 763 764 dst[0] = SkToU8(y); 765 dst[1] = SkToU8(u + 128); 766 dst[2] = SkToU8(v + 128); 767 } 768 769 static void rgb2yuv_16(uint8_t dst[], U16CPU c) { 770 int r = SkGetPackedR16(c); 771 int g = SkGetPackedG16(c); 772 int b = SkGetPackedB16(c); 773 774 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2); 775 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2); 776 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2); 777 778 dst[0] = SkToU8(y); 779 dst[1] = SkToU8(u + 128); 780 dst[2] = SkToU8(v + 128); 781 } 782 783 /////////////////////////////////////////////////////////////////////////////// 784 785 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 786 const void* SK_RESTRICT src, int width, 787 const SkPMColor* SK_RESTRICT ctable); 788 789 static void Write_32_YUV(uint8_t* SK_RESTRICT dst, 790 const void* SK_RESTRICT srcRow, int width, 791 const SkPMColor*) { 792 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 793 while (--width >= 0) { 794 #ifdef WE_CONVERT_TO_YUV 795 rgb2yuv_32(dst, *src++); 796 #else 797 uint32_t c = *src++; 798 dst[0] = SkGetPackedR32(c); 799 dst[1] = SkGetPackedG32(c); 800 dst[2] = SkGetPackedB32(c); 801 #endif 802 dst += 3; 803 } 804 } 805 806 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst, 807 const void* SK_RESTRICT srcRow, int width, 808 const SkPMColor*) { 809 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 810 while (--width >= 0) { 811 #ifdef WE_CONVERT_TO_YUV 812 rgb2yuv_4444(dst, *src++); 813 #else 814 SkPMColor16 c = *src++; 815 dst[0] = SkPacked4444ToR32(c); 816 dst[1] = SkPacked4444ToG32(c); 817 dst[2] = SkPacked4444ToB32(c); 818 #endif 819 dst += 3; 820 } 821 } 822 823 static void Write_16_YUV(uint8_t* SK_RESTRICT dst, 824 const void* SK_RESTRICT srcRow, int width, 825 const SkPMColor*) { 826 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 827 while (--width >= 0) { 828 #ifdef WE_CONVERT_TO_YUV 829 rgb2yuv_16(dst, *src++); 830 #else 831 uint16_t c = *src++; 832 dst[0] = SkPacked16ToR32(c); 833 dst[1] = SkPacked16ToG32(c); 834 dst[2] = SkPacked16ToB32(c); 835 #endif 836 dst += 3; 837 } 838 } 839 840 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst, 841 const void* SK_RESTRICT srcRow, int width, 842 const SkPMColor* SK_RESTRICT ctable) { 843 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 844 while (--width >= 0) { 845 #ifdef WE_CONVERT_TO_YUV 846 rgb2yuv_32(dst, ctable[*src++]); 847 #else 848 uint32_t c = ctable[*src++]; 849 dst[0] = SkGetPackedR32(c); 850 dst[1] = SkGetPackedG32(c); 851 dst[2] = SkGetPackedB32(c); 852 #endif 853 dst += 3; 854 } 855 } 856 857 static WriteScanline ChooseWriter(const SkBitmap& bm) { 858 switch (bm.config()) { 859 case SkBitmap::kARGB_8888_Config: 860 return Write_32_YUV; 861 case SkBitmap::kRGB_565_Config: 862 return Write_16_YUV; 863 case SkBitmap::kARGB_4444_Config: 864 return Write_4444_YUV; 865 case SkBitmap::kIndex8_Config: 866 return Write_Index_YUV; 867 default: 868 return NULL; 869 } 870 } 871 872 class SkJPEGImageEncoder : public SkImageEncoder { 873 protected: 874 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 875 #ifdef TIME_ENCODE 876 AutoTimeMillis atm("JPEG Encode"); 877 #endif 878 879 const WriteScanline writer = ChooseWriter(bm); 880 if (NULL == writer) { 881 return false; 882 } 883 884 SkAutoLockPixels alp(bm); 885 if (NULL == bm.getPixels()) { 886 return false; 887 } 888 889 jpeg_compress_struct cinfo; 890 skjpeg_error_mgr sk_err; 891 skjpeg_destination_mgr sk_wstream(stream); 892 893 // allocate these before set call setjmp 894 SkAutoMalloc oneRow; 895 SkAutoLockColors ctLocker; 896 897 cinfo.err = jpeg_std_error(&sk_err); 898 sk_err.error_exit = skjpeg_error_exit; 899 if (setjmp(sk_err.fJmpBuf)) { 900 return false; 901 } 902 jpeg_create_compress(&cinfo); 903 904 cinfo.dest = &sk_wstream; 905 cinfo.image_width = bm.width(); 906 cinfo.image_height = bm.height(); 907 cinfo.input_components = 3; 908 #ifdef WE_CONVERT_TO_YUV 909 cinfo.in_color_space = JCS_YCbCr; 910 #else 911 cinfo.in_color_space = JCS_RGB; 912 #endif 913 cinfo.input_gamma = 1; 914 915 jpeg_set_defaults(&cinfo); 916 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 917 cinfo.dct_method = JDCT_IFAST; 918 919 jpeg_start_compress(&cinfo, TRUE); 920 921 const int width = bm.width(); 922 uint8_t* oneRowP = (uint8_t*)oneRow.alloc(width * 3); 923 924 const SkPMColor* colors = ctLocker.lockColors(bm); 925 const void* srcRow = bm.getPixels(); 926 927 while (cinfo.next_scanline < cinfo.image_height) { 928 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 929 930 writer(oneRowP, srcRow, width, colors); 931 row_pointer[0] = oneRowP; 932 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 933 srcRow = (const void*)((const char*)srcRow + bm.rowBytes()); 934 } 935 936 jpeg_finish_compress(&cinfo); 937 jpeg_destroy_compress(&cinfo); 938 939 return true; 940 } 941 }; 942 943 /////////////////////////////////////////////////////////////////////////////// 944 945 #include "SkTRegistry.h" 946 947 static SkImageDecoder* DFactory(SkStream* stream) { 948 static const char gHeader[] = { 0xFF, 0xD8, 0xFF }; 949 static const size_t HEADER_SIZE = sizeof(gHeader); 950 951 char buffer[HEADER_SIZE]; 952 size_t len = stream->read(buffer, HEADER_SIZE); 953 954 if (len != HEADER_SIZE) { 955 return NULL; // can't read enough 956 } 957 if (memcmp(buffer, gHeader, HEADER_SIZE)) { 958 return NULL; 959 } 960 return SkNEW(SkJPEGImageDecoder); 961 } 962 963 static SkImageEncoder* EFactory(SkImageEncoder::Type t) { 964 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 965 } 966 967 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory); 968 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory); 969