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

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: Comments Created 4 years, 7 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 "SkAndroidCodec.h" 9 #include "SkAndroidCodec.h"
10 #include "SkCodec.h" 10 #include "SkCodec.h"
11 #include "SkCodecImageGenerator.h" 11 #include "SkCodecImageGenerator.h"
12 #include "SkColorSpaceXform.h"
12 #include "SkCommonFlags.h" 13 #include "SkCommonFlags.h"
13 #include "SkData.h" 14 #include "SkData.h"
14 #include "SkDocument.h" 15 #include "SkDocument.h"
15 #include "SkError.h" 16 #include "SkError.h"
17 #include "SkHalf.h"
16 #include "SkImageGenerator.h" 18 #include "SkImageGenerator.h"
17 #include "SkImageGeneratorCG.h" 19 #include "SkImageGeneratorCG.h"
18 #include "SkImageGeneratorWIC.h" 20 #include "SkImageGeneratorWIC.h"
19 #include "SkMallocPixelRef.h" 21 #include "SkMallocPixelRef.h"
20 #include "SkMultiPictureDraw.h" 22 #include "SkMultiPictureDraw.h"
21 #include "SkNullCanvas.h" 23 #include "SkNullCanvas.h"
22 #include "SkOSFile.h" 24 #include "SkOSFile.h"
23 #include "SkOpts.h" 25 #include "SkOpts.h"
24 #include "SkPictureData.h" 26 #include "SkPictureData.h"
25 #include "SkPictureRecorder.h" 27 #include "SkPictureRecorder.h"
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode) 937 ColorCodecSrc::ColorCodecSrc(Path path, Mode mode)
936 : fPath(path) 938 : fPath(path)
937 , fMode(mode) 939 , fMode(mode)
938 {} 940 {}
939 941
940 bool ColorCodecSrc::veto(SinkFlags flags) const { 942 bool ColorCodecSrc::veto(SinkFlags flags) const {
941 // Test to direct raster backends (8888 and 565). 943 // Test to direct raster backends (8888 and 565).
942 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect; 944 return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDir ect;
943 } 945 }
944 946
947 static uint8_t clampFloatToByte(float v) {
948 v = v * 255.0f;
949 if (v > 255.0f) {
950 return 255;
951 } else if (v < 0.0f) {
952 return 0;
953 } else {
954 return (uint8_t) (v + 0.5f);
955 }
956 }
957
945 Error ColorCodecSrc::draw(SkCanvas* canvas) const { 958 Error ColorCodecSrc::draw(SkCanvas* canvas) const {
946 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) { 959 if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
947 return Error::Nonfatal("No need to test color correction to 565 backend. "); 960 return Error::Nonfatal("No need to test color correction to 565 backend. ");
948 } 961 }
949 962
950 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 963 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
951 if (!encoded) { 964 if (!encoded) {
952 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 965 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
953 } 966 }
954 967
955 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 968 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
956 if (nullptr == codec.get()) { 969 if (nullptr == codec.get()) {
957 return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); 970 return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
958 } 971 }
959 972
960 SkImageInfo decodeInfo = codec->getInfo().makeColorType(kN32_SkColorType); 973 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
974 uint32_t width = info.width();
975 uint32_t height = info.height();
961 SkBitmap bitmap; 976 SkBitmap bitmap;
962 if (!bitmap.tryAllocPixels(decodeInfo)) { 977 if (!bitmap.tryAllocPixels(info)) {
963 return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(), 978 return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
964 decodeInfo.width(), decodeInfo.height()); 979 info.width(), info.height());
980 }
981
982 SkImageInfo decodeInfo = info;
983 if (kBaseline_Mode != fMode) {
984 decodeInfo = decodeInfo.makeColorType(kRGBA_8888_SkColorType);
985 }
986
987 SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap. rowBytes());
988 switch (r) {
herb_g 2016/05/05 14:44:50 Should be an if statement.
msarett 2016/05/05 15:49:05 Yes! SGTM :)
989 case SkCodec::kSuccess:
990 break;
991 default:
992 // Everything else is considered a failure.
993 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath. c_str(), r);
965 } 994 }
966 995
967 switch (fMode) { 996 switch (fMode) {
968 case kBaseline_Mode: 997 case kBaseline_Mode:
969 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowB ytes())) {
970 case SkCodec::kSuccess:
971 break;
972 default:
973 // Everything else is considered a failure.
974 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str( ));
975 }
976 canvas->drawBitmap(bitmap, 0, 0); 998 canvas->drawBitmap(bitmap, 0, 0);
977 break; 999 break;
1000 case kSrcToLinear_Mode: {
1001 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace());
1002 if (!srcSpace) {
1003 return SkStringPrintf("Cannot test color correction without a sr c profile.");
1004 }
1005
1006 SkAutoTDelete<SkColorSpaceXform> xform(SkColorSpaceXform::New(srcSpa ce, nullptr,
1007 SkColorSpaceXform::kSrcToLinear_Op));
1008 if (!xform) {
1009 return Error::Nonfatal("Xform is not implemented yet.");
1010 }
1011
1012 // Create a F16 destination buffer for the output of color conversio n.
1013 size_t rowBytes = width * SkColorTypeBytesPerPixel(kRGBA_F16_SkColor Type);
1014 SkAutoMalloc pixels(rowBytes * height);
1015
1016 // Apply the conversion to linear F16 pixels.
1017 SkISize size = SkISize::Make(width, height);
1018 xform->apply(pixels.get(), bitmap.getPixels(), size, rowBytes, bitma p.rowBytes());
1019
1020 // Converting to a linear color space is useful because most post-de code operations
1021 // assume linear pixels (ex: scaling, premultiplying, etc). However , we will want
1022 // to be in a non-linear dst color space when we write the pixels to the screen.
1023 // In order to test, we will assume that the dst wants sRGB pixels a nd convert the
1024 // linear intermediate to sRGB. This will make the output images lo ok normal (or
1025 // prettier than normal) if there are no bugs in our conversions.
Brian Osman 2016/05/05 13:29:44 Thanks for the better comment here. Like Leon, I w
msarett 2016/05/05 15:49:05 Acknowledged.
1026 uint64_t* rowPtr = (uint64_t*) pixels.get();
1027 for (uint32_t y = 0; y < height; y++) {
1028 for (uint32_t x = 0; x < width; x++) {
1029 // Extract floats.
1030 uint64_t pixel = rowPtr[x];
1031 float linearR = SkHalfToFloat((pixel >> 0) & 0xFFFF);
1032 float linearG = SkHalfToFloat((pixel >> 16) & 0xFFFF);
1033 float linearB = SkHalfToFloat((pixel >> 32) & 0xFFFF);
1034 float linearA = SkHalfToFloat((pixel >> 48) & 0xFFFF);
1035
1036 // Currently we only support decodes to F16 when the encoded image has
1037 // a color space.
1038 SkColorSpace* colorSpace = codec->getColorSpace();
1039 SkASSERT(colorSpace);
1040
1041 // Convert to XYZ gamut.
1042 const SkMatrix44& toXYZ = colorSpace->xyz();
1043 float xyzR = linearR*toXYZ.getFloat(0, 0) + linearG*toXYZ.ge tFloat(1, 0) +
1044 linearB*toXYZ.getFloat(2, 0) + toXYZ.getFloat(3 , 0);
1045 float xyzG = linearR*toXYZ.getFloat(0, 1) + linearG*toXYZ.ge tFloat(1, 1) +
1046 linearB*toXYZ.getFloat(2, 1) + toXYZ.getFloat(3 , 1);
1047 float xyzB = linearR*toXYZ.getFloat(0, 2) + linearG*toXYZ.ge tFloat(1, 2) +
1048 linearB*toXYZ.getFloat(2, 2) + toXYZ.getFloat(3 , 2);
1049
1050 // Convert to sRGB gamut, using inverse sRGB matrix.
1051 float dstR = xyzR*3.13651f + xyzG*-1.61902f + xyzB*-0.490837 f;
1052 float dstG = xyzR*-0.978981f + xyzG*1.91625f + xyzB*0.033434 9f;
1053 float dstB = xyzR*0.072085f + xyzG*-0.229113f + xyzB*1.40577 f;
1054
1055 // Convert to sRGB gamma.
1056 float curveR = pow(dstR, 1.0f/2.2f);
1057 float curveG = pow(dstG, 1.0f/2.2f);
1058 float curveB = pow(dstB, 1.0f/2.2f);
1059
1060 uint32_t* ptr = (uint32_t*) bitmap.getAddr(x, y);
1061 *ptr = SkPackARGB32NoCheck(clampFloatToByte(linearA),
1062 clampFloatToByte(curveR),
1063 clampFloatToByte(curveG),
1064 clampFloatToByte(curveB));
1065 }
1066
1067 rowPtr = SkTAddOffset<uint64_t>(rowPtr, rowBytes);
1068 }
1069
1070 canvas->drawBitmap(bitmap, 0, 0);
1071 break;
1072 }
978 default: 1073 default:
979 SkASSERT(false); 1074 SkASSERT(false);
980 return "Invalid fMode"; 1075 return "Invalid fMode";
981 } 1076 }
982 return ""; 1077 return "";
983 } 1078 }
984 1079
985 SkISize ColorCodecSrc::size() const { 1080 SkISize ColorCodecSrc::size() const {
986 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 1081 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
987 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 1082 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 skr.visit(i, drawsAsSingletonPictures); 1658 skr.visit(i, drawsAsSingletonPictures);
1564 } 1659 }
1565 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture()); 1660 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture());
1566 1661
1567 canvas->drawPicture(macroPic); 1662 canvas->drawPicture(macroPic);
1568 return check_against_reference(bitmap, src, fSink); 1663 return check_against_reference(bitmap, src, fSink);
1569 }); 1664 });
1570 } 1665 }
1571 1666
1572 } // namespace DM 1667 } // namespace DM
OLDNEW
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/core.gypi » ('j') | src/core/SkColorSpaceXform.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698