OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |