aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/codec/SkPngCodec.cpp38
-rw-r--r--src/codec/SkSwizzler.cpp57
2 files changed, 77 insertions, 18 deletions
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 9f5c8e6906..468b0b8731 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -420,8 +420,12 @@ void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) {
// be created later if we are sampling. We'll go ahead and allocate
// enough memory to swizzle if necessary.
case kSwizzleColor_XformMode: {
- const size_t bpp = (this->getEncodedInfo().bitsPerPixel() > 32) ? 8 : 4;
- const size_t colorXformBytes = dstInfo.width() * bpp;
+ const int bitsPerPixel = this->getEncodedInfo().bitsPerPixel();
+
+ // If we have more than 8-bits (per component) of precision, we will keep that
+ // extra precision. Otherwise, we will swizzle to RGBA_8888 before transforming.
+ const size_t bytesPerPixel = (bitsPerPixel > 32) ? bitsPerPixel / 8 : 4;
+ const size_t colorXformBytes = dstInfo.width() * bytesPerPixel;
fStorage.reset(colorXformBytes);
fColorXformSrcRow = fStorage.get();
break;
@@ -430,10 +434,13 @@ void SkPngCodec::allocateStorage(const SkImageInfo& dstInfo) {
}
static SkColorSpaceXform::ColorFormat png_select_xform_format(const SkEncodedInfo& info) {
- // We always use kRGBA because color PNGs are always RGB or RGBA.
- // TODO (msarett): Support kRGB_U16 inputs as well.
- if (16 == info.bitsPerComponent() && SkEncodedInfo::kRGBA_Color == info.color()) {
- return SkColorSpaceXform::kRGBA_U16_BE_ColorFormat;
+ // We use kRGB and kRGBA formats because color PNGs are always RGB or RGBA.
+ if (16 == info.bitsPerComponent()) {
+ if (SkEncodedInfo::kRGBA_Color == info.color()) {
+ return SkColorSpaceXform::kRGBA_U16_BE_ColorFormat;
+ } else if (SkEncodedInfo::kRGB_Color == info.color()) {
+ return SkColorSpaceXform::kRGB_U16_BE_ColorFormat;
+ }
}
return SkColorSpaceXform::kRGBA_8888_ColorFormat;
@@ -1090,9 +1097,22 @@ bool SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const Options& opt
return false;
}
- // If the image is RGBA and we have a color xform, we can skip the swizzler.
- const bool skipFormatConversion = this->colorXform() &&
- SkEncodedInfo::kRGBA_Color == this->getEncodedInfo().color();
+ // If SkColorSpaceXform directly supports the encoded PNG format, we should skip format
+ // conversion in the swizzler (or skip swizzling altogether).
+ bool skipFormatConversion = false;
+ switch (this->getEncodedInfo().color()) {
+ case SkEncodedInfo::kRGB_Color:
+ if (this->getEncodedInfo().bitsPerComponent() != 16) {
+ break;
+ }
+
+ // Fall through
+ case SkEncodedInfo::kRGBA_Color:
+ skipFormatConversion = this->colorXform();
+ break;
+ default:
+ break;
+ }
if (skipFormatConversion && !options.fSubset) {
fXformMode = kColorOnly_XformMode;
return true;
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index 21c999403e..31fc063aec 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -51,6 +51,17 @@ static void sample4(void* dst, const uint8_t* src, int width, int bpp, int delta
}
}
+static void sample6(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
+ const SkPMColor ctable[]) {
+ src += offset;
+ uint8_t* dst8 = (uint8_t*) dst;
+ for (int x = 0; x < width; x++) {
+ memcpy(dst8, src, 6);
+ dst8 += 6;
+ src += deltaSrc;
+ }
+}
+
static void sample8(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
const SkPMColor ctable[]) {
src += offset;
@@ -809,21 +820,42 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
int srcBPP;
const int dstBPP = SkColorTypeBytesPerPixel(dstInfo.colorType());
if (skipFormatConversion) {
- srcBPP = dstBPP;
- switch (dstInfo.colorType()) {
- case kGray_8_SkColorType:
- proc = &sample1;
- fastProc = &copy;
+ switch (encodedInfo.color()) {
+ case SkEncodedInfo::kGray_Color:
+ case SkEncodedInfo::kYUV_Color:
+ // We have a jpeg that has already been converted to the dstColorType.
+ srcBPP = dstBPP;
+ switch (dstInfo.colorType()) {
+ case kGray_8_SkColorType:
+ proc = &sample1;
+ fastProc = &copy;
+ break;
+ case kRGB_565_SkColorType:
+ proc = &sample2;
+ fastProc = &copy;
+ break;
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
+ proc = &sample4;
+ fastProc = &copy;
+ break;
+ default:
+ return nullptr;
+ }
break;
- case kRGB_565_SkColorType:
- proc = &sample2;
+ case SkEncodedInfo::kInvertedCMYK_Color:
+ case SkEncodedInfo::kYCCK_Color:
+ // We have a jpeg that remains in its original format.
+ srcBPP = 4;
+ proc = &sample4;
fastProc = &copy;
break;
- case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType:
+ case SkEncodedInfo::kRGBA_Color:
+ // We have a png that should remain in its original format.
SkASSERT(16 == encodedInfo.bitsPerComponent() ||
8 == encodedInfo.bitsPerComponent());
if (8 == encodedInfo.bitsPerComponent()) {
+ srcBPP = 4;
proc = &sample4;
} else {
srcBPP = 8;
@@ -831,6 +863,13 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
}
fastProc = &copy;
break;
+ case SkEncodedInfo::kRGB_Color:
+ // We have a png that remains in its original format.
+ SkASSERT(16 == encodedInfo.bitsPerComponent());
+ srcBPP = 6;
+ proc = &sample6;
+ fastProc = &copy;
+ break;
default:
return nullptr;
}