static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
                       SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
                       SkImage::CachingHint hint) {
    size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
    sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
    dstColorSpace = fix_for_colortype(dstColorSpace.get(), dstColorType);
    SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
                                            dstAlphaType, dstColorSpace);
    if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
        memset(data->writable_data(), 0, rowBytes * image->height());
    }

    // SkImage must be premul, so manually premul the data if we unpremul'd during readPixels
    if (kUnpremul_SkAlphaType == dstAlphaType) {
        auto xform = SkColorSpaceXform::New(dstColorSpace.get(), dstColorSpace.get());
        if (!xform->apply(select_xform_format(dstColorType), data->writable_data(),
                          select_xform_format(dstColorType), data->data(),
                          image->width() * image->height(), kPremul_SkAlphaType)) {
            memset(data->writable_data(), 0, rowBytes * image->height());
        }
        dstInfo = dstInfo.makeAlphaType(kPremul_SkAlphaType);
    }

    // readPixels() does not always clamp F16.  The drawing code expects pixels in the 0-1 range.
    clamp_if_necessary(dstInfo, data->writable_data());

    // Now that we have called readPixels(), dump the raw pixels into an srgb image.
    sk_sp<SkColorSpace> srgb = fix_for_colortype(
            SkColorSpace::MakeSRGB().get(), dstColorType);
    sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
    canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
}
Beispiel #2
0
void ColorCodecBench::xformOnly() {
    sk_sp<SkColorSpace> srcSpace = SkColorSpace::MakeICC(fSrcData->data(), fSrcData->size());
    if (!srcSpace) {
        srcSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
    }
    std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace.get(),
                                                                      fDstSpace.get());
    SkASSERT(xform);

    void* dst = fDst.get();
    void* src = fSrc.get();
    for (int y = 0; y < fSrcInfo.height(); y++) {
        SkAssertResult(xform->apply(select_xform_format(fDstInfo.colorType()), dst,
                                    SkColorSpaceXform::kRGBA_8888_ColorFormat, src,
                                    fSrcInfo.width(), fDstInfo.alphaType()));
        dst = SkTAddOffset<void>(dst, fDstInfo.minRowBytes());
        src = SkTAddOffset<void>(src, fSrcInfo.minRowBytes());
    }
}
Beispiel #3
0
SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
                                        size_t dstRowBytes, const Options& options,
                                        SkPMColor ctable[], int* ctableCount,
                                        int* rowsDecoded) {
    if (!conversion_possible(dstInfo, this->getInfo()) ||
        !this->initializeColorXform(dstInfo, options.fPremulBehavior))
    {
        SkCodecPrintf("Error: cannot convert input type to output type.\n");
        return kInvalidConversion;
    }

    static const SkColorType kXformSrcColorType = kRGBA_8888_SkColorType;
    SkImageInfo swizzlerInfo = dstInfo;
    std::unique_ptr<uint32_t[]> xformBuffer = nullptr;
    if (this->colorXform()) {
        swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
        xformBuffer.reset(new uint32_t[dstInfo.width()]);
    }

    std::unique_ptr<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(
            this->getEncodedInfo(), nullptr, swizzlerInfo, options));
    SkASSERT(swizzler);

    const int width = dstInfo.width();
    const int height = dstInfo.height();
    std::unique_ptr<dng_image> image(fDngImage->render(width, height));
    if (!image) {
        return kInvalidInput;
    }

    // Because the DNG SDK can not guarantee to render to requested size, we allow a small
    // difference. Only the overlapping region will be converted.
    const float maxDiffRatio = 1.03f;
    const dng_point& imageSize = image->Size();
    if (imageSize.h / (float) width > maxDiffRatio || imageSize.h < width ||
        imageSize.v / (float) height > maxDiffRatio || imageSize.v < height) {
        return SkCodec::kInvalidScale;
    }

    void* dstRow = dst;
    SkAutoTMalloc<uint8_t> srcRow(width * 3);

    dng_pixel_buffer buffer;
    buffer.fData = &srcRow[0];
    buffer.fPlane = 0;
    buffer.fPlanes = 3;
    buffer.fColStep = buffer.fPlanes;
    buffer.fPlaneStep = 1;
    buffer.fPixelType = ttByte;
    buffer.fPixelSize = sizeof(uint8_t);
    buffer.fRowStep = width * 3;

    for (int i = 0; i < height; ++i) {
        buffer.fArea = dng_rect(i, 0, i + 1, width);

        try {
            image->Get(buffer, dng_image::edge_zero);
        } catch (...) {
            *rowsDecoded = i;
            return kIncompleteInput; 
        }

        if (this->colorXform()) {
            swizzler->swizzle(xformBuffer.get(), &srcRow[0]);

            const SkColorSpaceXform::ColorFormat srcFormat =
                    select_xform_format(kXformSrcColorType);
            const SkColorSpaceXform::ColorFormat dstFormat =
                    select_xform_format(dstInfo.colorType());
            this->colorXform()->apply(dstFormat, dstRow, srcFormat, xformBuffer.get(),
                                      dstInfo.width(), kOpaque_SkAlphaType);
            dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
        } else {
            swizzler->swizzle(dstRow, &srcRow[0]);
            dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
        }
    }
    return kSuccess;
}