diff options
author | msarett <msarett@google.com> | 2016-06-01 14:47:18 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-01 14:47:18 -0700 |
commit | 9876ac5b3016e5353c072378ac1545a0a2270757 (patch) | |
tree | 2ca6c3c24f94550d2e8c71f2a1b57d0eea5a0f1c /dm | |
parent | 81e4cc7723ea87de8b8917e52cc25f524225fa43 (diff) |
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
Review-Url: https://codereview.chromium.org/1952063002
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DM.cpp | 15 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 117 | ||||
-rw-r--r-- | dm/DMSrcSink.h | 8 |
3 files changed, 73 insertions, 67 deletions
@@ -724,18 +724,17 @@ static bool gather_srcs() { return false; } - // Load the dstSpace. This particular dst is fairly similar to Adobe RGB. - SkAutoTUnref<SkData> data(SkData::NewFromFileName( - GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str())); - sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewICC(data->data(), data->size()); - SkASSERT(dstSpace); - for (auto colorImage : colorImages) { - ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode, nullptr); + ColorCodecSrc* src = new ColorCodecSrc(colorImage, ColorCodecSrc::kBaseline_Mode); push_src("image", "color_codec_baseline", src); - src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode, dstSpace); + src = new ColorCodecSrc(colorImage, ColorCodecSrc::kDst_HPZR30w_Mode); push_src("image", "color_codec_HPZR30w", src); + +#if !defined(GOOGLE3) + src = new ColorCodecSrc(colorImage, ColorCodecSrc::kQCMS_HPZR30w_Mode); + push_src("image", "color_codec_QCMS_HPZR30w", src); +#endif } return true; diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index f8c9bc0b58..356416035b 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -6,11 +6,13 @@ */ #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" @@ -39,6 +41,10 @@ #include "SkAutoCoInitialize.h" #endif +#if !defined(GOOGLE3) + #include "qcms.h" +#endif + 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?"); @@ -827,10 +833,9 @@ Name ImageGenSrc::name() const { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, sk_sp<SkColorSpace> dstSpace) +ColorCodecSrc::ColorCodecSrc(Path path, Mode mode) : fPath(path) , fMode(mode) - , fDstSpace(dstSpace) {} bool ColorCodecSrc::veto(SinkFlags flags) const { @@ -838,17 +843,6 @@ 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."); @@ -881,67 +875,76 @@ 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<SkData> 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<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace()); - if (!srcSpace) { - return SkStringPrintf("Cannot test color correction without a src profile."); - } else if (!as_CSB(srcSpace)->gammas()->isValues()) { + sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size()); + SkASSERT(dstSpace); + + std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcSpace, dstSpace); + if (!xform) { // FIXME (msarett): - // The conversion here doesn't cover all of the images that I've uploaded for + // 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 gamma conversion."); + 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<uint32_t>(row, bitmap.rowBytes()); } - // 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); + canvas->drawBitmap(bitmap, 0, 0); + break; + } +#if !defined(GOOGLE3) + case kQCMS_HPZR30w_Mode: { + sk_sp<SkData> srcData = codec->getICCData(); + SkAutoTCallVProc<qcms_profile, qcms_profile_release> + 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())); + } + + SkAutoTCallVProc<qcms_profile, qcms_profile_release> + dstSpace(qcms_profile_from_memory(dstData->data(), dstData->size())); + SkASSERT(dstSpace); + SkAutoTCallVProc<qcms_transform, qcms_transform_release> + 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()); + } +#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++) { - 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])); - } + qcms_transform_data_type(transform, row, row, info.width(), outType); + row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes()); } canvas->drawBitmap(bitmap, 0, 0); break; } +#endif default: SkASSERT(false); return "Invalid fMode"; diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index 84096bf0fe..42f0e6da36 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -212,9 +212,14 @@ 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, + +#if !defined(GOOGLE3) + // Use QCMS for color correction. + kQCMS_HPZR30w_Mode, +#endif }; - ColorCodecSrc(Path, Mode, sk_sp<SkColorSpace>); + ColorCodecSrc(Path, Mode); Error draw(SkCanvas*) const override; SkISize size() const override; @@ -223,7 +228,6 @@ public: private: Path fPath; Mode fMode; - sk_sp<SkColorSpace> fDstSpace; }; class SKPSrc : public Src { |