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

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: Rebase 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
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/core.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #if !defined(GOOGLE3)
45 #include "qcms.h"
46 #endif
47
42 DEFINE_bool(multiPage, false, "For document-type backends, render the source" 48 DEFINE_bool(multiPage, false, "For document-type backends, render the source"
43 " into multiple pages"); 49 " into multiple pages");
44 DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?" ); 50 DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?" );
45 51
46 using sk_gpu_test::GrContextFactory; 52 using sk_gpu_test::GrContextFactory;
47 53
48 namespace DM { 54 namespace DM {
49 55
50 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {} 56 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
51 57
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 } 826 }
821 return codec->getInfo().dimensions(); 827 return codec->getInfo().dimensions();
822 } 828 }
823 829
824 Name ImageGenSrc::name() const { 830 Name ImageGenSrc::name() const {
825 return SkOSPath::Basename(fPath.c_str()); 831 return SkOSPath::Basename(fPath.c_str());
826 } 832 }
827 833
828 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ 834 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
829 835
830 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode, sk_sp<SkColorSpace> dstSpace) 836 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode)
831 : fPath(path) 837 : fPath(path)
832 , fMode(mode) 838 , fMode(mode)
833 , fDstSpace(dstSpace)
834 {} 839 {}
835 840
836 bool ColorCodecSrc::veto(SinkFlags flags) const { 841 bool ColorCodecSrc::veto(SinkFlags flags) const {
837 // Test to direct raster backends (8888 and 565). 842 // Test to direct raster backends (8888 and 565).
838 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect; 843 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect;
839 } 844 }
840 845
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 { 846 Error ColorCodecSrc::draw(SkCanvas* canvas) const {
853 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) { 847 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
854 return Error::Nonfatal("No need to test color correction to 565 backend. "); 848 return Error::Nonfatal("No need to test color correction to 565 backend. ");
855 } 849 }
856 850
857 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 851 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
858 if (!encoded) { 852 if (!encoded) {
859 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 853 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
860 } 854 }
861 855
(...skipping 12 matching lines...) Expand all
874 SkImageInfo decodeInfo = info; 868 SkImageInfo decodeInfo = info;
875 if (kBaseline_Mode != fMode) { 869 if (kBaseline_Mode != fMode) {
876 decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType); 870 decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
877 } 871 }
878 872
879 SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap. rowBytes()); 873 SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap. rowBytes());
880 if (SkCodec::kSuccess != r) { 874 if (SkCodec::kSuccess != r) {
881 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_st r(), r); 875 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_st r(), r);
882 } 876 }
883 877
878 // Load the dst ICC profile. This particular dst is fairly similar to Adobe RGB.
879 sk_sp<SkData> dstData = SkData::MakeFromFileName(
880 GetResourcePath("monitor_profiles/HP_ZR30w.icc").c_str());
881 if (!dstData) {
882 return "Cannot read monitor profile. Is the resource path set correctly ?";
883 }
884
884 switch (fMode) { 885 switch (fMode) {
885 case kBaseline_Mode: 886 case kBaseline_Mode:
886 canvas->drawBitmap(bitmap, 0, 0); 887 canvas->drawBitmap(bitmap, 0, 0);
887 break; 888 break;
888 case kDst_HPZR30w_Mode: { 889 case kDst_HPZR30w_Mode: {
889 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace()); 890 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace());
890 if (!srcSpace) { 891 sk_sp<SkColorSpace> dstSpace = SkColorSpace::NewICC(dstData->data(), dstData->size());
891 return SkStringPrintf("Cannot test color correction without a sr c profile."); 892 SkASSERT(dstSpace);
892 } else if (!as_CSB(srcSpace)->gammas()->isValues()) { 893
894 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(sr cSpace, dstSpace);
895 if (!xform) {
893 // FIXME (msarett): 896 // FIXME (msarett):
894 // The conversion here doesn't cover all of the images that I've uploaded for 897 // 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. 898 // testing. Once we support all of them, this should be a fatal error.
896 return Error::Nonfatal("Unimplemented gamma conversion."); 899 return Error::Nonfatal("Unimplemented color conversion.");
897 } 900 }
898 901
899 // Build a matrix to transform to dst gamut. 902 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++) { 903 for (int y = 0; y < info.height(); y++) {
908 for (int x = 0; x < info.width(); x++) { 904 xform->xform_RGBA_8888(row, row, info.width());
909 // Extract floats. 905 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 } 906 }
941 907
942 canvas->drawBitmap(bitmap, 0, 0); 908 canvas->drawBitmap(bitmap, 0, 0);
943 break; 909 break;
944 } 910 }
911 #if !defined(GOOGLE3)
912 case kQCMS_HPZR30w_Mode: {
913 sk_sp<SkData> srcData = codec->getICCData();
914 SkAutoTCallVProc<qcms_profile, qcms_profile_release>
915 srcSpace(qcms_profile_from_memory(srcData->data(), srcData-> size()));
916 if (!srcSpace) {
917 return Error::Nonfatal(SkStringPrintf("QCMS cannot create profil e for %s.\n",
918 fPath.c_str()));
919 }
920
921 SkAutoTCallVProc<qcms_profile, qcms_profile_release>
922 dstSpace(qcms_profile_from_memory(dstData->data(), dstData-> size()));
923 SkASSERT(dstSpace);
924 SkAutoTCallVProc<qcms_transform, qcms_transform_release>
925 transform (qcms_transform_create(srcSpace, QCMS_DATA_RGBA_8, dstSpace,
926 QCMS_DATA_RGBA_8, QCMS_INTE NT_PERCEPTUAL));
927 if (!transform) {
928 return SkStringPrintf("QCMS cannot create transform for %s.\n", fPath.c_str());
929 }
930
931 #ifdef SK_PMCOLOR_IS_RGBA
932 qcms_output_type outType = QCMS_OUTPUT_RGBX;
933 #else
934 qcms_output_type outType = QCMS_OUTPUT_BGRX;
935 #endif
936
937 // Perform color correction.
938 uint32_t* row = (uint32_t*) bitmap.getPixels();
939 for (int y = 0; y < info.height(); y++) {
940 qcms_transform_data_type(transform, row, row, info.width(), outT ype);
941 row = SkTAddOffset<uint32_t>(row, bitmap.rowBytes());
942 }
943
944 canvas->drawBitmap(bitmap, 0, 0);
945 break;
946 }
947 #endif
945 default: 948 default:
946 SkASSERT(false); 949 SkASSERT(false);
947 return "Invalid fMode"; 950 return "Invalid fMode";
948 } 951 }
949 return ""; 952 return "";
950 } 953 }
951 954
952 SkISize ColorCodecSrc::size() const { 955 SkISize ColorCodecSrc::size() const {
953 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 956 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
954 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 957 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 skr.visit(i, drawsAsSingletonPictures); 1533 skr.visit(i, drawsAsSingletonPictures);
1531 } 1534 }
1532 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture()); 1535 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture());
1533 1536
1534 canvas->drawPicture(macroPic); 1537 canvas->drawPicture(macroPic);
1535 return check_against_reference(bitmap, src, fSink); 1538 return check_against_reference(bitmap, src, fSink);
1536 }); 1539 });
1537 } 1540 }
1538 1541
1539 } // namespace DM 1542 } // namespace DM
OLDNEW
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/core.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698