int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count) { // Set the jump location for libjpeg-turbo errors if (setjmp(fDecoderMgr->getJmpBuf())) { return 0; } // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case, // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer. // We can never swizzle "in place" because the swizzler may perform sampling and/or // subsetting. // When fColorXformSrcRow is non-null, it means that we need to color xform and that // we cannot color xform "in place" (many times we can, but not when the dst is F16). // In this case, we will color xform from fColorXformSrc into the dst. JSAMPLE* decodeDst = (JSAMPLE*) dst; uint32_t* swizzleDst = (uint32_t*) dst; size_t decodeDstRowBytes = rowBytes; size_t swizzleDstRowBytes = rowBytes; if (fSwizzleSrcRow && fColorXformSrcRow) { decodeDst = (JSAMPLE*) fSwizzleSrcRow; swizzleDst = fColorXformSrcRow; decodeDstRowBytes = 0; swizzleDstRowBytes = 0; } else if (fColorXformSrcRow) { decodeDst = (JSAMPLE*) fColorXformSrcRow; swizzleDst = fColorXformSrcRow; decodeDstRowBytes = 0; swizzleDstRowBytes = 0; } else if (fSwizzleSrcRow) { decodeDst = (JSAMPLE*) fSwizzleSrcRow; decodeDstRowBytes = 0; } for (int y = 0; y < count; y++) { uint32_t lines = jpeg_read_scanlines(fDecoderMgr->dinfo(), &decodeDst, 1); size_t srcRowBytes = get_row_bytes(fDecoderMgr->dinfo()); sk_msan_mark_initialized(decodeDst, decodeDst + srcRowBytes, "skbug.com/4550"); if (0 == lines) { return y; } if (fSwizzler) { fSwizzler->swizzle(swizzleDst, decodeDst); } if (fColorXform) { fColorXform->apply(dst, swizzleDst, dstInfo.width(), dstInfo.colorType(), kOpaque_SkAlphaType); dst = SkTAddOffset<void>(dst, rowBytes); } decodeDst = SkTAddOffset<JSAMPLE>(decodeDst, decodeDstRowBytes); swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes); } return count; }
int SkJpegCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { // Set the jump location for libjpeg errors if (setjmp(fDecoderMgr->getJmpBuf())) { return fDecoderMgr->returnFailure("setjmp", kInvalidInput); } // Read rows one at a time JSAMPLE* dstRow; size_t srcRowBytes = get_row_bytes(fDecoderMgr->dinfo()); if (fSwizzler) { // write data to storage row, then sample using swizzler dstRow = fSrcRow; } else { // write data directly to dst SkASSERT(count == 1 || dstRowBytes >= srcRowBytes); dstRow = (JSAMPLE*) dst; } for (int y = 0; y < count; y++) { // Read row of the image uint32_t rowsDecoded = jpeg_read_scanlines(fDecoderMgr->dinfo(), &dstRow, 1); sk_msan_mark_initialized(dstRow, dstRow + srcRowBytes, "skbug.com/4550"); if (rowsDecoded != 1) { fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height(); return y; } if (fSwizzler) { // use swizzler to sample row fSwizzler->swizzle(dst, dstRow); dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes); } else { dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); } } return count; }
/* * Performs the jpeg decode */ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& options, SkPMColor*, int*, int* rowsDecoded) { if (options.fSubset) { // Subsets are not supported. return kUnimplemented; } // Get a pointer to the decompress info since we will use it quite frequently jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); // Set the jump location for libjpeg errors if (setjmp(fDecoderMgr->getJmpBuf())) { return fDecoderMgr->returnFailure("setjmp", kInvalidInput); } // Check if we can decode to the requested destination and set the output color space if (!this->setOutputColorSpace(dstInfo)) { return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion); } // Now, given valid output dimensions, we can start the decompress if (!jpeg_start_decompress(dinfo)) { return fDecoderMgr->returnFailure("startDecompress", kInvalidInput); } // The recommended output buffer height should always be 1 in high quality modes. // If it's not, we want to know because it means our strategy is not optimal. SkASSERT(1 == dinfo->rec_outbuf_height); J_COLOR_SPACE colorSpace = dinfo->out_color_space; if (JCS_CMYK == colorSpace || JCS_RGB == colorSpace) { this->initializeSwizzler(dstInfo, options); } // Perform the decode a single row at a time uint32_t dstHeight = dstInfo.height(); JSAMPLE* dstRow; if (fSwizzler) { // write data to storage row, then sample using swizzler dstRow = fSrcRow; } else { // write data directly to dst dstRow = (JSAMPLE*) dst; } for (uint32_t y = 0; y < dstHeight; y++) { // Read rows of the image uint32_t lines = jpeg_read_scanlines(dinfo, &dstRow, 1); sk_msan_mark_initialized(dstRow, dstRow + dstRowBytes, "skbug.com/4550"); // If we cannot read enough rows, assume the input is incomplete if (lines != 1) { *rowsDecoded = y; return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput); } if (fSwizzler) { // use swizzler to sample row fSwizzler->swizzle(dst, dstRow); dst = SkTAddOffset<JSAMPLE>(dst, dstRowBytes); } else { dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes); } } return kSuccess; }