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