Example #1
0
void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
    SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
    if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
        srcConfig = SkSwizzler::kCMYK;
    } else {
        // If the out_color_space is not CMYK, the only reason we would need a swizzler is
        // for sampling and/or subsetting.
        switch (dstInfo.colorType()) {
            case kGray_8_SkColorType:
                srcConfig = SkSwizzler::kNoOp8;
                break;
            case kN32_SkColorType:
                srcConfig = SkSwizzler::kNoOp32;
                break;
            case kRGB_565_SkColorType:
                srcConfig = SkSwizzler::kNoOp16;
                break;
            default:
                // This function should only be called if the colorType is supported by jpeg
                SkASSERT(false);
        }
    }

    fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, options));
    fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
    fSrcRow = fStorage.get();
}
Example #2
0
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;
}
Example #3
0
// TODO (msarett): Avoid reallocating the memory buffer on each call to skip.
static uint32_t jpeg_skip_scanlines(jpeg_decompress_struct* dinfo, int count) {
    SkAutoTMalloc<uint8_t> storage(get_row_bytes(dinfo));
    uint8_t* storagePtr = storage.get();
    for (int y = 0; y < count; y++) {
        if (1 != jpeg_read_scanlines(dinfo, &storagePtr, 1)) {
            return y;
        }
    }
    return count;
}
Example #4
0
void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
    SkSwizzler::SrcConfig srcConfig = SkSwizzler::kUnknown;
    if (JCS_CMYK == fDecoderMgr->dinfo()->out_color_space) {
        srcConfig = SkSwizzler::kCMYK;
    } else {
        // If the out_color_space is not CMYK, the only reason we would need a swizzler is
        // for sampling and/or subsetting.
        switch (dstInfo.colorType()) {
            case kGray_8_SkColorType:
                srcConfig = SkSwizzler::kNoOp8;
                break;
            case kN32_SkColorType:
                srcConfig = SkSwizzler::kNoOp32;
                break;
            case kRGB_565_SkColorType:
                srcConfig = SkSwizzler::kNoOp16;
                break;
            default:
                // This function should only be called if the colorType is supported by jpeg
                SkASSERT(false);
        }
    }

    if (JCS_RGB == fDecoderMgr->dinfo()->out_color_space) {
        srcConfig = SkSwizzler::kRGB;
    }

    Options swizzlerOptions = options;
    if (options.fSubset) {
        // Use fSwizzlerSubset if this is a subset decode.  This is necessary in the case
        // where libjpeg-turbo provides a subset and then we need to subset it further.
        // Also, verify that fSwizzlerSubset is initialized and valid.
        SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
                fSwizzlerSubset.width() == options.fSubset->width());
        swizzlerOptions.fSubset = &fSwizzlerSubset;
    }
    fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, nullptr, dstInfo, swizzlerOptions));
    SkASSERT(fSwizzler);
    fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
    fSrcRow = fStorage.get();
}
Example #5
0
void SkJpegCodec::allocateStorage(const SkImageInfo& dstInfo) {
    size_t swizzleBytes = 0;
    if (fSwizzler) {
        swizzleBytes = get_row_bytes(fDecoderMgr->dinfo());
        SkASSERT(!fColorXform || SkIsAlign4(swizzleBytes));
    }

    size_t xformBytes = 0;
    if (kRGBA_F16_SkColorType == dstInfo.colorType()) {
        SkASSERT(fColorXform);
        xformBytes = dstInfo.width() * sizeof(uint32_t);
    }

    size_t totalBytes = swizzleBytes + xformBytes;
    if (totalBytes > 0) {
        fStorage.reset(totalBytes);
        fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
        fColorXformSrcRow = (xformBytes > 0) ?
                SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
    }
}
Example #6
0
bool SkJpegCodec::onSkipScanlines(int count) {
    // Set the jump location for libjpeg errors
    if (setjmp(fDecoderMgr->getJmpBuf())) {
        return fDecoderMgr->returnFalse("setjmp");
    }

#ifdef TURBO_HAS_SKIP
    return (uint32_t) count == jpeg_skip_scanlines(fDecoderMgr->dinfo(), count);
#else
    if (!fSrcRow) {
        fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
        fSrcRow = fStorage.get();
    }

    for (int y = 0; y < count; y++) {
        if (1 != jpeg_read_scanlines(fDecoderMgr->dinfo(), &fSrcRow, 1)) {
            return false;
        }
    }
    return true;
#endif
}
Example #7
0
void SkJpegCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& options) {
    // libjpeg-turbo may have already performed color conversion.  We must indicate the
    // appropriate format to the swizzler.
    SkEncodedInfo swizzlerInfo = this->getEncodedInfo();
    bool preSwizzled = true;
    switch (fDecoderMgr->dinfo()->out_color_space) {
        case JCS_RGB:
            preSwizzled = false;
            swizzlerInfo = SkEncodedInfo::Make(SkEncodedInfo::kRGB_Color,
                                               swizzlerInfo.alpha(),
                                               swizzlerInfo.bitsPerComponent());
            break;
        case JCS_CMYK:
            preSwizzled = false;
            swizzlerInfo = SkEncodedInfo::Make(
                    SkEncodedInfo::kInvertedCMYK_Color, swizzlerInfo.alpha(),
                    swizzlerInfo.bitsPerComponent());
            break;
        default:
            break;
    }

    Options swizzlerOptions = options;
    if (options.fSubset) {
        // Use fSwizzlerSubset if this is a subset decode.  This is necessary in the case
        // where libjpeg-turbo provides a subset and then we need to subset it further.
        // Also, verify that fSwizzlerSubset is initialized and valid.
        SkASSERT(!fSwizzlerSubset.isEmpty() && fSwizzlerSubset.x() <= options.fSubset->x() &&
                fSwizzlerSubset.width() == options.fSubset->width());
        swizzlerOptions.fSubset = &fSwizzlerSubset;
    }
    fSwizzler.reset(SkSwizzler::CreateSwizzler(swizzlerInfo, nullptr, dstInfo, swizzlerOptions,
                                               nullptr, preSwizzled));
    SkASSERT(fSwizzler);
    fStorage.reset(get_row_bytes(fDecoderMgr->dinfo()));
    fSrcRow = fStorage.get();
}
Example #8
0
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;
}