OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
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 #include "SkCodec.h" | 8 #include "SkCodec.h" |
9 #include "SkJpegCodec.h" | 9 #include "SkJpegCodec.h" |
10 #include "SkJpegDecoderMgr.h" | 10 #include "SkJpegDecoderMgr.h" |
11 #include "SkJpegUtility_codec.h" | 11 #include "SkJpegUtility_codec.h" |
12 #include "SkCodecPriv.h" | 12 #include "SkCodecPriv.h" |
13 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
14 #include "SkScaledCodec.h" | 14 #include "SkScaledCodec.h" |
15 #include "SkScanlineDecoder.h" | 15 #include "SkScanlineDecoder.h" |
16 #include "SkStream.h" | 16 #include "SkStream.h" |
17 #include "SkTemplates.h" | 17 #include "SkTemplates.h" |
18 #include "SkTypes.h" | 18 #include "SkTypes.h" |
19 | 19 |
20 // stdio is needed for libjpeg-turbo | 20 // stdio is needed for libjpeg-turbo |
21 #include <stdio.h> | 21 #include <stdio.h> |
22 | 22 |
23 extern "C" { | 23 extern "C" { |
24 #include "jpeglibmangler.h" | |
25 #include "jerror.h" | 24 #include "jerror.h" |
26 #include "jpegint.h" | |
27 #include "jpeglib.h" | 25 #include "jpeglib.h" |
28 } | 26 } |
29 | 27 |
30 /* | 28 /* |
31 * Convert a row of CMYK samples to RGBA in place. | 29 * Convert a row of CMYK samples to RGBA in place. |
32 * Note that this method moves the row pointer. | 30 * Note that this method moves the row pointer. |
33 * @param width the number of pixels in the row that is being converted | 31 * @param width the number of pixels in the row that is being converted |
34 * CMYK is stored as four bytes per pixel | 32 * CMYK is stored as four bytes per pixel |
35 */ | 33 */ |
36 static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) { | 34 static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 | 103 |
106 // libjpeg errors will be caught and reported here | 104 // libjpeg errors will be caught and reported here |
107 if (setjmp(decoderMgr->getJmpBuf())) { | 105 if (setjmp(decoderMgr->getJmpBuf())) { |
108 return decoderMgr->returnFalse("setjmp"); | 106 return decoderMgr->returnFalse("setjmp"); |
109 } | 107 } |
110 | 108 |
111 // Initialize the decompress info and the source manager | 109 // Initialize the decompress info and the source manager |
112 decoderMgr->init(); | 110 decoderMgr->init(); |
113 | 111 |
114 // Read the jpeg header | 112 // Read the jpeg header |
115 if (JPEG_HEADER_OK != chromium_jpeg_read_header(decoderMgr->dinfo(), true))
{ | 113 if (JPEG_HEADER_OK != jpeg_read_header(decoderMgr->dinfo(), true)) { |
116 return decoderMgr->returnFalse("read_header"); | 114 return decoderMgr->returnFalse("read_header"); |
117 } | 115 } |
118 | 116 |
119 if (nullptr != codecOut) { | 117 if (nullptr != codecOut) { |
120 // Recommend the color type to decode to | 118 // Recommend the color type to decode to |
121 const SkColorType colorType = decoderMgr->getColorType(); | 119 const SkColorType colorType = decoderMgr->getColorType(); |
122 | 120 |
123 // Create image info object and the codec | 121 // Create image info object and the codec |
124 const SkImageInfo& imageInfo = SkImageInfo::Make(decoderMgr->dinfo()->im
age_width, | 122 const SkImageInfo& imageInfo = SkImageInfo::Make(decoderMgr->dinfo()->im
age_width, |
125 decoderMgr->dinfo()->image_height, colorType, kOpaque_SkAlphaTyp
e); | 123 decoderMgr->dinfo()->image_height, colorType, kOpaque_SkAlphaTyp
e); |
(...skipping 14 matching lines...) Expand all Loading... |
140 streamDeleter.detach(); | 138 streamDeleter.detach(); |
141 return codec; | 139 return codec; |
142 } | 140 } |
143 return nullptr; | 141 return nullptr; |
144 } | 142 } |
145 | 143 |
146 SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, | 144 SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, |
147 JpegDecoderMgr* decoderMgr) | 145 JpegDecoderMgr* decoderMgr) |
148 : INHERITED(srcInfo, stream) | 146 : INHERITED(srcInfo, stream) |
149 , fDecoderMgr(decoderMgr) | 147 , fDecoderMgr(decoderMgr) |
| 148 , fReadyState(decoderMgr->dinfo()->global_state) |
150 {} | 149 {} |
151 | 150 |
152 /* | 151 /* |
153 * Return the row bytes of a particular image type and width | 152 * Return the row bytes of a particular image type and width |
154 */ | 153 */ |
155 static int get_row_bytes(const j_decompress_ptr dinfo) { | 154 static int get_row_bytes(const j_decompress_ptr dinfo) { |
156 int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_col
or_components; | 155 int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_col
or_components; |
157 return dinfo->output_width * colorBytes; | 156 return dinfo->output_width * colorBytes; |
158 | 157 |
159 } | 158 } |
(...skipping 21 matching lines...) Expand all Loading... |
181 num = 2; | 180 num = 2; |
182 } else { | 181 } else { |
183 num = 1; | 182 num = 1; |
184 } | 183 } |
185 | 184 |
186 // Set up a fake decompress struct in order to use libjpeg to calculate outp
ut dimensions | 185 // Set up a fake decompress struct in order to use libjpeg to calculate outp
ut dimensions |
187 jpeg_decompress_struct dinfo; | 186 jpeg_decompress_struct dinfo; |
188 sk_bzero(&dinfo, sizeof(dinfo)); | 187 sk_bzero(&dinfo, sizeof(dinfo)); |
189 dinfo.image_width = this->getInfo().width(); | 188 dinfo.image_width = this->getInfo().width(); |
190 dinfo.image_height = this->getInfo().height(); | 189 dinfo.image_height = this->getInfo().height(); |
191 dinfo.global_state = DSTATE_READY; | 190 dinfo.global_state = fReadyState; |
192 dinfo.num_components = 0; | 191 dinfo.num_components = 0; |
193 dinfo.scale_num = num; | 192 dinfo.scale_num = num; |
194 dinfo.scale_denom = denom; | 193 dinfo.scale_denom = denom; |
195 chromium_jpeg_calc_output_dimensions(&dinfo); | 194 jpeg_calc_output_dimensions(&dinfo); |
196 | 195 |
197 // Return the calculated output dimensions for the given scale | 196 // Return the calculated output dimensions for the given scale |
198 return SkISize::Make(dinfo.output_width, dinfo.output_height); | 197 return SkISize::Make(dinfo.output_width, dinfo.output_height); |
199 } | 198 } |
200 | 199 |
201 bool SkJpegCodec::onRewind() { | 200 bool SkJpegCodec::onRewind() { |
202 JpegDecoderMgr* decoderMgr = nullptr; | 201 JpegDecoderMgr* decoderMgr = nullptr; |
203 if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) { | 202 if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) { |
204 return fDecoderMgr->returnFalse("could not rewind"); | 203 return fDecoderMgr->returnFalse("could not rewind"); |
205 } | 204 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 } | 266 } |
268 | 267 |
269 /* | 268 /* |
270 * Checks if we can natively scale to the requested dimensions and natively scal
es the | 269 * Checks if we can natively scale to the requested dimensions and natively scal
es the |
271 * dimensions if possible | 270 * dimensions if possible |
272 */ | 271 */ |
273 bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeigh
t) { | 272 bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeigh
t) { |
274 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1 | 273 // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1 |
275 fDecoderMgr->dinfo()->scale_denom = 8; | 274 fDecoderMgr->dinfo()->scale_denom = 8; |
276 fDecoderMgr->dinfo()->scale_num = 8; | 275 fDecoderMgr->dinfo()->scale_num = 8; |
277 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); | 276 jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); |
278 while (fDecoderMgr->dinfo()->output_width != dstWidth || | 277 while (fDecoderMgr->dinfo()->output_width != dstWidth || |
279 fDecoderMgr->dinfo()->output_height != dstHeight) { | 278 fDecoderMgr->dinfo()->output_height != dstHeight) { |
280 | 279 |
281 // Return a failure if we have tried all of the possible scales | 280 // Return a failure if we have tried all of the possible scales |
282 if (1 == fDecoderMgr->dinfo()->scale_num || | 281 if (1 == fDecoderMgr->dinfo()->scale_num || |
283 dstWidth > fDecoderMgr->dinfo()->output_width || | 282 dstWidth > fDecoderMgr->dinfo()->output_width || |
284 dstHeight > fDecoderMgr->dinfo()->output_height) { | 283 dstHeight > fDecoderMgr->dinfo()->output_height) { |
285 // reset native scale settings on failure because this may be suppor
ted by the swizzler | 284 // reset native scale settings on failure because this may be suppor
ted by the swizzler |
286 this->fDecoderMgr->dinfo()->scale_num = 8; | 285 this->fDecoderMgr->dinfo()->scale_num = 8; |
287 chromium_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo()); | 286 jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo()); |
288 return false; | 287 return false; |
289 } | 288 } |
290 | 289 |
291 // Try the next scale | 290 // Try the next scale |
292 fDecoderMgr->dinfo()->scale_num -= 1; | 291 fDecoderMgr->dinfo()->scale_num -= 1; |
293 chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); | 292 jpeg_calc_output_dimensions(fDecoderMgr->dinfo()); |
294 } | 293 } |
295 return true; | 294 return true; |
296 } | 295 } |
297 | 296 |
298 /* | 297 /* |
299 * Performs the jpeg decode | 298 * Performs the jpeg decode |
300 */ | 299 */ |
301 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, | 300 SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, |
302 void* dst, size_t dstRowBytes, | 301 void* dst, size_t dstRowBytes, |
303 const Options& options, SkPMColor*, int
*) { | 302 const Options& options, SkPMColor*, int
*) { |
(...skipping 19 matching lines...) Expand all Loading... |
323 if (!this->setOutputColorSpace(dstInfo)) { | 322 if (!this->setOutputColorSpace(dstInfo)) { |
324 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConvers
ion); | 323 return fDecoderMgr->returnFailure("conversion_possible", kInvalidConvers
ion); |
325 } | 324 } |
326 | 325 |
327 // Perform the necessary scaling | 326 // Perform the necessary scaling |
328 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { | 327 if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) { |
329 return fDecoderMgr->returnFailure("cannot scale to requested dims", kInv
alidScale); | 328 return fDecoderMgr->returnFailure("cannot scale to requested dims", kInv
alidScale); |
330 } | 329 } |
331 | 330 |
332 // Now, given valid output dimensions, we can start the decompress | 331 // Now, given valid output dimensions, we can start the decompress |
333 if (!chromium_jpeg_start_decompress(dinfo)) { | 332 if (!jpeg_start_decompress(dinfo)) { |
334 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); | 333 return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); |
335 } | 334 } |
336 | 335 |
337 // The recommended output buffer height should always be 1 in high quality m
odes. | 336 // The recommended output buffer height should always be 1 in high quality m
odes. |
338 // If it's not, we want to know because it means our strategy is not optimal
. | 337 // If it's not, we want to know because it means our strategy is not optimal
. |
339 SkASSERT(1 == dinfo->rec_outbuf_height); | 338 SkASSERT(1 == dinfo->rec_outbuf_height); |
340 | 339 |
341 // Perform the decode a single row at a time | 340 // Perform the decode a single row at a time |
342 uint32_t dstHeight = dstInfo.height(); | 341 uint32_t dstHeight = dstInfo.height(); |
343 JSAMPLE* dstRow = (JSAMPLE*) dst; | 342 JSAMPLE* dstRow = (JSAMPLE*) dst; |
344 for (uint32_t y = 0; y < dstHeight; y++) { | 343 for (uint32_t y = 0; y < dstHeight; y++) { |
345 // Read rows of the image | 344 // Read rows of the image |
346 uint32_t rowsDecoded = chromium_jpeg_read_scanlines(dinfo, &dstRow, 1); | 345 uint32_t rowsDecoded = jpeg_read_scanlines(dinfo, &dstRow, 1); |
347 | 346 |
348 // If we cannot read enough rows, assume the input is incomplete | 347 // If we cannot read enough rows, assume the input is incomplete |
349 if (rowsDecoded != 1) { | 348 if (rowsDecoded != 1) { |
350 // Fill the remainder of the image with black. This error handling | 349 // Fill the remainder of the image with black. This error handling |
351 // behavior is unspecified but SkCodec consistently uses black as | 350 // behavior is unspecified but SkCodec consistently uses black as |
352 // the fill color for opaque images. If the destination is kGray, | 351 // the fill color for opaque images. If the destination is kGray, |
353 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, | 352 // the low 8 bits of SK_ColorBLACK will be used. Conveniently, |
354 // these are zeros, which is the representation for black in kGray. | 353 // these are zeros, which is the representation for black in kGray. |
355 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK | 354 // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK |
356 // will be used. Conveniently, these are zeros, which is the | 355 // will be used. Conveniently, these are zeros, which is the |
357 // representation for black in kRGB_565. | 356 // representation for black in kRGB_565. |
358 if (kNo_ZeroInitialized == options.fZeroInitialized || | 357 if (kNo_ZeroInitialized == options.fZeroInitialized || |
359 kN32_SkColorType == dstInfo.colorType()) { | 358 kN32_SkColorType == dstInfo.colorType()) { |
360 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, | 359 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y, |
361 SK_ColorBLACK, nullptr); | 360 SK_ColorBLACK, nullptr); |
362 } | 361 } |
363 | 362 |
364 // Prevent libjpeg from failing on incomplete decode | 363 // Prevent libjpeg from failing on incomplete decode |
365 dinfo->output_scanline = dstHeight; | 364 dinfo->output_scanline = dstHeight; |
366 | 365 |
367 // Finish the decode and indicate that the input was incomplete. | 366 // Finish the decode and indicate that the input was incomplete. |
368 chromium_jpeg_finish_decompress(dinfo); | 367 jpeg_finish_decompress(dinfo); |
369 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); | 368 return fDecoderMgr->returnFailure("Incomplete image data", kIncomple
teInput); |
370 } | 369 } |
371 | 370 |
372 // Convert to RGBA if necessary | 371 // Convert to RGBA if necessary |
373 if (JCS_CMYK == dinfo->out_color_space) { | 372 if (JCS_CMYK == dinfo->out_color_space) { |
374 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); | 373 convert_CMYK_to_RGBA(dstRow, dstInfo.width()); |
375 } | 374 } |
376 | 375 |
377 // Move to the next row | 376 // Move to the next row |
378 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); | 377 dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); |
379 } | 378 } |
380 chromium_jpeg_finish_decompress(dinfo); | 379 jpeg_finish_decompress(dinfo); |
381 | 380 |
382 return kSuccess; | 381 return kSuccess; |
383 } | 382 } |
384 | 383 |
385 /* | 384 /* |
386 * Enable scanline decoding for jpegs | 385 * Enable scanline decoding for jpegs |
387 */ | 386 */ |
388 class SkJpegScanlineDecoder : public SkScanlineDecoder { | 387 class SkJpegScanlineDecoder : public SkScanlineDecoder { |
389 public: | 388 public: |
390 SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec) | 389 SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 return result; | 466 return result; |
468 } | 467 } |
469 fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo())); | 468 fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo())); |
470 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 469 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
471 } else { | 470 } else { |
472 fSrcRow = nullptr; | 471 fSrcRow = nullptr; |
473 fSwizzler.reset(nullptr); | 472 fSwizzler.reset(nullptr); |
474 } | 473 } |
475 | 474 |
476 // Now, given valid output dimensions, we can start the decompress | 475 // Now, given valid output dimensions, we can start the decompress |
477 if (!chromium_jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) { | 476 if (!jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) { |
478 SkCodecPrintf("start decompress failed\n"); | 477 SkCodecPrintf("start decompress failed\n"); |
479 return SkCodec::kInvalidInput; | 478 return SkCodec::kInvalidInput; |
480 } | 479 } |
481 | 480 |
482 fOpts = options; | 481 fOpts = options; |
483 | 482 |
484 return SkCodec::kSuccess; | 483 return SkCodec::kSuccess; |
485 } | 484 } |
486 | 485 |
487 virtual ~SkJpegScanlineDecoder() { | 486 virtual ~SkJpegScanlineDecoder() { |
488 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { | 487 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
489 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); | 488 SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n"); |
490 return; | 489 return; |
491 } | 490 } |
492 | 491 |
493 // We may not have decoded the entire image. Prevent libjpeg-turbo from
failing on a | 492 // We may not have decoded the entire image. Prevent libjpeg-turbo from
failing on a |
494 // partial decode. | 493 // partial decode. |
495 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height
(); | 494 fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height
(); |
496 chromium_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); | 495 jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo()); |
497 } | 496 } |
498 | 497 |
499 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { | 498 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
de { |
500 // Set the jump location for libjpeg errors | 499 // Set the jump location for libjpeg errors |
501 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { | 500 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
502 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali
dInput); | 501 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali
dInput); |
503 } | 502 } |
504 // Read rows one at a time | 503 // Read rows one at a time |
505 JSAMPLE* dstRow; | 504 JSAMPLE* dstRow; |
506 if (fSwizzler) { | 505 if (fSwizzler) { |
507 // write data to storage row, then sample using swizzler | 506 // write data to storage row, then sample using swizzler |
508 dstRow = fSrcRow; | 507 dstRow = fSrcRow; |
509 } else { | 508 } else { |
510 // write data directly to dst | 509 // write data directly to dst |
511 dstRow = (JSAMPLE*) dst; | 510 dstRow = (JSAMPLE*) dst; |
512 } | 511 } |
513 | 512 |
514 for (int y = 0; y < count; y++) { | 513 for (int y = 0; y < count; y++) { |
515 // Read row of the image | 514 // Read row of the image |
516 uint32_t rowsDecoded = | 515 uint32_t rowsDecoded = jpeg_read_scanlines(fCodec->fDecoderMgr->dinf
o(), &dstRow, 1); |
517 chromium_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &
dstRow, 1); | |
518 if (rowsDecoded != 1) { | 516 if (rowsDecoded != 1) { |
519 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized || | 517 if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized || |
520 kN32_SkColorType == this->dstInfo().colorType()) { | 518 kN32_SkColorType == this->dstInfo().colorType()) { |
521 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, | 519 SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, |
522 count - y, SK_ColorBLACK, nullptr); | 520 count - y, SK_ColorBLACK, nullptr); |
523 } | 521 } |
524 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo().
height(); | 522 fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo().
height(); |
525 return SkCodec::kIncompleteInput; | 523 return SkCodec::kIncompleteInput; |
526 } | 524 } |
527 | 525 |
528 // Convert to RGBA if necessary | 526 // Convert to RGBA if necessary |
529 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { | 527 if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) { |
530 convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->outpu
t_width); | 528 convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->outpu
t_width); |
531 } | 529 } |
532 | 530 |
533 if(fSwizzler) { | 531 if(fSwizzler) { |
534 // use swizzler to sample row | 532 // use swizzler to sample row |
535 fSwizzler->swizzle(dst, dstRow); | 533 fSwizzler->swizzle(dst, dstRow); |
536 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); | 534 dst = SkTAddOffset<JSAMPLE>(dst, rowBytes); |
537 } else { | 535 } else { |
538 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); | 536 dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes); |
539 } | 537 } |
540 } | 538 } |
541 return SkCodec::kSuccess; | 539 return SkCodec::kSuccess; |
542 } | 540 } |
543 | 541 |
544 #ifndef TURBO_HAS_SKIP | 542 #ifndef TURBO_HAS_SKIP |
545 // TODO (msarett): Make this a member function and avoid reallocating the | 543 // TODO (msarett): Make this a member function and avoid reallocating the |
546 // memory buffer on each call to skip. | 544 // memory buffer on each call to skip. |
547 #define chromium_jpeg_skip_scanlines(dinfo, count) \ | 545 #define jpeg_skip_scanlines(dinfo, count) \ |
548 SkAutoMalloc storage(get_row_bytes(dinfo)); \ | 546 SkAutoMalloc storage(get_row_bytes(dinfo)); \ |
549 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ | 547 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); \ |
550 for (int y = 0; y < count; y++) { \ | 548 for (int y = 0; y < count; y++) { \ |
551 chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1); \ | 549 jpeg_read_scanlines(dinfo, &storagePtr, 1); \ |
552 } | 550 } |
553 #endif | 551 #endif |
554 | 552 |
555 SkCodec::Result onSkipScanlines(int count) override { | 553 SkCodec::Result onSkipScanlines(int count) override { |
556 // Set the jump location for libjpeg errors | 554 // Set the jump location for libjpeg errors |
557 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { | 555 if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) { |
558 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali
dInput); | 556 return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvali
dInput); |
559 } | 557 } |
560 | 558 |
561 chromium_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); | 559 jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count); |
562 | 560 |
563 return SkCodec::kSuccess; | 561 return SkCodec::kSuccess; |
564 } | 562 } |
565 | 563 |
566 SkEncodedFormat onGetEncodedFormat() const override { | 564 SkEncodedFormat onGetEncodedFormat() const override { |
567 return kJPEG_SkEncodedFormat; | 565 return kJPEG_SkEncodedFormat; |
568 } | 566 } |
569 | 567 |
570 private: | 568 private: |
571 SkAutoTDelete<SkJpegCodec> fCodec; | 569 SkAutoTDelete<SkJpegCodec> fCodec; |
572 SkAutoMalloc fStorage; // Only used if sampling is needed | 570 SkAutoMalloc fStorage; // Only used if sampling is needed |
573 uint8_t* fSrcRow; // Only used if sampling is needed | 571 uint8_t* fSrcRow; // Only used if sampling is needed |
574 SkCodec::Options fOpts; | 572 SkCodec::Options fOpts; |
575 SkAutoTDelete<SkSwizzler> fSwizzler; | 573 SkAutoTDelete<SkSwizzler> fSwizzler; |
576 | 574 |
577 typedef SkScanlineDecoder INHERITED; | 575 typedef SkScanlineDecoder INHERITED; |
578 }; | 576 }; |
579 | 577 |
580 SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) { | 578 SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) { |
581 SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewF
romStream(stream))); | 579 SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewF
romStream(stream))); |
582 if (!codec) { | 580 if (!codec) { |
583 return nullptr; | 581 return nullptr; |
584 } | 582 } |
585 | 583 |
586 const SkImageInfo& srcInfo = codec->getInfo(); | 584 const SkImageInfo& srcInfo = codec->getInfo(); |
587 | 585 |
588 // Return the new scanline decoder | 586 // Return the new scanline decoder |
589 return new SkJpegScanlineDecoder(srcInfo, codec.detach()); | 587 return new SkJpegScanlineDecoder(srcInfo, codec.detach()); |
590 } | 588 } |
OLD | NEW |