SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, size_t dstRowBytes, const Options& options, SkPMColor ctable[], int* ctableCount, int* rowsDecoded) { if (!conversion_possible(requestedInfo, this->getInfo())) { SkCodecPrintf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler( SkSwizzler::kRGB, nullptr, requestedInfo, options)); SkASSERT(swizzler); const int width = requestedInfo.width(); const int height = requestedInfo.height(); SkAutoTDelete<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 / width > maxDiffRatio || imageSize.h < width || imageSize.v / 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; } swizzler->swizzle(dstRow, &srcRow[0]); dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); } return kSuccess; }
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; }