aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2016-11-07 10:26:17 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-07 16:00:11 +0000
commita225e9be53001a8397344ce1e272a7df2fced499 (patch)
treebb99b48a9cccfa82e4da7dff98ac60fd63c58b45 /src
parent84a812061f1d16aa6d349ca065bf67d06767bbc2 (diff)
Finish color space support for SkCodec
Implements color space xforms and F16 for SkRawCodec and SkWbmpCodec. BUG=skia:4895 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4459 Change-Id: I8c72918e46387350b49a9811ce654d26b1ab352a Reviewed-on: https://skia-review.googlesource.com/4459 Commit-Queue: Matt Sarett <msarett@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/android/SkBitmapRegionCodec.cpp2
-rw-r--r--src/codec/SkCodecPriv.h30
-rw-r--r--src/codec/SkRawCodec.cpp33
-rw-r--r--src/codec/SkSwizzler.cpp33
-rw-r--r--src/codec/SkWbmpCodec.cpp14
5 files changed, 68 insertions, 44 deletions
diff --git a/src/android/SkBitmapRegionCodec.cpp b/src/android/SkBitmapRegionCodec.cpp
index df0a32ca31..7c51fc80d3 100644
--- a/src/android/SkBitmapRegionCodec.cpp
+++ b/src/android/SkBitmapRegionCodec.cpp
@@ -138,5 +138,5 @@ bool SkBitmapRegionCodec::conversionSupported(SkColorType colorType) {
// Enable legacy behavior.
sk_sp<SkColorSpace> colorSpace = nullptr;
SkImageInfo dstInfo = fCodec->getInfo().makeColorType(colorType).makeColorSpace(colorSpace);
- return conversion_possible_ignore_color_space(dstInfo, fCodec->getInfo());
+ return conversion_possible(dstInfo, fCodec->getInfo());
}
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index bf3ab291e2..75fbcf224e 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -109,36 +109,6 @@ static inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) {
}
/*
- * Original version of conversion_possible that does not account for color spaces.
- * Used by codecs that have not been updated to support color spaces.
- *
- * Most of our codecs support the same conversions:
- * - opaque to any alpha type
- * - 565 only if opaque
- * - premul to unpremul and vice versa
- * - always support RGBA, BGRA
- * - otherwise match the src color type
- */
-static inline bool conversion_possible_ignore_color_space(const SkImageInfo& dst,
- const SkImageInfo& src) {
- // Ensure the alpha type is valid
- if (!valid_alpha(dst.alphaType(), src.alphaType())) {
- return false;
- }
-
- // Check for supported color types
- switch (dst.colorType()) {
- case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType:
- return true;
- case kRGB_565_SkColorType:
- return kOpaque_SkAlphaType == src.alphaType();
- default:
- return dst.colorType() == src.colorType();
- }
-}
-
-/*
* If there is a color table, get a pointer to the colors, otherwise return nullptr
*/
static inline const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp
index 26519e6f03..151363239c 100644
--- a/src/codec/SkRawCodec.cpp
+++ b/src/codec/SkRawCodec.cpp
@@ -679,21 +679,28 @@ SkCodec* SkRawCodec::NewFromStream(SkStream* stream) {
return new SkRawCodec(dngImage.release());
}
-SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
+SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
size_t dstRowBytes, const Options& options,
SkPMColor ctable[], int* ctableCount,
int* rowsDecoded) {
- if (!conversion_possible_ignore_color_space(requestedInfo, this->getInfo())) {
+ if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo)) {
SkCodecPrintf("Error: cannot convert input type to output type.\n");
return kInvalidConversion;
}
+ SkImageInfo swizzlerInfo = dstInfo;
+ std::unique_ptr<uint32_t[]> xformBuffer = nullptr;
+ if (this->colorXform()) {
+ swizzlerInfo = swizzlerInfo.makeColorType(kRGBA_8888_SkColorType);
+ xformBuffer.reset(new uint32_t[dstInfo.width()]);
+ }
+
std::unique_ptr<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(
- this->getEncodedInfo(), nullptr, requestedInfo, options));
+ this->getEncodedInfo(), nullptr, swizzlerInfo, options));
SkASSERT(swizzler);
- const int width = requestedInfo.width();
- const int height = requestedInfo.height();
+ const int width = dstInfo.width();
+ const int height = dstInfo.height();
std::unique_ptr<dng_image> image(fDngImage->render(width, height));
if (!image) {
return kInvalidInput;
@@ -731,8 +738,20 @@ SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
return kIncompleteInput;
}
- swizzler->swizzle(dstRow, &srcRow[0]);
- dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ if (this->colorXform()) {
+ swizzler->swizzle(xformBuffer.get(), &srcRow[0]);
+
+ const SkColorSpaceXform::ColorFormat srcFormat =
+ SkColorSpaceXform::kRGBA_8888_ColorFormat;
+ const SkColorSpaceXform::ColorFormat dstFormat =
+ select_xform_format(dstInfo.colorType());
+ this->colorXform()->apply(dstFormat, dstRow, srcFormat, xformBuffer.get(),
+ dstInfo.width(), kOpaque_SkAlphaType);
+ dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ } else {
+ swizzler->swizzle(dstRow, &srcRow[0]);
+ dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ }
}
return kSuccess;
}
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index c9eb923053..0bbe824dc2 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -7,6 +7,7 @@
#include "SkCodecPriv.h"
#include "SkColorPriv.h"
+#include "SkHalf.h"
#include "SkOpts.h"
#include "SkSwizzler.h"
#include "SkTemplates.h"
@@ -150,6 +151,35 @@ static void swizzle_bit_to_565(
#undef RGB565_BLACK
#undef RGB565_WHITE
+static void swizzle_bit_to_f16(
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
+ int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
+ static const uint64_t kWhite = (((uint64_t) SK_Half1) << 0) |
+ (((uint64_t) SK_Half1) << 16) |
+ (((uint64_t) SK_Half1) << 32) |
+ (((uint64_t) SK_Half1) << 48);
+ static const uint64_t kBlack = (((uint64_t) 0) << 0) |
+ (((uint64_t) 0) << 16) |
+ (((uint64_t) 0) << 32) |
+ (((uint64_t) SK_Half1) << 48);
+
+ uint64_t* SK_RESTRICT dst = (uint64_t*) dstRow;
+
+ // increment src by byte offset and bitIndex by bit offset
+ src += offset / 8;
+ int bitIndex = offset % 8;
+ uint8_t currByte = *src;
+
+ dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
+
+ for (int x = 1; x < dstWidth; x++) {
+ int bitOffset = bitIndex + deltaSrc;
+ bitIndex = bitOffset % 8;
+ currByte = *(src += bitOffset / 8);
+ dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
+ }
+}
+
// kIndex1, kIndex2, kIndex4
static void swizzle_small_index_to_index(
@@ -700,6 +730,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(const SkEncodedInfo& encodedInfo,
case kGray_8_SkColorType:
proc = &swizzle_bit_to_grayscale;
break;
+ case kRGBA_F16_SkColorType:
+ proc = &swizzle_bit_to_f16;
+ break;
default:
return nullptr;
}
diff --git a/src/codec/SkWbmpCodec.cpp b/src/codec/SkWbmpCodec.cpp
index 4102bf2607..19c8c7db37 100644
--- a/src/codec/SkWbmpCodec.cpp
+++ b/src/codec/SkWbmpCodec.cpp
@@ -30,14 +30,16 @@ static inline void setup_color_table(SkColorType colorType,
}
}
-static inline bool valid_color_type(SkColorType colorType) {
- switch (colorType) {
+static inline bool valid_color_type(const SkImageInfo& dstInfo) {
+ switch (dstInfo.colorType()) {
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
case kIndex_8_SkColorType:
case kGray_8_SkColorType:
case kRGB_565_SkColorType:
return true;
+ case kRGBA_F16_SkColorType:
+ return dstInfo.colorSpace() && dstInfo.colorSpace()->gammaIsLinear();
default:
return false;
}
@@ -127,8 +129,7 @@ SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info,
return kUnimplemented;
}
- if (!valid_color_type(info.colorType()) ||
- !valid_alpha(info.alphaType(), this->getInfo().alphaType())) {
+ if (!valid_color_type(info) || !valid_alpha(info.alphaType(), this->getInfo().alphaType())) {
return kInvalidConversion;
}
@@ -194,8 +195,9 @@ SkCodec::Result SkWbmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
return kUnimplemented;
}
- if (!valid_color_type(dstInfo.colorType()) ||
- !valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType())) {
+ if (!valid_color_type(dstInfo) ||
+ !valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType()))
+ {
return kInvalidConversion;
}