Chromium Code Reviews| 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 if (SkCodec::kSuccess != r) { | |
| 989 return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_st r(), r); | |
| 965 } | 990 } |
| 966 | 991 |
| 967 switch (fMode) { | 992 switch (fMode) { |
| 968 case kBaseline_Mode: | 993 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); | 994 canvas->drawBitmap(bitmap, 0, 0); |
| 977 break; | 995 break; |
| 996 case kSrcToLinear_Mode: { | |
| 997 sk_sp<SkColorSpace> srcSpace = sk_ref_sp(codec->getColorSpace()); | |
|
scroggo
2016/05/05 20:57:26
Should we update the API to return a const sk_sp<S
msarett
2016/05/05 21:34:26
We *should* do that. We actually can't because Sk
| |
| 998 if (!srcSpace) { | |
| 999 return SkStringPrintf("Cannot test color correction without a sr c profile."); | |
| 1000 } | |
| 1001 | |
| 1002 SkAutoTDelete<SkColorSpaceXform> xform(SkColorSpaceXform::New(srcSpa ce, nullptr, | |
| 1003 SkColorSpaceXform::kSrcToLinear_Op)); | |
| 1004 if (!xform) { | |
| 1005 return Error::Nonfatal("Xform is not implemented yet."); | |
|
scroggo
2016/05/05 20:57:26
Alternatively, should we only upload an image for
msarett
2016/05/05 21:34:26
I believe that's how it works now.
The only image
scroggo
2016/05/06 13:50:00
In that case, shouldn't this be a fatal error?
| |
| 1006 } | |
| 1007 | |
| 1008 // Create a F16 destination buffer for the output of color conversio n. | |
| 1009 size_t rowBytes = width * SkColorTypeBytesPerPixel(kRGBA_F16_SkColor Type); | |
| 1010 SkAutoMalloc pixels(rowBytes * height); | |
| 1011 | |
| 1012 // Apply the conversion to linear F16 pixels. | |
| 1013 SkISize size = SkISize::Make(width, height); | |
| 1014 xform->apply(pixels.get(), bitmap.getPixels(), size, rowBytes, bitma p.rowBytes()); | |
| 1015 | |
| 1016 // Converting to a linear color space is useful because most post-de code operations | |
| 1017 // assume linear pixels (ex: scaling, premultiplying, etc). However , we will want | |
| 1018 // to be in a non-linear dst color space when we write the pixels to the screen. | |
|
scroggo
2016/05/05 20:57:26
It's strange that we are talking about writing to
msarett
2016/05/05 21:34:26
Agreed I'll go back and explain this further...
W
| |
| 1019 // In order to test, we will assume that the dst wants sRGB pixels a nd convert the | |
| 1020 // linear intermediate to sRGB. This will make the output images lo ok normal (or | |
| 1021 // prettier than normal) if there are no bugs in our conversions. | |
| 1022 uint64_t* rowPtr = (uint64_t*) pixels.get(); | |
| 1023 for (uint32_t y = 0; y < height; y++) { | |
| 1024 for (uint32_t x = 0; x < width; x++) { | |
| 1025 // Extract floats. | |
| 1026 uint64_t pixel = rowPtr[x]; | |
| 1027 float linearR = SkHalfToFloat((pixel >> 0) & 0xFFFF); | |
| 1028 float linearG = SkHalfToFloat((pixel >> 16) & 0xFFFF); | |
| 1029 float linearB = SkHalfToFloat((pixel >> 32) & 0xFFFF); | |
| 1030 float linearA = SkHalfToFloat((pixel >> 48) & 0xFFFF); | |
| 1031 | |
| 1032 // Currently we only support decodes to F16 when the encoded image has | |
| 1033 // a color space. | |
| 1034 SkColorSpace* colorSpace = codec->getColorSpace(); | |
| 1035 SkASSERT(colorSpace); | |
| 1036 | |
| 1037 // Convert to XYZ gamut. | |
| 1038 const SkMatrix44& toXYZ = colorSpace->xyz(); | |
| 1039 float xyzR = linearR*toXYZ.getFloat(0, 0) + linearG*toXYZ.ge tFloat(1, 0) + | |
| 1040 linearB*toXYZ.getFloat(2, 0) + toXYZ.getFloat(3 , 0); | |
| 1041 float xyzG = linearR*toXYZ.getFloat(0, 1) + linearG*toXYZ.ge tFloat(1, 1) + | |
| 1042 linearB*toXYZ.getFloat(2, 1) + toXYZ.getFloat(3 , 1); | |
| 1043 float xyzB = linearR*toXYZ.getFloat(0, 2) + linearG*toXYZ.ge tFloat(1, 2) + | |
| 1044 linearB*toXYZ.getFloat(2, 2) + toXYZ.getFloat(3 , 2); | |
| 1045 | |
| 1046 // Convert to sRGB gamut, using inverse sRGB matrix. | |
| 1047 float dstR = xyzR*3.13651f + xyzG*-1.61902f + xyzB*-0.490837 f; | |
| 1048 float dstG = xyzR*-0.978981f + xyzG*1.91625f + xyzB*0.033434 9f; | |
| 1049 float dstB = xyzR*0.072085f + xyzG*-0.229113f + xyzB*1.40577 f; | |
| 1050 | |
| 1051 // Convert to sRGB gamma. | |
| 1052 float curveR = pow(dstR, 1.0f/2.2f); | |
| 1053 float curveG = pow(dstG, 1.0f/2.2f); | |
| 1054 float curveB = pow(dstB, 1.0f/2.2f); | |
| 1055 | |
| 1056 uint32_t* ptr = (uint32_t*) bitmap.getAddr(x, y); | |
| 1057 *ptr = SkPackARGB32NoCheck(clampFloatToByte(linearA), | |
| 1058 clampFloatToByte(curveR), | |
| 1059 clampFloatToByte(curveG), | |
| 1060 clampFloatToByte(curveB)); | |
| 1061 } | |
| 1062 | |
| 1063 rowPtr = SkTAddOffset<uint64_t>(rowPtr, rowBytes); | |
| 1064 } | |
| 1065 | |
| 1066 canvas->drawBitmap(bitmap, 0, 0); | |
| 1067 break; | |
| 1068 } | |
| 978 default: | 1069 default: |
| 979 SkASSERT(false); | 1070 SkASSERT(false); |
| 980 return "Invalid fMode"; | 1071 return "Invalid fMode"; |
| 981 } | 1072 } |
| 982 return ""; | 1073 return ""; |
| 983 } | 1074 } |
| 984 | 1075 |
| 985 SkISize ColorCodecSrc::size() const { | 1076 SkISize ColorCodecSrc::size() const { |
| 986 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 1077 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
| 987 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); | 1078 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1563 skr.visit(i, drawsAsSingletonPictures); | 1654 skr.visit(i, drawsAsSingletonPictures); |
| 1564 } | 1655 } |
| 1565 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture()); | 1656 sk_sp<SkPicture> macroPic(macroRec.finishRecordingAsPicture()); |
| 1566 | 1657 |
| 1567 canvas->drawPicture(macroPic); | 1658 canvas->drawPicture(macroPic); |
| 1568 return check_against_reference(bitmap, src, fSink); | 1659 return check_against_reference(bitmap, src, fSink); |
| 1569 }); | 1660 }); |
| 1570 } | 1661 } |
| 1571 | 1662 |
| 1572 } // namespace DM | 1663 } // namespace DM |
| OLD | NEW |