Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Side by Side Diff: dm/DMSrcSink.cpp

Issue 1952063002: Create SkColorSpaceXform to handle color conversions (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add private API to allow test code to access ICC data Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "DMSrcSink.h" 8 #include "DMSrcSink.h"
9 #include "Resources.h"
9 #include "SkAndroidCodec.h" 10 #include "SkAndroidCodec.h"
10 #include "SkCodec.h" 11 #include "SkCodec.h"
11 #include "SkCodecImageGenerator.h" 12 #include "SkCodecImageGenerator.h"
12 #include "SkColorSpace.h" 13 #include "SkColorSpace.h"
13 #include "SkColorSpace_Base.h" 14 #include "SkColorSpace_Base.h"
15 #include "SkColorSpaceXform.h"
14 #include "SkCommonFlags.h" 16 #include "SkCommonFlags.h"
15 #include "SkData.h" 17 #include "SkData.h"
16 #include "SkDocument.h" 18 #include "SkDocument.h"
17 #include "SkError.h" 19 #include "SkError.h"
18 #include "SkImageGenerator.h" 20 #include "SkImageGenerator.h"
19 #include "SkImageGeneratorCG.h" 21 #include "SkImageGeneratorCG.h"
20 #include "SkImageGeneratorWIC.h" 22 #include "SkImageGeneratorWIC.h"
21 #include "SkMallocPixelRef.h" 23 #include "SkMallocPixelRef.h"
22 #include "SkMultiPictureDraw.h" 24 #include "SkMultiPictureDraw.h"
23 #include "SkNullCanvas.h" 25 #include "SkNullCanvas.h"
24 #include "SkOSFile.h" 26 #include "SkOSFile.h"
25 #include "SkOpts.h" 27 #include "SkOpts.h"
26 #include "SkPictureData.h" 28 #include "SkPictureData.h"
27 #include "SkPictureRecorder.h" 29 #include "SkPictureRecorder.h"
28 #include "SkRandom.h" 30 #include "SkRandom.h"
29 #include "SkRecordDraw.h" 31 #include "SkRecordDraw.h"
30 #include "SkRecorder.h" 32 #include "SkRecorder.h"
31 #include "SkSVGCanvas.h" 33 #include "SkSVGCanvas.h"
32 #include "SkStream.h" 34 #include "SkStream.h"
33 #include "SkTLogic.h" 35 #include "SkTLogic.h"
34 #include "SkXMLWriter.h" 36 #include "SkXMLWriter.h"
35 #include "SkSwizzler.h" 37 #include "SkSwizzler.h"
36 #include <functional> 38 #include <functional>
37 39
38 #if defined(SK_BUILD_FOR_WIN) 40 #if defined(SK_BUILD_FOR_WIN)
39 #include "SkAutoCoInitialize.h" 41 #include "SkAutoCoInitialize.h"
40 #endif 42 #endif
41 43
44 #include "qcms.h"
45
42 DEFINE_bool(multiPage, false, "For document-type backends, render the source" 46 DEFINE_bool(multiPage, false, "For document-type backends, render the source"
43 " into multiple pages"); 47 " into multiple pages");
44 DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?" ); 48 DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?" );
45 49
46 using sk_gpu_test::GrContextFactory; 50 using sk_gpu_test::GrContextFactory;
47 51
48 namespace DM { 52 namespace DM {
49 53
50 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {} 54 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
51 55
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 } 824 }
821 return codec->getInfo().dimensions(); 825 return codec->getInfo().dimensions();
822 } 826 }
823 827
824 Name ImageGenSrc::name() const { 828 Name ImageGenSrc::name() const {
825 return SkOSPath::Basename(fPath.c_str()); 829 return SkOSPath::Basename(fPath.c_str());
826 } 830 }
827 831
828 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ 832 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
829 833
830 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, sk_sp<SkColorSpace> dstSpace) 834 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode)
831 : fPath(path) 835 : fPath(path)
832 , fMode(mode) 836 , fMode(mode)
833 , fDstSpace(dstSpace)
834 {} 837 {}
835 838
836 bool ColorCodecSrc::veto(SinkFlags flags) const { 839 bool ColorCodecSrc::veto(SinkFlags flags) const {
837 // Test to direct raster backends (8888 and 565). 840 // Test to direct raster backends (8888 and 565).
838 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect; 841 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect;
839 } 842 }
840 843
841 static uint8_t clampFloatToByte(float v) {
842 v = v * 255.0f;
843 if (v > 255.0f) {
844 return 255;
845 } else if (v < 0.0f) {
846 return 0;
847 } else {
848 return (uint8_t) (v + 0.5f);
849 }
850 }
851
852 Error ColorCodecSrc::draw(SkCanvas* canvas) const { 844 Error ColorCodecSrc::draw(SkCanvas* canvas) const {
853 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) { 845 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
854 return Error::Nonfatal("No need to test color correction to 565 backend. "); 846 return Error::Nonfatal("No need to test color correction to 565 backend. ");
855 } 847 }
856 848
857 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 849 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
858 if (!encoded) { 850 if (!encoded) {
859 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 851 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
860 } 852 }
861 853
(...skipping 12 matching lines...) Expand all
874 SkImageInfo decodeInfo = info; 866 SkImageInfo decodeInfo = info;
875 if (kBaseline_Mode != fMode) { 867 if (kBaseline_Mode != fMode) {
876 decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType); 868 decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
877 } 869 }
878 870
879 SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap. rowBytes()); 871 SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap. rowBytes());
880 if (SkCodec::kSuccess != r) { 872 if (SkCodec::kSuccess != r) {
881 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_st r(), r); 873 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_st r(), r);
882 } 874 }
883 875
876 // Load the dst ICC profile. This particular dst is fairly similar to Adobe RGB.
877 sk_sp<SkData> dstData = SkData::MakeFromFileName(
878 GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
879
884 switch (fMode) { 880 switch (fMode) {
885 case kBaseline_Mode: 881 case kBaseline_Mode:
886 canvas->drawBitmap(bitmap, 0, 0); 882 canvas->drawBitmap(bitmap, 0, 0);
887 break; 883 break;
888 case kDst_HPZR30w_Mode: { 884 case kDst_HPZR30w_Mode: {
889 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace()); 885 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace());
890 if (!srcSpace) { 886 sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size());
scroggo 2016/05/31 21:13:34 Should we fail gracefully if dstData is null?
msarett 2016/05/31 22:02:19 Yes I think so. Let's fail, but not crash, if the
891 return SkStringPrintf("Cannot test color correction without a sr c profile."); 887 SkASSERT(dstSpace);
892 } else if (!as_CSB(srcSpace)->gammas()->isValues()) { 888
889 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(sr cSpace, dstSpace);
890 if (!xform) {
893 // FIXME (msarett): 891 // FIXME (msarett):
894 // The conversion here doesn't cover all of the images that I've uploaded for 892 // I haven't implemented conversions for all of the images that I've uploaded for
895 // testing. Once we support all of them, this should be a fatal error. 893 // testing. Once we support all of them, this should be a fatal error.
896 return Error::Nonfatal("Unimplemented gamma conversion."); 894 return Error::Nonfatal("Unimplemented color conversion.");
897 } 895 }
898 896
899 // Build a matrix to transform to dst gamut. 897 uint32_t* row = (uint32_t*) bitmap.getPixels();
900 // srcToDst = inverse(dstToXYZ) * srcToXYZ
901 const SkMatrix44& srcToXYZ = srcSpace->xyz();
902 const SkMatrix44& dstToXYZ = fDstSpace->xyz();
903 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
904 dstToXYZ.invert(&srcToDst);
905 srcToDst.postConcat(srcToXYZ);
906
907 for (int y = 0; y < info.height(); y++) { 898 for (int y = 0; y < info.height(); y++) {
908 for (int x = 0; x < info.width(); x++) { 899 xform->xform_RGBA_8888(row, row, info.width());
909 // Extract floats. 900 row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
910 uint32_t* pixelPtr = (uint32_t*) bitmap.getAddr(x, y);
911 float src[3];
912 src[0] = ((*pixelPtr >> 0) & 0xFF) / 255.0f;
913 src[1] = ((*pixelPtr >> 8) & 0xFF) / 255.0f;
914 src[2] = ((*pixelPtr >> 16) & 0xFF) / 255.0f;
915
916 // Convert to linear.
917 src[0] = pow(src[0], as_CSB(srcSpace)->gammas()->fRed.fValue );
918 src[1] = pow(src[1], as_CSB(srcSpace)->gammas()->fGreen.fVal ue);
919 src[2] = pow(src[2], as_CSB(srcSpace)->gammas()->fBlue.fValu e);
920
921 // Convert to dst gamut.
922 float dst[3];
923 dst[0] = src[0]*srcToDst.getFloat(0, 0) + src[1]*srcToDst.ge tFloat(1, 0) +
924 src[2]*srcToDst.getFloat(2, 0) + srcToDst.getFloat( 3, 0);
925 dst[1] = src[0]*srcToDst.getFloat(0, 1) + src[1]*srcToDst.ge tFloat(1, 1) +
926 src[2]*srcToDst.getFloat(2, 1) + srcToDst.getFloat( 3, 1);
927 dst[2] = src[0]*srcToDst.getFloat(0, 2) + src[1]*srcToDst.ge tFloat(1, 2) +
928 src[2]*srcToDst.getFloat(2, 2) + srcToDst.getFloat( 3, 2);
929
930 // Convert to dst gamma.
931 dst[0] = pow(dst[0], 1.0f / as_CSB(fDstSpace)->gammas()->fRe d.fValue);
932 dst[1] = pow(dst[1], 1.0f / as_CSB(fDstSpace)->gammas()->fGr een.fValue);
933 dst[2] = pow(dst[2], 1.0f / as_CSB(fDstSpace)->gammas()->fBl ue.fValue);
934
935 *pixelPtr = SkPackARGB32NoCheck(((*pixelPtr >> 24) & 0xFF),
936 clampFloatToByte(dst[0]),
937 clampFloatToByte(dst[1]),
938 clampFloatToByte(dst[2]));
939 }
940 } 901 }
941 902
942 canvas->drawBitmap(bitmap, 0, 0); 903 canvas->drawBitmap(bitmap, 0, 0);
943 break; 904 break;
944 } 905 }
906 case kQCMS_HPZR30w_Mode: {
907 sk_sp<SkData> srcData = codec->getICCData();
908 qcms_profile* srcSpace = qcms_profile_from_memory(srcData->data(), s rcData->size());
909 if (!srcSpace) {
910 return Error::Nonfatal(SkStringPrintf("QCMS cannot create profil e for %s.\n",
911 fPath.c_str()));
912 }
913
914 qcms_profile* dstSpace = qcms_profile_from_memory(dstData->data(), d stData->size());
915 SkASSERT(dstSpace);
916 qcms_transform* transform = qcms_transform_create(srcSpace, QCMS_DAT A_RGBA_8, dstSpace,
917 QCMS_DATA_RGBA_8,
918 QCMS_INTENT_PERCEP TUAL);
919 if (!transform) {
920 qcms_profile_release(srcSpace);
scroggo 2016/05/31 21:13:34 Can you put these in an auto deleter?
msarett 2016/05/31 22:02:19 Done.
921 qcms_profile_release(dstSpace);
922 return SkStringPrintf("QCMS cannot create transform for %s.\n", fPath.c_str());
923 }
924
925 #ifdef SK_PMCOLOR_IS_RGBA
926 qcms_output_type outType = QCMS_OUTPUT_RGBX;
927 #else
928 qcms_output_type outType = QCMS_OUTPUT_BGRX;
929 #endif
930
931 // Perform color correction.
932 uint32_t* row = (uint32_t*) bitmap.getPixels();
933 for (int y = 0; y < info.height(); y++) {
934 qcms_transform_data_type(transform, row, row, info.width(), outT ype);
935 row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
936 }
937
938 qcms_profile_release(srcSpace);
939 qcms_profile_release(dstSpace);
940 qcms_transform_release(transform);
941 canvas->drawBitmap(bitmap, 0, 0);
942 break;
943 }
945 default: 944 default:
946 SkASSERT(false); 945 SkASSERT(false);
947 return "Invalid fMode"; 946 return "Invalid fMode";
948 } 947 }
949 return ""; 948 return "";
950 } 949 }
951 950
952 SkISize ColorCodecSrc::size() const { 951 SkISize ColorCodecSrc::size() const {
953 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 952 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
954 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 953 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 skr.visit(i, drawsAsSingletonPictures); 1529 skr.visit(i, drawsAsSingletonPictures);
1531 } 1530 }
1532 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture()); 1531 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture());
1533 1532
1534 canvas->drawPicture(macroPic); 1533 canvas->drawPicture(macroPic);
1535 return check_against_reference(bitmap, src, fSink); 1534 return check_against_reference(bitmap, src, fSink);
1536 }); 1535 });
1537 } 1536 }
1538 1537
1539 } // namespace DM 1538 } // namespace DM
OLDNEW
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/core.gypi » ('j') | include/codec/SkCodec.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698