| 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 |