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

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

Issue 1830943002: Revert of Delete SkImageDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fix-animator
Patch Set: Created 4 years, 9 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
« no previous file with comments | « src/images/SkImageDecoder_libico.cpp ('k') | src/images/SkImageDecoder_libpng.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "SkImageEncoder.h" 10 #include "SkImageEncoder.h"
10 #include "SkJpegUtility.h" 11 #include "SkJpegUtility.h"
11 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
12 #include "SkDither.h" 13 #include "SkDither.h"
14 #include "SkMSAN.h"
15 #include "SkScaledBitmapSampler.h"
13 #include "SkStream.h" 16 #include "SkStream.h"
14 #include "SkTemplates.h" 17 #include "SkTemplates.h"
15 #include "SkTime.h" 18 #include "SkTime.h"
16 #include "SkUtils.h" 19 #include "SkUtils.h"
17 #include "SkRTConf.h" 20 #include "SkRTConf.h"
18 #include "SkRect.h" 21 #include "SkRect.h"
19 #include "SkCanvas.h" 22 #include "SkCanvas.h"
20 23
21 24
22 #include <stdio.h> 25 #include <stdio.h>
23 extern "C" { 26 extern "C" {
24 #include "jpeglib.h" 27 #include "jpeglib.h"
25 #include "jerror.h" 28 #include "jerror.h"
26 } 29 }
27 30
28 // These enable timing code that report milliseconds for an encoding 31 // These enable timing code that report milliseconds for an encoding/decoding
29 //#define TIME_ENCODE 32 //#define TIME_ENCODE
33 //#define TIME_DECODE
30 34
31 // this enables our rgb->yuv code, which is faster than libjpeg on ARM 35 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
32 #define WE_CONVERT_TO_YUV 36 #define WE_CONVERT_TO_YUV
33 37
38 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s
39 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
40
41 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
42 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
43 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
44 "images.jpeg.suppressDecoderWarnings",
45 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
46 "Suppress most JPG warnings when calling decode functions.");
47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
48 "images.jpeg.suppressDecoderErrors",
49 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS,
50 "Suppress most JPG error messages when decode "
51 "function fails.");
52
53 //////////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////////
55
56 static void do_nothing_emit_message(jpeg_common_struct*, int) {
57 /* do nothing */
58 }
59 static void do_nothing_output_message(j_common_ptr) {
60 /* do nothing */
61 }
62
63 static void initialize_info(jpeg_decompress_struct* cinfo, skjpeg_source_mgr* sr c_mgr) {
64 SkASSERT(cinfo != nullptr);
65 SkASSERT(src_mgr != nullptr);
66 jpeg_create_decompress(cinfo);
67 cinfo->src = src_mgr;
68 /* To suppress warnings with a SK_DEBUG binary, set the
69 * environment variable "skia_images_jpeg_suppressDecoderWarnings"
70 * to "true". Inside a program that links to skia:
71 * SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true); */
72 if (c_suppressJPEGImageDecoderWarnings) {
73 cinfo->err->emit_message = &do_nothing_emit_message;
74 }
75 /* To suppress error messages with a SK_DEBUG binary, set the
76 * environment variable "skia_images_jpeg_suppressDecoderErrors"
77 * to "true". Inside a program that links to skia:
78 * SK_CONF_SET("images.jpeg.suppressDecoderErrors", true); */
79 if (c_suppressJPEGImageDecoderErrors) {
80 cinfo->err->output_message = &do_nothing_output_message;
81 }
82 }
83
84 class SkJPEGImageDecoder : public SkImageDecoder {
85 public:
86
87 Format getFormat() const override {
88 return kJPEG_Format;
89 }
90
91 protected:
92 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
93 bool onDecodeYUV8Planes(SkStream* stream, SkISize componentSizes[3],
94 void* planes[3], size_t rowBytes[3],
95 SkYUVColorSpace* colorSpace) override;
96
97 private:
98
99 /**
100 * Determine the appropriate bitmap colortype and out_color_space based on
101 * both the preference of the caller and the jpeg_color_space on the
102 * jpeg_decompress_struct passed in.
103 * Must be called after jpeg_read_header.
104 */
105 SkColorType getBitmapColorType(jpeg_decompress_struct*);
106
107 typedef SkImageDecoder INHERITED;
108 };
109
110 //////////////////////////////////////////////////////////////////////////
111
112 /* Automatically clean up after throwing an exception */
113 class JPEGAutoClean {
114 public:
115 JPEGAutoClean(): cinfo_ptr(nullptr) {}
116 ~JPEGAutoClean() {
117 if (cinfo_ptr) {
118 jpeg_destroy_decompress(cinfo_ptr);
119 }
120 }
121 void set(jpeg_decompress_struct* info) {
122 cinfo_ptr = info;
123 }
124 private:
125 jpeg_decompress_struct* cinfo_ptr;
126 };
127
34 /////////////////////////////////////////////////////////////////////////////// 128 ///////////////////////////////////////////////////////////////////////////////
35 129
130 /* If we need to better match the request, we might examine the image and
131 output dimensions, and determine if the downsampling jpeg provided is
132 not sufficient. If so, we can recompute a modified sampleSize value to
133 make up the difference.
134
135 To skip this additional scaling, just set sampleSize = 1; below.
136 */
137 static int recompute_sampleSize(int sampleSize,
138 const jpeg_decompress_struct& cinfo) {
139 return sampleSize * cinfo.output_width / cinfo.image_width;
140 }
141
142 static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
143 /* These are initialized to 0, so if they have non-zero values, we assume
144 they are "valid" (i.e. have been computed by libjpeg)
145 */
146 return 0 != cinfo.output_width && 0 != cinfo.output_height;
147 }
148
149 static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count ) {
150 for (int i = 0; i < count; i++) {
151 JSAMPLE* rowptr = (JSAMPLE*)buffer;
152 int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
153 if (1 != row_count) {
154 return false;
155 }
156 }
157 return true;
158 }
159
160 ///////////////////////////////////////////////////////////////////////////////
161
162 // This guy exists just to aid in debugging, as it allows debuggers to just
163 // set a break-point in one place to see all error exists.
164 static void print_jpeg_decoder_errors(const jpeg_decompress_struct& cinfo,
165 int width, int height, const char caller[]) {
166 if (!(c_suppressJPEGImageDecoderErrors)) {
167 char buffer[JMSG_LENGTH_MAX];
168 cinfo.err->format_message((const j_common_ptr)&cinfo, buffer);
169 SkDebugf("libjpeg error %d <%s> from %s [%d %d]\n",
170 cinfo.err->msg_code, buffer, caller, width, height);
171 }
172 }
173
174 static bool return_false(const jpeg_decompress_struct& cinfo,
175 const char caller[]) {
176 print_jpeg_decoder_errors(cinfo, 0, 0, caller);
177 return false;
178 }
179
180 static SkImageDecoder::Result return_failure(const jpeg_decompress_struct& cinfo ,
181 const SkBitmap& bm, const char call er[]) {
182 print_jpeg_decoder_errors(cinfo, bm.width(), bm.height(), caller);
183 return SkImageDecoder::kFailure;
184 }
185
186 ///////////////////////////////////////////////////////////////////////////////
187
188 // Convert a scanline of CMYK samples to RGBX in place. Note that this
189 // method moves the "scanline" pointer in its processing
190 static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
191 // At this point we've received CMYK pixels from libjpeg. We
192 // perform a crude conversion to RGB (based on the formulae
193 // from easyrgb.com):
194 // CMYK -> CMY
195 // C = ( C * (1 - K) + K ) // for each CMY component
196 // CMY -> RGB
197 // R = ( 1 - C ) * 255 // for each RGB component
198 // Unfortunately we are seeing inverted CMYK so all the original terms
199 // are 1-. This yields:
200 // CMYK -> CMY
201 // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
202 // The conversion from CMY->RGB remains the same
203 for (unsigned int x = 0; x < width; ++x, scanline += 4) {
204 scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
205 scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
206 scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
207 scanline[3] = 255;
208 }
209 }
210
211 /**
212 * Common code for setting the error manager.
213 */
214 static void set_error_mgr(jpeg_decompress_struct* cinfo, skjpeg_error_mgr* error Manager) {
215 SkASSERT(cinfo != nullptr);
216 SkASSERT(errorManager != nullptr);
217 cinfo->err = jpeg_std_error(errorManager);
218 errorManager->error_exit = skjpeg_error_exit;
219 }
220
221 /**
222 * Common code for setting the dct method.
223 */
224 static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct * cinfo) {
225 SkASSERT(cinfo != nullptr);
226 cinfo->dct_method = JDCT_ISLOW;
227 }
228
229 SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo ) {
230 SkASSERT(cinfo != nullptr);
231
232 SrcDepth srcDepth = k32Bit_SrcDepth;
233 if (JCS_GRAYSCALE == cinfo->jpeg_color_space) {
234 srcDepth = k8BitGray_SrcDepth;
235 }
236
237 SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false) ;
238 switch (colorType) {
239 case kAlpha_8_SkColorType:
240 // Only respect A8 colortype if the original is grayscale,
241 // in which case we will treat the grayscale as alpha
242 // values.
243 if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
244 colorType = kN32_SkColorType;
245 }
246 break;
247 case kN32_SkColorType:
248 // Fall through.
249 case kARGB_4444_SkColorType:
250 // Fall through.
251 case kRGB_565_SkColorType:
252 // These are acceptable destination colortypes.
253 break;
254 default:
255 // Force all other colortypes to 8888.
256 colorType = kN32_SkColorType;
257 break;
258 }
259
260 switch (cinfo->jpeg_color_space) {
261 case JCS_CMYK:
262 // Fall through.
263 case JCS_YCCK:
264 // libjpeg cannot convert from CMYK or YCCK to RGB - here we set up
265 // so libjpeg will give us CMYK samples back and we will later
266 // manually convert them to RGB
267 cinfo->out_color_space = JCS_CMYK;
268 break;
269 case JCS_GRAYSCALE:
270 if (kAlpha_8_SkColorType == colorType) {
271 cinfo->out_color_space = JCS_GRAYSCALE;
272 break;
273 }
274 // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
275 // colortype. Fall through to set to the default.
276 default:
277 cinfo->out_color_space = JCS_RGB;
278 break;
279 }
280 return colorType;
281 }
282
283 /**
284 * Based on the colortype and dither mode, adjust out_color_space and
285 * dither_mode of cinfo. Only does work in ANDROID_RGB
286 */
287 static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
288 SkColorType colorType,
289 const SkImageDecoder& decoder) {
290 SkASSERT(cinfo != nullptr);
291 #ifdef ANDROID_RGB
292 cinfo->dither_mode = JDITHER_NONE;
293 if (JCS_CMYK == cinfo->out_color_space) {
294 return;
295 }
296 switch (colorType) {
297 case kN32_SkColorType:
298 cinfo->out_color_space = JCS_RGBA_8888;
299 break;
300 case kRGB_565_SkColorType:
301 cinfo->out_color_space = JCS_RGB_565;
302 if (decoder.getDitherImage()) {
303 cinfo->dither_mode = JDITHER_ORDERED;
304 }
305 break;
306 default:
307 break;
308 }
309 #endif
310 }
311
312 /**
313 Sets all pixels in given bitmap to SK_ColorWHITE for all rows >= y.
314 Used when decoding fails partway through reading scanlines to fill
315 remaining lines. */
316 static void fill_below_level(int y, SkBitmap* bitmap) {
317 SkIRect rect = SkIRect::MakeLTRB(0, y, bitmap->width(), bitmap->height());
318 SkCanvas canvas(*bitmap);
319 canvas.clipRect(SkRect::Make(rect));
320 canvas.drawColor(SK_ColorWHITE);
321 }
322
323 /**
324 * Get the config and bytes per pixel of the source data. Return
325 * whether the data is supported.
326 */
327 static bool get_src_config(const jpeg_decompress_struct& cinfo,
328 SkScaledBitmapSampler::SrcConfig* sc,
329 int* srcBytesPerPixel) {
330 SkASSERT(sc != nullptr && srcBytesPerPixel != nullptr);
331 if (JCS_CMYK == cinfo.out_color_space) {
332 // In this case we will manually convert the CMYK values to RGB
333 *sc = SkScaledBitmapSampler::kRGBX;
334 // The CMYK work-around relies on 4 components per pixel here
335 *srcBytesPerPixel = 4;
336 } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_spa ce) {
337 *sc = SkScaledBitmapSampler::kRGB;
338 *srcBytesPerPixel = 3;
339 #ifdef ANDROID_RGB
340 } else if (JCS_RGBA_8888 == cinfo.out_color_space) {
341 *sc = SkScaledBitmapSampler::kRGBX;
342 *srcBytesPerPixel = 4;
343 } else if (JCS_RGB_565 == cinfo.out_color_space) {
344 *sc = SkScaledBitmapSampler::kRGB_565;
345 *srcBytesPerPixel = 2;
346 #endif
347 } else if (1 == cinfo.out_color_components &&
348 JCS_GRAYSCALE == cinfo.out_color_space) {
349 *sc = SkScaledBitmapSampler::kGray;
350 *srcBytesPerPixel = 1;
351 } else {
352 return false;
353 }
354 return true;
355 }
356
357 SkImageDecoder::Result SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
358 #ifdef TIME_DECODE
359 SkAutoTime atm("JPEG Decode");
360 #endif
361
362 JPEGAutoClean autoClean;
363
364 jpeg_decompress_struct cinfo;
365 skjpeg_source_mgr srcManager(stream, this);
366
367 skjpeg_error_mgr errorManager;
368 set_error_mgr(&cinfo, &errorManager);
369
370 // All objects need to be instantiated before this setjmp call so that
371 // they will be cleaned up properly if an error occurs.
372 if (setjmp(errorManager.fJmpBuf)) {
373 return return_failure(cinfo, *bm, "setjmp");
374 }
375
376 initialize_info(&cinfo, &srcManager);
377 autoClean.set(&cinfo);
378
379 int status = jpeg_read_header(&cinfo, true);
380 if (status != JPEG_HEADER_OK) {
381 return return_failure(cinfo, *bm, "read_header");
382 }
383
384 /* Try to fulfill the requested sampleSize. Since jpeg can do it (when it
385 can) much faster that we, just use their num/denom api to approximate
386 the size.
387 */
388 int sampleSize = this->getSampleSize();
389
390 set_dct_method(*this, &cinfo);
391
392 SkASSERT(1 == cinfo.scale_num);
393 cinfo.scale_denom = sampleSize;
394
395 const SkColorType colorType = this->getBitmapColorType(&cinfo);
396 const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
397 kPremul_SkAlphaType : kOpaque_SkAlphaType;
398
399 adjust_out_color_space_and_dither(&cinfo, colorType, *this);
400
401 if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
402 // Assume an A8 bitmap is not opaque to avoid the check of each
403 // individual pixel. It is very unlikely to be opaque, since
404 // an opaque A8 bitmap would not be very interesting.
405 // Otherwise, a jpeg image is opaque.
406 bool success = bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.im age_height,
407 colorType, alphaType));
408 return success ? kSuccess : kFailure;
409 }
410
411 /* image_width and image_height are the original dimensions, available
412 after jpeg_read_header(). To see the scaled dimensions, we have to call
413 jpeg_start_decompress(), and then read output_width and output_height.
414 */
415 if (!jpeg_start_decompress(&cinfo)) {
416 /* If we failed here, we may still have enough information to return
417 to the caller if they just wanted (subsampled bounds). If sampleSize
418 was 1, then we would have already returned. Thus we just check if
419 we're in kDecodeBounds_Mode, and that we have valid output sizes.
420
421 One reason to fail here is that we have insufficient stream data
422 to complete the setup. However, output dimensions seem to get
423 computed very early, which is why this special check can pay off.
424 */
425 if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimension s(cinfo)) {
426 SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
427 recompute_sampleSize(sampleSize, cinfo));
428 // Assume an A8 bitmap is not opaque to avoid the check of each
429 // individual pixel. It is very unlikely to be opaque, since
430 // an opaque A8 bitmap would not be very interesting.
431 // Otherwise, a jpeg image is opaque.
432 bool success = bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smp l.scaledHeight(),
433 colorType, alphaType));
434 return success ? kSuccess : kFailure;
435 } else {
436 return return_failure(cinfo, *bm, "start_decompress");
437 }
438 }
439 sampleSize = recompute_sampleSize(sampleSize, cinfo);
440
441 SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampl eSize);
442 // Assume an A8 bitmap is not opaque to avoid the check of each
443 // individual pixel. It is very unlikely to be opaque, since
444 // an opaque A8 bitmap would not be very interesting.
445 // Otherwise, a jpeg image is opaque.
446 bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
447 colorType, alphaType));
448 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
449 return kSuccess;
450 }
451 if (!this->allocPixelRef(bm, nullptr)) {
452 return return_failure(cinfo, *bm, "allocPixelRef");
453 }
454
455 SkAutoLockPixels alp(*bm);
456
457 #ifdef ANDROID_RGB
458 /* short-circuit the SkScaledBitmapSampler when possible, as this gives
459 a significant performance boost.
460 */
461 if (sampleSize == 1 &&
462 ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_888 8) ||
463 (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_ 565)))
464 {
465 JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
466 INT32 const bpr = bm->rowBytes();
467
468 while (cinfo.output_scanline < cinfo.output_height) {
469 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
470 if (0 == row_count) {
471 // if row_count == 0, then we didn't get a scanline,
472 // so return early. We will return a partial image.
473 fill_below_level(cinfo.output_scanline, bm);
474 cinfo.output_scanline = cinfo.output_height;
475 jpeg_finish_decompress(&cinfo);
476 return kPartialSuccess;
477 }
478 if (this->shouldCancelDecode()) {
479 return return_failure(cinfo, *bm, "shouldCancelDecode");
480 }
481 rowptr += bpr;
482 }
483 jpeg_finish_decompress(&cinfo);
484 return kSuccess;
485 }
486 #endif
487
488 // check for supported formats
489 SkScaledBitmapSampler::SrcConfig sc;
490 int srcBytesPerPixel;
491
492 if (!get_src_config(cinfo, &sc, &srcBytesPerPixel)) {
493 return return_failure(cinfo, *bm, "jpeg colorspace");
494 }
495
496 if (!sampler.begin(bm, sc, *this)) {
497 return return_failure(cinfo, *bm, "sampler.begin");
498 }
499
500 SkAutoTMalloc<uint8_t> srcStorage(cinfo.output_width * srcBytesPerPixel);
501 uint8_t* srcRow = srcStorage.get();
502
503 // Possibly skip initial rows [sampler.srcY0]
504 if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
505 return return_failure(cinfo, *bm, "skip rows");
506 }
507
508 // now loop through scanlines until y == bm->height() - 1
509 for (int y = 0;; y++) {
510 JSAMPLE* rowptr = (JSAMPLE*)srcRow;
511 int row_count = jpeg_read_scanlines(&cinfo, &rowptr, 1);
512 sk_msan_mark_initialized(srcRow, srcRow + cinfo.output_width * srcBytesP erPixel,
513 "skbug.com/4550");
514 if (0 == row_count) {
515 // if row_count == 0, then we didn't get a scanline,
516 // so return early. We will return a partial image.
517 fill_below_level(y, bm);
518 cinfo.output_scanline = cinfo.output_height;
519 jpeg_finish_decompress(&cinfo);
520 return kPartialSuccess;
521 }
522 if (this->shouldCancelDecode()) {
523 return return_failure(cinfo, *bm, "shouldCancelDecode");
524 }
525
526 if (JCS_CMYK == cinfo.out_color_space) {
527 convert_CMYK_to_RGB(srcRow, cinfo.output_width);
528 }
529
530
531 sampler.next(srcRow);
532 if (bm->height() - 1 == y) {
533 // we're done
534 break;
535 }
536
537 if (!skip_src_rows(&cinfo, srcRow, sampler.srcDY() - 1)) {
538 return return_failure(cinfo, *bm, "skip rows");
539 }
540 }
541
542 // we formally skip the rest, so we don't get a complaint from libjpeg
543 if (!skip_src_rows(&cinfo, srcRow,
544 cinfo.output_height - cinfo.output_scanline)) {
545 return return_failure(cinfo, *bm, "skip rows");
546 }
547 jpeg_finish_decompress(&cinfo);
548
549 return kSuccess;
550 }
551
552 ///////////////////////////////////////////////////////////////////////////////
553
554 enum SizeType {
555 kSizeForMemoryAllocation_SizeType,
556 kActualSize_SizeType
557 };
558
559 static SkISize compute_yuv_size(const jpeg_decompress_struct& info, int componen t,
560 SizeType sizeType) {
561 if (sizeType == kSizeForMemoryAllocation_SizeType) {
562 return SkISize::Make(info.cur_comp_info[component]->width_in_blocks * DC TSIZE,
563 info.cur_comp_info[component]->height_in_blocks * D CTSIZE);
564 }
565 return SkISize::Make(info.cur_comp_info[component]->downsampled_width,
566 info.cur_comp_info[component]->downsampled_height);
567 }
568
569 static bool appears_to_be_yuv(const jpeg_decompress_struct& info) {
570 return (info.jpeg_color_space == JCS_YCbCr)
571 && (DCTSIZE == 8)
572 && (info.num_components == 3)
573 && (info.comps_in_scan >= info.num_components)
574 && (info.scale_denom <= 8)
575 && (info.cur_comp_info[0])
576 && (info.cur_comp_info[1])
577 && (info.cur_comp_info[2])
578 && (info.cur_comp_info[1]->h_samp_factor == 1)
579 && (info.cur_comp_info[1]->v_samp_factor == 1)
580 && (info.cur_comp_info[2]->h_samp_factor == 1)
581 && (info.cur_comp_info[2]->v_samp_factor == 1);
582 }
583
584 static void update_components_sizes(const jpeg_decompress_struct& cinfo, SkISize componentSizes[3],
585 SizeType sizeType) {
586 SkASSERT(appears_to_be_yuv(cinfo));
587 for (int i = 0; i < 3; ++i) {
588 componentSizes[i] = compute_yuv_size(cinfo, i, sizeType);
589 }
590 }
591
592 static bool output_raw_data(jpeg_decompress_struct& cinfo, void* planes[3], size _t rowBytes[3]) {
593 SkASSERT(appears_to_be_yuv(cinfo));
594 // U size and V size have to be the same if we're calling output_raw_data()
595 SkISize uvSize = compute_yuv_size(cinfo, 1, kSizeForMemoryAllocation_SizeTyp e);
596 SkASSERT(uvSize == compute_yuv_size(cinfo, 2, kSizeForMemoryAllocation_SizeT ype));
597
598 JSAMPARRAY bufferraw[3];
599 JSAMPROW bufferraw2[32];
600 bufferraw[0] = &bufferraw2[0]; // Y channel rows (8 or 16)
601 bufferraw[1] = &bufferraw2[16]; // U channel rows (8)
602 bufferraw[2] = &bufferraw2[24]; // V channel rows (8)
603 int yWidth = cinfo.output_width;
604 int yHeight = cinfo.output_height;
605 int yMaxH = yHeight - 1;
606 int v = cinfo.cur_comp_info[0]->v_samp_factor;
607 int uvMaxH = uvSize.height() - 1;
608 JSAMPROW outputY = static_cast<JSAMPROW>(planes[0]);
609 JSAMPROW outputU = static_cast<JSAMPROW>(planes[1]);
610 JSAMPROW outputV = static_cast<JSAMPROW>(planes[2]);
611 size_t rowBytesY = rowBytes[0];
612 size_t rowBytesU = rowBytes[1];
613 size_t rowBytesV = rowBytes[2];
614
615 int yScanlinesToRead = DCTSIZE * v;
616 SkAutoMalloc lastRowStorage(rowBytesY * 4);
617 JSAMPROW yLastRow = (JSAMPROW)lastRowStorage.get();
618 JSAMPROW uLastRow = yLastRow + rowBytesY;
619 JSAMPROW vLastRow = uLastRow + rowBytesY;
620 JSAMPROW dummyRow = vLastRow + rowBytesY;
621
622 while (cinfo.output_scanline < cinfo.output_height) {
623 // Request 8 or 16 scanlines: returns 0 or more scanlines.
624 bool hasYLastRow(false), hasUVLastRow(false);
625 // Assign 8 or 16 rows of memory to read the Y channel.
626 for (int i = 0; i < yScanlinesToRead; ++i) {
627 int scanline = (cinfo.output_scanline + i);
628 if (scanline < yMaxH) {
629 bufferraw2[i] = &outputY[scanline * rowBytesY];
630 } else if (scanline == yMaxH) {
631 bufferraw2[i] = yLastRow;
632 hasYLastRow = true;
633 } else {
634 bufferraw2[i] = dummyRow;
635 }
636 }
637 int scaledScanline = cinfo.output_scanline / v;
638 // Assign 8 rows of memory to read the U and V channels.
639 for (int i = 0; i < 8; ++i) {
640 int scanline = (scaledScanline + i);
641 if (scanline < uvMaxH) {
642 bufferraw2[16 + i] = &outputU[scanline * rowBytesU];
643 bufferraw2[24 + i] = &outputV[scanline * rowBytesV];
644 } else if (scanline == uvMaxH) {
645 bufferraw2[16 + i] = uLastRow;
646 bufferraw2[24 + i] = vLastRow;
647 hasUVLastRow = true;
648 } else {
649 bufferraw2[16 + i] = dummyRow;
650 bufferraw2[24 + i] = dummyRow;
651 }
652 }
653 JDIMENSION scanlinesRead = jpeg_read_raw_data(&cinfo, bufferraw, yScanli nesToRead);
654
655 if (scanlinesRead == 0) {
656 return false;
657 }
658
659 if (hasYLastRow) {
660 memcpy(&outputY[yMaxH * rowBytesY], yLastRow, yWidth);
661 }
662 if (hasUVLastRow) {
663 memcpy(&outputU[uvMaxH * rowBytesU], uLastRow, uvSize.width());
664 memcpy(&outputV[uvMaxH * rowBytesV], vLastRow, uvSize.width());
665 }
666 }
667
668 cinfo.output_scanline = SkMin32(cinfo.output_scanline, cinfo.output_height);
669
670 return true;
671 }
672
673 bool SkJPEGImageDecoder::onDecodeYUV8Planes(SkStream* stream, SkISize componentS izes[3],
674 void* planes[3], size_t rowBytes[3],
675 SkYUVColorSpace* colorSpace) {
676 #ifdef TIME_DECODE
677 SkAutoTime atm("JPEG YUV8 Decode");
678 #endif
679 if (this->getSampleSize() != 1) {
680 return false; // Resizing not supported
681 }
682
683 JPEGAutoClean autoClean;
684
685 jpeg_decompress_struct cinfo;
686 skjpeg_source_mgr srcManager(stream, this);
687
688 skjpeg_error_mgr errorManager;
689 set_error_mgr(&cinfo, &errorManager);
690
691 // All objects need to be instantiated before this setjmp call so that
692 // they will be cleaned up properly if an error occurs.
693 if (setjmp(errorManager.fJmpBuf)) {
694 return return_false(cinfo, "setjmp YUV8");
695 }
696
697 initialize_info(&cinfo, &srcManager);
698 autoClean.set(&cinfo);
699
700 int status = jpeg_read_header(&cinfo, true);
701 if (status != JPEG_HEADER_OK) {
702 return return_false(cinfo, "read_header YUV8");
703 }
704
705 if (!appears_to_be_yuv(cinfo)) {
706 // It's not an error to not be encoded in YUV, so no need to use return_ false()
707 return false;
708 }
709
710 cinfo.out_color_space = JCS_YCbCr;
711 cinfo.raw_data_out = TRUE;
712
713 if (!planes || !planes[0] || !rowBytes || !rowBytes[0]) { // Compute size on ly
714 update_components_sizes(cinfo, componentSizes, kSizeForMemoryAllocation_ SizeType);
715 return true;
716 }
717
718 set_dct_method(*this, &cinfo);
719
720 SkASSERT(1 == cinfo.scale_num);
721 cinfo.scale_denom = 1;
722
723 #ifdef ANDROID_RGB
724 cinfo.dither_mode = JDITHER_NONE;
725 #endif
726
727 /* image_width and image_height are the original dimensions, available
728 after jpeg_read_header(). To see the scaled dimensions, we have to call
729 jpeg_start_decompress(), and then read output_width and output_height.
730 */
731 if (!jpeg_start_decompress(&cinfo)) {
732 return return_false(cinfo, "start_decompress YUV8");
733 }
734
735 // Seems like jpeg_start_decompress is updating our opinion of whether cinfo represents YUV.
736 // Again, not really an error.
737 if (!appears_to_be_yuv(cinfo)) {
738 return false;
739 }
740
741 if (!output_raw_data(cinfo, planes, rowBytes)) {
742 return return_false(cinfo, "output_raw_data");
743 }
744
745 update_components_sizes(cinfo, componentSizes, kActualSize_SizeType);
746 jpeg_finish_decompress(&cinfo);
747
748 if (nullptr != colorSpace) {
749 *colorSpace = kJPEG_SkYUVColorSpace;
750 }
751
752 return true;
753 }
754
755 ///////////////////////////////////////////////////////////////////////////////
756
36 #include "SkColorPriv.h" 757 #include "SkColorPriv.h"
37 758
38 // taken from jcolor.c in libjpeg 759 // taken from jcolor.c in libjpeg
39 #if 0 // 16bit - precise but slow 760 #if 0 // 16bit - precise but slow
40 #define CYR 19595 // 0.299 761 #define CYR 19595 // 0.299
41 #define CYG 38470 // 0.587 762 #define CYG 38470 // 0.587
42 #define CYB 7471 // 0.114 763 #define CYB 7471 // 0.114
43 764
44 #define CUR -11059 // -0.16874 765 #define CUR -11059 // -0.16874
45 #define CUG -21709 // -0.33126 766 #define CUG -21709 // -0.33126
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 986 }
266 987
267 jpeg_finish_compress(&cinfo); 988 jpeg_finish_compress(&cinfo);
268 jpeg_destroy_compress(&cinfo); 989 jpeg_destroy_compress(&cinfo);
269 990
270 return true; 991 return true;
271 } 992 }
272 }; 993 };
273 994
274 /////////////////////////////////////////////////////////////////////////////// 995 ///////////////////////////////////////////////////////////////////////////////
996 DEFINE_DECODER_CREATOR(JPEGImageDecoder);
275 DEFINE_ENCODER_CREATOR(JPEGImageEncoder); 997 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
276 /////////////////////////////////////////////////////////////////////////////// 998 ///////////////////////////////////////////////////////////////////////////////
277 999
1000 static bool is_jpeg(SkStreamRewindable* stream) {
1001 static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
1002 static const size_t HEADER_SIZE = sizeof(gHeader);
1003
1004 char buffer[HEADER_SIZE];
1005 size_t len = stream->read(buffer, HEADER_SIZE);
1006
1007 if (len != HEADER_SIZE) {
1008 return false; // can't read enough
1009 }
1010 if (memcmp(buffer, gHeader, HEADER_SIZE)) {
1011 return false;
1012 }
1013 return true;
1014 }
1015
1016
1017 static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
1018 if (is_jpeg(stream)) {
1019 return new SkJPEGImageDecoder;
1020 }
1021 return nullptr;
1022 }
1023
1024 static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
1025 if (is_jpeg(stream)) {
1026 return SkImageDecoder::kJPEG_Format;
1027 }
1028 return SkImageDecoder::kUnknown_Format;
1029 }
1030
278 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 1031 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
279 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr; 1032 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
280 } 1033 }
281 1034
1035 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1036 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
282 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 1037 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW
« no previous file with comments | « src/images/SkImageDecoder_libico.cpp ('k') | src/images/SkImageDecoder_libpng.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698