From 4a603fc591dcd36b3cb47344c244ecbbbaf179f4 Mon Sep 17 00:00:00 2001 From: msarett Date: Wed, 1 Jun 2016 09:16:04 -0700 Subject: [PATCH] Revert of Create SkColorSpaceXform to handle color conversions (patchset #10 id:260001 of https://codereview.chromium.org/1952063002/ ) Reason for revert: Google3 can't find qcms Original issue's description: > Create SkColorSpaceXform to handle color conversions > > Also adds testing of qcms color correction, so we can compare > SkColorSpaceXform outputs to qcms outputs. > > BUG=skia: > GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1952063002 > > Committed: https://skia.googlesource.com/skia/+/740cc88ee3d63c75e52d31238f2a32600cc57a8c TBR=reed@google.com,scroggo@google.com,mtklein@google.com,herb@google.com,brianosman@google.com # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review-Url: https://codereview.chromium.org/2023093004 --- dm/DM.cpp | 13 ++-- dm/DMSrcSink.cpp | 115 +++++++++++++++++---------------- dm/DMSrcSink.h | 6 +- gyp/core.gypi | 1 - gyp/ports.gyp | 1 - gyp/qcms.gyp | 2 +- include/codec/SkCodec.h | 11 ---- src/codec/SkJpegCodec.cpp | 23 ++----- src/codec/SkJpegCodec.h | 7 +- src/core/SkColorSpaceXform.cpp | 109 ------------------------------- src/core/SkColorSpaceXform.h | 51 --------------- 11 files changed, 77 insertions(+), 262 deletions(-) delete mode 100644 src/core/SkColorSpaceXform.cpp delete mode 100644 src/core/SkColorSpaceXform.h diff --git a/dm/DM.cpp b/dm/DM.cpp index e17fd358d0..8ee2ea739f 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -724,15 +724,18 @@ static bool gather_srcs() { return false; } + // Load the dstSpace. This particular dst is fairly similar to Adobe RGB. + SkAutoTUnref data(SkData::NewFromFileName( + GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str())); + sk_sp dstSpace = SkColorSpace::NewICC(data->data(), data->size()); + SkASSERT(dstSpace); + for (auto colorImage : colorImages) { - ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode); + ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode, nullptr); push_src("image", "color_codec_baseline", src); - src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode); + src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode, dstSpace); push_src("image", "color_codec_HPZR30w", src); - - src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode); - push_src("image", "color_codec_QCMS_HPZR30w", src); } return true; diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index a9851895bb..755bae378e 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -6,13 +6,11 @@ */ #include "DMSrcSink.h" -#include "Resources.h" #include "SkAndroidCodec.h" #include "SkCodec.h" #include "SkCodecImageGenerator.h" #include "SkColorSpace.h" #include "SkColorSpace_Base.h" -#include "SkColorSpaceXform.h" #include "SkCommonFlags.h" #include "SkData.h" #include "SkDocument.h" @@ -41,8 +39,6 @@ #include "SkAutoCoInitialize.h" #endif -#include "qcms.h" - DEFINE_bool(multiPage, false, "For document-type backends, render the source" " into multiple pages"); DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?"); @@ -855,9 +851,10 @@ Name ImageGenSrc::name() const { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -ColorCodecSrc::ColorCodecSrc(Path path, Mode mode) +ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, sk_sp dstSpace) : fPath(path) , fMode(mode) + , fDstSpace(dstSpace) {} bool ColorCodecSrc::veto(SinkFlags flags) const { @@ -865,6 +862,17 @@ bool ColorCodecSrc::veto(SinkFlags flags) const { return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect; } +static uint8_t clampFloatToByte(float v) { + v = v * 255.0f; + if (v > 255.0f) { + return 255; + } else if (v < 0.0f) { + return 0; + } else { + return (uint8_t) (v + 0.5f); + } +} + Error ColorCodecSrc::draw(SkCanvas* canvas) const { if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) { return Error::Nonfatal("No need to test color correction to 565 backend."); @@ -897,69 +905,62 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const { return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r); } - // Load the dst ICC profile. This particular dst is fairly similar to Adobe RGB. - sk_sp dstData = SkData::MakeFromFileName( - GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str()); - if (!dstData) { - return "Cannot read monitor profile. Is the resource path set correctly?"; - } - switch (fMode) { case kBaseline_Mode: canvas->drawBitmap(bitmap, 0, 0); break; case kDst_HPZR30w_Mode: { sk_sp srcSpace = sk_ref_sp(codec->getColorSpace()); - sk_sp dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size()); - SkASSERT(dstSpace); - - std::unique_ptr xform = SkColorSpaceXform::New(srcSpace, dstSpace); - if (!xform) { - // FIXME (msarett): - // I haven't implemented conversions for all of the images that I've uploaded for - // testing. Once we support all of them, this should be a fatal error. - return Error::Nonfatal("Unimplemented color conversion."); - } - - uint32_t* row = (uint32_t*) bitmap.getPixels(); - for (int y = 0; y < info.height(); y++) { - xform->xform_RGBA_8888(row, row, info.width()); - row = SkTAddOffset(row, bitmap.rowBytes()); - } - - canvas->drawBitmap(bitmap, 0, 0); - break; - } - case kQCMS_HPZR30w_Mode: { - sk_sp srcData = codec->getICCData(); - SkAutoTCallVProc - srcSpace(qcms_profile_from_memory(srcData->data(), srcData->size())); if (!srcSpace) { - return Error::Nonfatal(SkStringPrintf("QCMS cannot create profile for %s.\n", - fPath.c_str())); + return SkStringPrintf("Cannot test color correction without a src profile."); + } else if (!as_CSB(srcSpace)->gammas()->isValues()) { + // FIXME (msarett): + // The conversion here doesn't cover all of the images that I've uploaded for + // testing. Once we support all of them, this should be a fatal error. + return Error::Nonfatal("Unimplemented gamma conversion."); } - SkAutoTCallVProc - dstSpace(qcms_profile_from_memory(dstData->data(), dstData->size())); - SkASSERT(dstSpace); - SkAutoTCallVProc - transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, dstSpace, - QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); - if (!transform) { - return SkStringPrintf("QCMS cannot create transform for %s.\n", fPath.c_str()); - } + // Build a matrix to transform to dst gamut. + // srcToDst = inverse(dstToXYZ) * srcToXYZ + const SkMatrix44& srcToXYZ = srcSpace->xyz(); + const SkMatrix44& dstToXYZ = fDstSpace->xyz(); + SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); + dstToXYZ.invert(&srcToDst); + srcToDst.postConcat(srcToXYZ); -#ifdef SK_PMCOLOR_IS_RGBA - qcms_output_type outType = QCMS_OUTPUT_RGBX; -#else - qcms_output_type outType = QCMS_OUTPUT_BGRX; -#endif - - // Perform color correction. - uint32_t* row = (uint32_t*) bitmap.getPixels(); for (int y = 0; y < info.height(); y++) { - qcms_transform_data_type(transform, row, row, info.width(), outType); - row = SkTAddOffset(row, bitmap.rowBytes()); + for (int x = 0; x < info.width(); x++) { + // Extract floats. + uint32_t* pixelPtr = (uint32_t*) bitmap.getAddr(x, y); + float src[3]; + src[0] = ((*pixelPtr >> 0) & 0xFF) / 255.0f; + src[1] = ((*pixelPtr >> 8) & 0xFF) / 255.0f; + src[2] = ((*pixelPtr >> 16) & 0xFF) / 255.0f; + + // Convert to linear. + src[0] = pow(src[0], as_CSB(srcSpace)->gammas()->fRed.fValue); + src[1] = pow(src[1], as_CSB(srcSpace)->gammas()->fGreen.fValue); + src[2] = pow(src[2], as_CSB(srcSpace)->gammas()->fBlue.fValue); + + // Convert to dst gamut. + float dst[3]; + dst[0] = src[0]*srcToDst.getFloat(0, 0) + src[1]*srcToDst.getFloat(1, 0) + + src[2]*srcToDst.getFloat(2, 0) + srcToDst.getFloat(3, 0); + dst[1] = src[0]*srcToDst.getFloat(0, 1) + src[1]*srcToDst.getFloat(1, 1) + + src[2]*srcToDst.getFloat(2, 1) + srcToDst.getFloat(3, 1); + dst[2] = src[0]*srcToDst.getFloat(0, 2) + src[1]*srcToDst.getFloat(1, 2) + + src[2]*srcToDst.getFloat(2, 2) + srcToDst.getFloat(3, 2); + + // Convert to dst gamma. + dst[0] = pow(dst[0], 1.0f / as_CSB(fDstSpace)->gammas()->fRed.fValue); + dst[1] = pow(dst[1], 1.0f / as_CSB(fDstSpace)->gammas()->fGreen.fValue); + dst[2] = pow(dst[2], 1.0f / as_CSB(fDstSpace)->gammas()->fBlue.fValue); + + *pixelPtr = SkPackARGB32NoCheck(((*pixelPtr >> 24) & 0xFF), + clampFloatToByte(dst[0]), + clampFloatToByte(dst[1]), + clampFloatToByte(dst[2])); + } } canvas->drawBitmap(bitmap, 0, 0); diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index 70d52f260a..84096bf0fe 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -212,12 +212,9 @@ public: // TODO (msarett): Should we add a new test with a new monitor and verify that outputs // look identical on two different dsts? kDst_HPZR30w_Mode, - - // Use QCMS for color correction. - kQCMS_HPZR30w_Mode, }; - ColorCodecSrc(Path, Mode); + ColorCodecSrc(Path, Mode, sk_sp); Error draw(SkCanvas*) const override; SkISize size() const override; @@ -226,6 +223,7 @@ public: private: Path fPath; Mode fMode; + sk_sp fDstSpace; }; class SKPSrc : public Src { diff --git a/gyp/core.gypi b/gyp/core.gypi index ff3e270534..3319e6311c 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -76,7 +76,6 @@ '<(skia_src_path)/core/SkColorShader.cpp', '<(skia_src_path)/core/SkColorShader.h', '<(skia_src_path)/core/SkColorSpace.cpp', - '<(skia_src_path)/core/SkColorSpaceXform.cpp', '<(skia_src_path)/core/SkColorTable.cpp', '<(skia_src_path)/core/SkComposeShader.cpp', '<(skia_src_path)/core/SkConfig8888.cpp', diff --git a/gyp/ports.gyp b/gyp/ports.gyp index 536ae9ce49..6b29052144 100644 --- a/gyp/ports.gyp +++ b/gyp/ports.gyp @@ -14,7 +14,6 @@ 'core.gyp:*', 'qcms.gyp:qcms', ], - 'export_dependent_settings': [ 'qcms.gyp:qcms', ], 'include_dirs': [ '../include/effects', '../include/client/android', diff --git a/gyp/qcms.gyp b/gyp/qcms.gyp index fc007b3eee..ebd3fa4c84 100644 --- a/gyp/qcms.gyp +++ b/gyp/qcms.gyp @@ -19,7 +19,7 @@ 'direct_dependent_settings': { 'include_dirs': [ - '../third_party/qcms/src/', + './src', ], }, diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h index 31d6ea7cd5..f66eb85377 100644 --- a/include/codec/SkCodec.h +++ b/include/codec/SkCodec.h @@ -25,7 +25,6 @@ class SkSampler; namespace DM { class CodecSrc; -class ColorCodecSrc; } /** @@ -696,11 +695,6 @@ protected: virtual int onOutputScanline(int inputScanline) const; - /** - * Used for testing with qcms. - * FIXME: Remove this when we are done comparing with qcms. - */ - virtual sk_sp getICCData() const { return nullptr; } private: const SkEncodedInfo fEncodedInfo; const SkImageInfo fSrcInfo; @@ -776,11 +770,6 @@ private: virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; } friend class DM::CodecSrc; // for fillIncompleteImage - - // For testing with qcms - // FIXME: Remove this when we are done comparing with qcms. - friend class DM::ColorCodecSrc; - friend class SkSampledCodec; friend class SkIcoCodec; }; diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp index 0413f79a3c..85de356118 100644 --- a/src/codec/SkJpegCodec.cpp +++ b/src/codec/SkJpegCodec.cpp @@ -120,7 +120,7 @@ static bool is_icc_marker(jpeg_marker_struct* marker) { * (1) Discover all ICC profile markers and verify that they are numbered properly. * (2) Copy the data from each marker into a contiguous ICC profile. */ -static sk_sp get_icc_profile(jpeg_decompress_struct* dinfo) { +static sk_sp get_icc_profile(jpeg_decompress_struct* dinfo) { // Note that 256 will be enough storage space since each markerIndex is stored in 8-bits. jpeg_marker_struct* markerSequence[256]; memset(markerSequence, 0, sizeof(markerSequence)); @@ -165,8 +165,8 @@ static sk_sp get_icc_profile(jpeg_decompress_struct* dinfo) { } // Combine the ICC marker data into a contiguous profile. - sk_sp iccData = SkData::MakeUninitialized(totalBytes); - void* dst = iccData->writable_data(); + SkAutoMalloc iccData(totalBytes); + void* dst = iccData.get(); for (uint32_t i = 1; i <= numMarkers; i++) { jpeg_marker_struct* marker = markerSequence[i]; if (!marker) { @@ -180,7 +180,7 @@ static sk_sp get_icc_profile(jpeg_decompress_struct* dinfo) { dst = SkTAddOffset(dst, bytes); } - return iccData; + return SkColorSpace::NewICC(iccData.get(), totalBytes); } bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, @@ -221,14 +221,7 @@ bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, SkEncodedInfo info = SkEncodedInfo::Make(color, SkEncodedInfo::kOpaque_Alpha, 8); Origin orientation = get_exif_orientation(decoderMgr->dinfo()); - sk_sp iccData = get_icc_profile(decoderMgr->dinfo()); - sk_sp colorSpace = nullptr; - if (iccData) { - colorSpace = SkColorSpace::NewICC(iccData->data(), iccData->size()); - if (!colorSpace) { - SkCodecPrintf("Could not create SkColorSpace from ICC data.\n"); - } - } + sk_sp colorSpace = get_icc_profile(decoderMgr->dinfo()); if (!colorSpace) { // Treat unmarked jpegs as sRGB. colorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); @@ -237,7 +230,7 @@ bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, const int width = decoderMgr->dinfo()->image_width; const int height = decoderMgr->dinfo()->image_height; *codecOut = new SkJpegCodec(width, height, info, stream, decoderMgr.release(), - std::move(colorSpace), orientation, std::move(iccData)); + std::move(colorSpace), orientation); } else { SkASSERT(nullptr != decoderMgrOut); *decoderMgrOut = decoderMgr.release(); @@ -258,13 +251,11 @@ SkCodec* SkJpegCodec::NewFromStream(SkStream* stream) { } SkJpegCodec::SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream, - JpegDecoderMgr* decoderMgr, sk_sp colorSpace, Origin origin, - sk_sp iccData) + JpegDecoderMgr* decoderMgr, sk_sp colorSpace, Origin origin) : INHERITED(width, height, info, stream, std::move(colorSpace), origin) , fDecoderMgr(decoderMgr) , fReadyState(decoderMgr->dinfo()->global_state) , fSwizzlerSubset(SkIRect::MakeEmpty()) - , fICCData(std::move(iccData)) {} /* diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h index 7aa275ce4e..f8cddd0221 100644 --- a/src/codec/SkJpegCodec.h +++ b/src/codec/SkJpegCodec.h @@ -58,8 +58,6 @@ protected: bool onDimensionsSupported(const SkISize&) override; - sk_sp getICCData() const override { return fICCData; } - private: /* @@ -94,8 +92,7 @@ private: * takes ownership */ SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream, - JpegDecoderMgr* decoderMgr, sk_sp colorSpace, Origin origin, - sk_sp iccData); + JpegDecoderMgr* decoderMgr, sk_sp colorSpace, Origin origin); /* * Checks if the conversion between the input image and the requested output @@ -126,8 +123,6 @@ private: SkIRect fSwizzlerSubset; SkAutoTDelete fSwizzler; - sk_sp fICCData; - typedef SkCodec INHERITED; }; diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp deleted file mode 100644 index 473e715353..0000000000 --- a/src/core/SkColorSpaceXform.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkColorPriv.h" -#include "SkColorSpace_Base.h" -#include "SkColorSpaceXform.h" - -bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& srcToXYZ, - const SkMatrix44& dstToXYZ) { - if (!dstToXYZ.invert(srcToDst)) { - return false; - } - - srcToDst->postConcat(srcToXYZ); - return true; -} - -std::unique_ptr SkColorSpaceXform::New(const sk_sp& srcSpace, - const sk_sp& dstSpace) { - if (!srcSpace || !dstSpace) { - return nullptr; - } - - if (as_CSB(srcSpace)->gammas()->isValues() && as_CSB(dstSpace)->gammas()->isValues()) { - SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); - if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { - return nullptr; - } - - float srcGammas[3]; - float dstGammas[3]; - srcGammas[0] = as_CSB(srcSpace)->gammas()->fRed.fValue; - srcGammas[1] = as_CSB(srcSpace)->gammas()->fGreen.fValue; - srcGammas[2] = as_CSB(srcSpace)->gammas()->fBlue.fValue; - dstGammas[0] = 1.0f / as_CSB(dstSpace)->gammas()->fRed.fValue; - dstGammas[1] = 1.0f / as_CSB(dstSpace)->gammas()->fGreen.fValue; - dstGammas[2] = 1.0f / as_CSB(dstSpace)->gammas()->fBlue.fValue; - - return std::unique_ptr( - new SkGammaByValueXform(srcGammas, srcToDst, dstGammas)); - } - - // Unimplemeted - return nullptr; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -SkGammaByValueXform::SkGammaByValueXform(float srcGammas[3], const SkMatrix44& srcToDst, - float dstGammas[3]) - : fSrcToDst(srcToDst) -{ - memcpy(fSrcGammas, srcGammas, 3 * sizeof(float)); - memcpy(fDstGammas, dstGammas, 3 * sizeof(float)); -} - -static uint8_t clamp_float_to_byte(float v) { - v = v * 255.0f; - if (v > 255.0f) { - return 255; - } else if (v <= 0.0f) { - return 0; - } else { - return (uint8_t) (v + 0.5f); - } -} - -void SkGammaByValueXform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { - while (len-- > 0) { - float srcFloats[3]; - srcFloats[0] = ((*src >> 0) & 0xFF) * (1.0f / 255.0f); - srcFloats[1] = ((*src >> 8) & 0xFF) * (1.0f / 255.0f); - srcFloats[2] = ((*src >> 16) & 0xFF) * (1.0f / 255.0f); - - // Convert to linear. - srcFloats[0] = pow(srcFloats[0], fSrcGammas[0]); - srcFloats[1] = pow(srcFloats[1], fSrcGammas[1]); - srcFloats[2] = pow(srcFloats[2], fSrcGammas[2]); - - // Convert to dst gamut. - float dstFloats[3]; - dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) + - srcFloats[1] * fSrcToDst.getFloat(1, 0) + - srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFloat(3, 0); - dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) + - srcFloats[1] * fSrcToDst.getFloat(1, 1) + - srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFloat(3, 1); - dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) + - srcFloats[1] * fSrcToDst.getFloat(1, 2) + - srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFloat(3, 2); - - // Convert to dst gamma. - dstFloats[0] = pow(dstFloats[0], fDstGammas[0]); - dstFloats[1] = pow(dstFloats[1], fDstGammas[1]); - dstFloats[2] = pow(dstFloats[2], fDstGammas[2]); - - *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF), - clamp_float_to_byte(dstFloats[0]), - clamp_float_to_byte(dstFloats[1]), - clamp_float_to_byte(dstFloats[2])); - - dst++; - src++; - } -} diff --git a/src/core/SkColorSpaceXform.h b/src/core/SkColorSpaceXform.h deleted file mode 100644 index c3010f0cca..0000000000 --- a/src/core/SkColorSpaceXform.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkColorSpaceXform_DEFINED -#define SkColorSpaceXform_DEFINED - -#include "SkColorSpace.h" - -class SkColorSpaceXform { -public: - - /** - * Create an object to handle color space conversions. - * - * @param srcSpace The encoded color space. - * @param dstSpace The destination color space. - * - */ - static std::unique_ptr New(const sk_sp& srcSpace, - const sk_sp& dstSpace); - - /** - * Apply the color conversion to a src buffer, storing the output in the dst buffer. - * The src is stored in RGBA_8888 and the dst is stored in 8888 platform format. - * The output is not premultiplied. - */ - virtual void xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const = 0; - - virtual ~SkColorSpaceXform() {} -}; - -class SkGammaByValueXform : public SkColorSpaceXform { -public: - - void xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const override; - -private: - SkGammaByValueXform(float srcGammas[3], const SkMatrix44& srcToDst, float dstGammas[3]); - - float fSrcGammas[3]; - const SkMatrix44 fSrcToDst; - float fDstGammas[3]; - - friend class SkColorSpaceXform; -}; - -#endif