Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 24449003: Make Jpeg decoding more fault resistant. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: description change Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
11 #include "SkJpegUtility.h" 11 #include "SkJpegUtility.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkDither.h" 13 #include "SkDither.h"
14 #include "SkScaledBitmapSampler.h" 14 #include "SkScaledBitmapSampler.h"
15 #include "SkStream.h" 15 #include "SkStream.h"
16 #include "SkTemplates.h" 16 #include "SkTemplates.h"
17 #include "SkTime.h" 17 #include "SkTime.h"
18 #include "SkUtils.h" 18 #include "SkUtils.h"
19 #include "SkRect.h" 19 #include "SkRect.h"
20 #include "SkCanvas.h" 20 #include "SkCanvas.h"
21 21
22 #if defined(SK_DEBUG)
23 #include "SkRTConf.h" // SK_CONF_DECLARE
24 #endif // defined(SK_DEBUG)
25
22 #include <stdio.h> 26 #include <stdio.h>
23 extern "C" { 27 extern "C" {
24 #include "jpeglib.h" 28 #include "jpeglib.h"
25 #include "jerror.h" 29 #include "jerror.h"
26 } 30 }
27 31
28 // These enable timing code that report milliseconds for an encoding/decoding 32 // These enable timing code that report milliseconds for an encoding/decoding
29 //#define TIME_ENCODE 33 //#define TIME_ENCODE
30 //#define TIME_DECODE 34 //#define TIME_DECODE
31 35
32 // this enables our rgb->yuv code, which is faster than libjpeg on ARM 36 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
33 #define WE_CONVERT_TO_YUV 37 #define WE_CONVERT_TO_YUV
34 38
35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s 39 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s
36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. 40 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
37 41
42 #if defined(SK_DEBUG)
43 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
44 "images.jpeg.suppressDecoderWarnings", false,
45 "Suppress most JPG warnings when calling decode functions.");
46 #endif // defined(SK_DEBUG)
47
38 ////////////////////////////////////////////////////////////////////////// 48 //////////////////////////////////////////////////////////////////////////
39 ////////////////////////////////////////////////////////////////////////// 49 //////////////////////////////////////////////////////////////////////////
40 50
41 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) { 51 static void overwrite_mem_buffer_size(jpeg_decompress_struct* cinfo) {
42 #ifdef SK_BUILD_FOR_ANDROID 52 #ifdef SK_BUILD_FOR_ANDROID
43 /* Check if the device indicates that it has a large amount of system memory 53 /* Check if the device indicates that it has a large amount of system memory
44 * if so, increase the memory allocation to 30MB instead of the default 5MB. 54 * if so, increase the memory allocation to 30MB instead of the default 5MB.
45 */ 55 */
46 #ifdef ANDROID_LARGE_MEMORY_DEVICE 56 #ifdef ANDROID_LARGE_MEMORY_DEVICE
47 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; 57 cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
48 #else 58 #else
49 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; 59 cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
50 #endif 60 #endif
51 #endif // SK_BUILD_FOR_ANDROID 61 #endif // SK_BUILD_FOR_ANDROID
52 } 62 }
53 63
54 ////////////////////////////////////////////////////////////////////////// 64 //////////////////////////////////////////////////////////////////////////
55 ////////////////////////////////////////////////////////////////////////// 65 //////////////////////////////////////////////////////////////////////////
56 66
67 static void do_nothing_emit_message(jpeg_common_struct*, int) {
68 /* do nothing */
69 }
70
57 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr c_mgr) { 71 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr c_mgr) {
58 SkASSERT(cinfo != NULL); 72 SkASSERT(cinfo != NULL);
59 SkASSERT(src_mgr != NULL); 73 SkASSERT(src_mgr != NULL);
60 jpeg_create_decompress(cinfo); 74 jpeg_create_decompress(cinfo);
61 overwrite_mem_buffer_size(cinfo); 75 overwrite_mem_buffer_size(cinfo);
62 cinfo->src = src_mgr; 76 cinfo->src = src_mgr;
77 #if defined(SK_DEBUG)
78 /* To suppress warnings with a SK_DEBUG binary, set the
79 * environment variable "skia_images_jpeg_suppressDecoderWarnings"
80 * to "true". Inside a program that links to skia:
81 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
82 if (c_suppressJPEGImageDecoderWarnings) {
83 cinfo->err->emit_message = &do_nothing_emit_message;
84 }
85 #else // Always suppress in release mode.
86 cinfo->err->emit_message = &do_nothing_emit_message;
87 #endif //defined(SK_DEBUG)
63 } 88 }
64 89
65 #ifdef SK_BUILD_FOR_ANDROID 90 #ifdef SK_BUILD_FOR_ANDROID
66 class SkJPEGImageIndex { 91 class SkJPEGImageIndex {
67 public: 92 public:
68 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder) 93 SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
69 : fSrcMgr(stream, decoder) 94 : fSrcMgr(stream, decoder)
70 , fInfoInitialized(false) 95 , fInfoInitialized(false)
71 , fHuffmanCreated(false) 96 , fHuffmanCreated(false)
72 , fDecompressStarted(false) 97 , fDecompressStarted(false)
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 cinfo.out_color_space == JCS_RGB_565))) 574 cinfo.out_color_space == JCS_RGB_565)))
550 { 575 {
551 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); 576 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
552 INT32 const bpr = bm->rowBytes(); 577 INT32 const bpr = bm->rowBytes();
553 578
554 while (cinfo.output_scanline < cinfo.output_height) { 579 while (cinfo.output_scanline < cinfo.output_height) {
555 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 580 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
556 // if row_count == 0, then we didn't get a scanline, so abort. 581 // if row_count == 0, then we didn't get a scanline, so abort.
557 // if we supported partial images, we might return true in this case 582 // if we supported partial images, we might return true in this case
558 if (0 == row_count) { 583 if (0 == row_count) {
559 return return_false(cinfo, *bm, "read_scanlines"); 584 return true;
scroggo 2013/10/02 17:05:04 The remaining rows will still be uninitialized.
560 } 585 }
561 if (this->shouldCancelDecode()) { 586 if (this->shouldCancelDecode()) {
562 return return_false(cinfo, *bm, "shouldCancelDecode"); 587 return return_false(cinfo, *bm, "shouldCancelDecode");
563 } 588 }
564 rowptr += bpr; 589 rowptr += bpr;
565 } 590 }
566 jpeg_finish_decompress(&cinfo); 591 jpeg_finish_decompress(&cinfo);
567 return true; 592 return true;
568 } 593 }
569 #endif 594 #endif
(...skipping 29 matching lines...) Expand all
599 // Possibly skip initial rows [sampler.srcY0] 624 // Possibly skip initial rows [sampler.srcY0]
600 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) { 625 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
601 return return_false(cinfo, *bm, "skip rows"); 626 return return_false(cinfo, *bm, "skip rows");
602 } 627 }
603 628
604 // now loop through scanlines until y == bm->height() - 1 629 // now loop through scanlines until y == bm->height() - 1
605 for (int y = 0;; y++) { 630 for (int y = 0;; y++) {
606 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 631 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
607 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1); 632 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
608 if (0 == row_count) { 633 if (0 == row_count) {
609 return return_false(cinfo, *bm, "read_scanlines"); 634 return true;
scroggo 2013/10/02 17:05:04 Ditto
610 } 635 }
611 if (this->shouldCancelDecode()) { 636 if (this->shouldCancelDecode()) {
612 return return_false(cinfo, *bm, "shouldCancelDecode"); 637 return return_false(cinfo, *bm, "shouldCancelDecode");
613 } 638 }
614 639
615 if (JCS_CMYK == cinfo.out_color_space) { 640 if (JCS_CMYK == cinfo.out_color_space) {
616 convert_CMYK_to_RGB(srcRow, cinfo.output_width); 641 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
617 } 642 }
618 643
619 sampler.next(srcRow); 644 sampler.next(srcRow);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 INT32 const bpr = bitmap.rowBytes(); 806 INT32 const bpr = bitmap.rowBytes();
782 int rowTotalCount = 0; 807 int rowTotalCount = 0;
783 808
784 while (rowTotalCount < height) { 809 while (rowTotalCount < height) {
785 int rowCount = jpeg_read_tile_scanline(cinfo, 810 int rowCount = jpeg_read_tile_scanline(cinfo,
786 fImageIndex->huffmanIndex(), 811 fImageIndex->huffmanIndex(),
787 &rowptr); 812 &rowptr);
788 // if row_count == 0, then we didn't get a scanline, so abort. 813 // if row_count == 0, then we didn't get a scanline, so abort.
789 // if we supported partial images, we might return true in this case 814 // if we supported partial images, we might return true in this case
790 if (0 == rowCount) { 815 if (0 == rowCount) {
791 return return_false(*cinfo, bitmap, "read_scanlines"); 816 return true;
scroggo 2013/10/02 17:05:04 Ditto
792 } 817 }
793 if (this->shouldCancelDecode()) { 818 if (this->shouldCancelDecode()) {
794 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 819 return return_false(*cinfo, bitmap, "shouldCancelDecode");
795 } 820 }
796 rowTotalCount += rowCount; 821 rowTotalCount += rowCount;
797 rowptr += bpr; 822 rowptr += bpr;
798 } 823 }
799 824
800 if (swapOnly) { 825 if (swapOnly) {
801 bm->swap(bitmap); 826 bm->swap(bitmap);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 // Possibly skip initial rows [sampler.srcY0] 863 // Possibly skip initial rows [sampler.srcY0]
839 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) { 864 if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler. srcY0())) {
840 return return_false(*cinfo, bitmap, "skip rows"); 865 return return_false(*cinfo, bitmap, "skip rows");
841 } 866 }
842 867
843 // now loop through scanlines until y == bitmap->height() - 1 868 // now loop through scanlines until y == bitmap->height() - 1
844 for (int y = 0;; y++) { 869 for (int y = 0;; y++) {
845 JSAMPLE* rowptr = (JSAMPLE*)srcRow; 870 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
846 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr); 871 int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex (), &rowptr);
847 if (0 == row_count) { 872 if (0 == row_count) {
848 return return_false(*cinfo, bitmap, "read_scanlines"); 873 return true;
scroggo 2013/10/02 17:05:04 Ditto
849 } 874 }
850 if (this->shouldCancelDecode()) { 875 if (this->shouldCancelDecode()) {
851 return return_false(*cinfo, bitmap, "shouldCancelDecode"); 876 return return_false(*cinfo, bitmap, "shouldCancelDecode");
852 } 877 }
853 878
854 if (JCS_CMYK == cinfo->out_color_space) { 879 if (JCS_CMYK == cinfo->out_color_space) {
855 convert_CMYK_to_RGB(srcRow, width); 880 convert_CMYK_to_RGB(srcRow, width);
856 } 881 }
857 882
858 sampler.next(srcRow); 883 sampler.next(srcRow);
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 return SkImageDecoder::kUnknown_Format; 1177 return SkImageDecoder::kUnknown_Format;
1153 } 1178 }
1154 1179
1155 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1180 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1156 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL; 1181 return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
1157 } 1182 }
1158 1183
1159 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 1184 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1160 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 1185 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1161 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1186 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698