Implement Fill() for incomplete decodes to RGBA_F16
Before this patch, we would hit an SkASSERT(false).
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2335203002
Review-Url: https://codereview.chromium.org/2335203002
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 6b33023..0c7de85 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -915,7 +915,7 @@
size_t rowBytes = bitmap.rowBytes();
SkCodec::Result r = codec->getPixels(decodeInfo, bitmap.getPixels(), rowBytes);
- if (SkCodec::kSuccess != r) {
+ if (SkCodec::kSuccess != r && SkCodec::kIncompleteInput != r) {
return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
}
diff --git a/gyp/codec_android.gyp b/gyp/codec_android.gyp
index 833d430..ce96d8d 100644
--- a/gyp/codec_android.gyp
+++ b/gyp/codec_android.gyp
@@ -25,6 +25,7 @@
'../include/private',
'../src/android',
'../src/codec',
+ '../src/core',
],
'sources': [
'../src/android/SkBitmapRegionCodec.cpp',
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index bee4f3c..b0647ed 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -601,30 +601,30 @@
* On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
* scanlines. This allows the subclass to indicate what value to fill with.
*
- * @param colorType Destination color type.
+ * @param dstInfo Describes the destination.
* @return The value with which to fill uninitialized pixels.
*
- * Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color,
- * an 8-bit gray color, or an 8-bit index into a color table, depending on the color
- * type.
+ * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,
+ * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,
+ * depending on the color type.
*/
- uint32_t getFillValue(SkColorType colorType) const {
- return this->onGetFillValue(colorType);
+ uint64_t getFillValue(const SkImageInfo& dstInfo) const {
+ return this->onGetFillValue(dstInfo);
}
/**
* Some subclasses will override this function, but this is a useful default for the color
- * types that we support. Note that for color types that do not use the full 32-bits,
+ * types that we support. Note that for color types that do not use the full 64-bits,
* we will simply take the low bits of the fill value.
*
+ * The defaults are:
+ * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type
* kN32_SkColorType: Transparent or Black, depending on the src alpha type
* kRGB_565_SkColorType: Black
* kGray_8_SkColorType: Black
* kIndex_8_SkColorType: First color in color table
*/
- virtual uint32_t onGetFillValue(SkColorType /*colorType*/) const {
- return kOpaque_SkAlphaType == fSrcInfo.alphaType() ? SK_ColorBLACK : SK_ColorTRANSPARENT;
- }
+ virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;
/**
* Get method for the input stream
diff --git a/infra/bots/assets/skimage/VERSION b/infra/bots/assets/skimage/VERSION
index 1e8b314..c793025 100644
--- a/infra/bots/assets/skimage/VERSION
+++ b/infra/bots/assets/skimage/VERSION
@@ -1 +1 @@
-6
+7
\ No newline at end of file
diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp
index 089e310..7d67d18 100644
--- a/src/codec/SkBmpStandardCodec.cpp
+++ b/src/codec/SkBmpStandardCodec.cpp
@@ -302,10 +302,11 @@
}
}
-uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType) const {
+uint64_t SkBmpStandardCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
if (colorPtr) {
- return get_color_table_fill_value(colorType, colorPtr, 0);
+ return get_color_table_fill_value(dstInfo.colorType(), dstInfo.alphaType(), colorPtr, 0,
+ nullptr);
}
- return INHERITED::onGetFillValue(colorType);
+ return INHERITED::onGetFillValue(dstInfo);
}
diff --git a/src/codec/SkBmpStandardCodec.h b/src/codec/SkBmpStandardCodec.h
index 506742b..7039cf7 100644
--- a/src/codec/SkBmpStandardCodec.h
+++ b/src/codec/SkBmpStandardCodec.h
@@ -57,7 +57,7 @@
int* inputColorCount) override;
- uint32_t onGetFillValue(SkColorType) const override;
+ uint64_t onGetFillValue(const SkImageInfo&) const override;
SkSampler* getSampler(bool createIfNecessary) override {
SkASSERT(fSwizzler);
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index b076954..6f29870 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -11,6 +11,7 @@
#include "SkColorSpace.h"
#include "SkData.h"
#include "SkGifCodec.h"
+#include "SkHalf.h"
#include "SkIcoCodec.h"
#include "SkJpegCodec.h"
#ifdef SK_HAS_PNG_LIBRARY
@@ -353,8 +354,24 @@
}
}
+uint64_t SkCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
+ switch (dstInfo.colorType()) {
+ case kRGBA_F16_SkColorType: {
+ static constexpr uint64_t transparentColor = 0;
+ static constexpr uint64_t opaqueColor = ((uint64_t) SK_Half1) << 48;
+ return (kOpaque_SkAlphaType == fSrcInfo.alphaType()) ? opaqueColor : transparentColor;
+ }
+ default: {
+ // This not only handles the kN32 case, but also k565, kGray8, kIndex8, since
+ // the low bits are zeros.
+ return (kOpaque_SkAlphaType == fSrcInfo.alphaType()) ?
+ SK_ColorBLACK : SK_ColorTRANSPARENT;
+ }
+ }
+}
+
static void fill_proc(const SkImageInfo& info, void* dst, size_t rowBytes,
- uint32_t colorOrIndex, SkCodec::ZeroInitialized zeroInit, SkSampler* sampler) {
+ uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit, SkSampler* sampler) {
if (sampler) {
sampler->fill(info, dst, rowBytes, colorOrIndex, zeroInit);
} else {
@@ -366,7 +383,7 @@
ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
void* fillDst;
- const uint32_t fillValue = this->getFillValue(info.colorType());
+ const uint64_t fillValue = this->getFillValue(info);
const int linesRemaining = linesRequested - linesDecoded;
SkSampler* sampler = this->getSampler(false);
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index 5845256..8876b72 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -9,6 +9,7 @@
#define SkCodecPriv_DEFINED
#include "SkColorPriv.h"
+#include "SkColorSpaceXform.h"
#include "SkColorTable.h"
#include "SkImageInfo.h"
#include "SkTypes.h"
@@ -146,8 +147,8 @@
/*
* Given that the encoded image uses a color table, return the fill value
*/
-static inline uint32_t get_color_table_fill_value(SkColorType colorType, const SkPMColor* colorPtr,
- uint8_t fillIndex) {
+static inline uint64_t get_color_table_fill_value(SkColorType colorType, SkAlphaType alphaType,
+ const SkPMColor* colorPtr, uint8_t fillIndex, SkColorSpaceXform* colorXform) {
SkASSERT(nullptr != colorPtr);
switch (colorType) {
case kRGBA_8888_SkColorType:
@@ -157,6 +158,13 @@
return SkPixel32ToPixel16(colorPtr[fillIndex]);
case kIndex_8_SkColorType:
return fillIndex;
+ case kRGBA_F16_SkColorType: {
+ SkASSERT(colorXform);
+ uint64_t dstColor;
+ uint32_t srcColor = colorPtr[fillIndex];
+ colorXform->apply(&dstColor, &srcColor, 1, colorType, alphaType);
+ return dstColor;
+ }
default:
SkASSERT(false);
return 0;
diff --git a/src/codec/SkGifCodec.cpp b/src/codec/SkGifCodec.cpp
index 1e6e300..c35cd24 100644
--- a/src/codec/SkGifCodec.cpp
+++ b/src/codec/SkGifCodec.cpp
@@ -494,7 +494,7 @@
// Initialize the swizzler
if (fFrameIsSubset) {
// Fill the background
- SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo.colorType()),
+ SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo),
opts.fZeroInitialized);
}
@@ -512,9 +512,10 @@
// FIXME: This is similar to the implementation for bmp and png. Can we share more code or
// possibly make this non-virtual?
-uint32_t SkGifCodec::onGetFillValue(SkColorType colorType) const {
+uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
- return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
+ return get_color_table_fill_value(dstInfo.colorType(), dstInfo.alphaType(), colorPtr,
+ fFillIndex, nullptr);
}
SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
@@ -555,7 +556,7 @@
if (fFrameIsSubset) {
// Fill the requested rows
SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
- uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType());
+ uint64_t fillValue = this->onGetFillValue(this->dstInfo());
fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized);
// Start to write pixels at the start of the image frame
diff --git a/src/codec/SkGifCodec.h b/src/codec/SkGifCodec.h
index 984bcea..c56d371 100644
--- a/src/codec/SkGifCodec.h
+++ b/src/codec/SkGifCodec.h
@@ -66,7 +66,7 @@
bool onRewind() override;
- uint32_t onGetFillValue(SkColorType) const override;
+ uint64_t onGetFillValue(const SkImageInfo&) const override;
int onOutputScanline(int inputScanline) const override;
diff --git a/src/codec/SkMaskSwizzler.h b/src/codec/SkMaskSwizzler.h
index 1dc1918..3bf8d17 100644
--- a/src/codec/SkMaskSwizzler.h
+++ b/src/codec/SkMaskSwizzler.h
@@ -39,7 +39,7 @@
/**
* Implement fill using a custom width.
*/
- void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint32_t colorOrIndex,
+ void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint64_t colorOrIndex,
SkCodec::ZeroInitialized zeroInit) override {
const SkImageInfo fillInfo = info.makeWH(fDstWidth, info.height());
SkSampler::Fill(fillInfo, dst, rowBytes, colorOrIndex, zeroInit);
diff --git a/src/codec/SkPngCodec.cpp b/src/codec/SkPngCodec.cpp
index 46da29e..0002bc5 100644
--- a/src/codec/SkPngCodec.cpp
+++ b/src/codec/SkPngCodec.cpp
@@ -899,12 +899,15 @@
return kSuccess;
}
-uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const {
+uint64_t SkPngCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
if (colorPtr) {
- return get_color_table_fill_value(colorType, colorPtr, 0);
+ SkAlphaType alphaType = select_alpha_xform(dstInfo.alphaType(),
+ this->getInfo().alphaType());
+ return get_color_table_fill_value(dstInfo.colorType(), alphaType, colorPtr, 0,
+ fColorXform.get());
}
- return INHERITED::onGetFillValue(colorType);
+ return INHERITED::onGetFillValue(dstInfo);
}
SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkReader) {
diff --git a/src/codec/SkPngCodec.h b/src/codec/SkPngCodec.h
index fba29a9..a4c20c7 100644
--- a/src/codec/SkPngCodec.h
+++ b/src/codec/SkPngCodec.h
@@ -43,7 +43,7 @@
override;
SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; }
bool onRewind() override;
- uint32_t onGetFillValue(SkColorType) const override;
+ uint64_t onGetFillValue(const SkImageInfo&) const override;
// Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info.
bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr,
diff --git a/src/codec/SkSampledCodec.cpp b/src/codec/SkSampledCodec.cpp
index 49c939c..47f99f7 100644
--- a/src/codec/SkSampledCodec.cpp
+++ b/src/codec/SkSampledCodec.cpp
@@ -253,7 +253,7 @@
// We handle filling uninitialized memory here instead of using this->codec().
// this->codec() does not know that we are sampling.
- const uint32_t fillValue = this->codec()->getFillValue(info.colorType());
+ const uint64_t fillValue = this->codec()->getFillValue(info);
const SkImageInfo fillInfo = info.makeWH(info.width(), 1);
for (; y < nativeSize.height(); y++) {
int srcY = this->codec()->outputScanline(y);
diff --git a/src/codec/SkSampler.cpp b/src/codec/SkSampler.cpp
index ccfe400..244aa3b 100644
--- a/src/codec/SkSampler.cpp
+++ b/src/codec/SkSampler.cpp
@@ -11,7 +11,7 @@
#include "SkUtils.h"
void SkSampler::Fill(const SkImageInfo& info, void* dst, size_t rowBytes,
- uint32_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {
+ uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {
SkASSERT(dst != nullptr);
// Calculate bytes to fill. We use getSafeSize since the last row may not be padded.
@@ -24,26 +24,15 @@
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType: {
// If memory is zero initialized, we may not need to fill
- uint32_t color = colorOrIndex;
+ uint32_t color = (uint32_t) colorOrIndex;
if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == color) {
return;
}
- // We must fill row by row in the case of unaligned row bytes
- if (SkIsAlign4((size_t) dst) && SkIsAlign4(rowBytes)) {
- sk_memset32((uint32_t*) dst, color,
- (uint32_t) bytesToFill / sizeof(SkPMColor));
- } else {
- // We must fill row by row in the case of unaligned row bytes. This is an
- // unlikely, slow case.
- SkCodecPrintf("Warning: Strange number of row bytes, fill will be slow.\n");
- uint32_t* dstRow = (uint32_t*) dst;
- for (int row = 0; row < numRows; row++) {
- for (int col = 0; col < width; col++) {
- dstRow[col] = color;
- }
- dstRow = SkTAddOffset<uint32_t>(dstRow, rowBytes);
- }
+ uint32_t* dstRow = (uint32_t*) dst;
+ for (int row = 0; row < numRows; row++) {
+ sk_memset32((uint32_t*) dstRow, color, width);
+ dstRow = SkTAddOffset<uint32_t>(dstRow, rowBytes);
}
break;
}
@@ -61,19 +50,10 @@
return;
}
- if (SkIsAlign2((size_t) dst) && SkIsAlign2(rowBytes)) {
- sk_memset16((uint16_t*) dst, color, (uint32_t) bytesToFill / sizeof(uint16_t));
- } else {
- // We must fill row by row in the case of unaligned row bytes. This is an
- // unlikely, slow case.
- SkCodecPrintf("Warning: Strange number of row bytes, fill will be slow.\n");
- uint16_t* dstRow = (uint16_t*) dst;
- for (int row = 0; row < numRows; row++) {
- for (int col = 0; col < width; col++) {
- dstRow[col] = color;
- }
- dstRow = SkTAddOffset<uint16_t>(dstRow, rowBytes);
- }
+ uint16_t* dstRow = (uint16_t*) dst;
+ for (int row = 0; row < numRows; row++) {
+ sk_memset16((uint16_t*) dstRow, color, width);
+ dstRow = SkTAddOffset<uint16_t>(dstRow, rowBytes);
}
break;
}
@@ -95,6 +75,19 @@
memset(dst, (uint8_t) colorOrIndex, bytesToFill);
break;
+ case kRGBA_F16_SkColorType: {
+ uint64_t color = colorOrIndex;
+ if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == color) {
+ return;
+ }
+
+ uint64_t* dstRow = (uint64_t*) dst;
+ for (int row = 0; row < numRows; row++) {
+ sk_memset64((uint64_t*) dstRow, color, width);
+ dstRow = SkTAddOffset<uint64_t>(dstRow, rowBytes);
+ }
+ break;
+ }
default:
SkCodecPrintf("Error: Unsupported dst color type for fill(). Doing nothing.\n");
SkASSERT(false);
diff --git a/src/codec/SkSampler.h b/src/codec/SkSampler.h
index 73e11c9..b233c32 100644
--- a/src/codec/SkSampler.h
+++ b/src/codec/SkSampler.h
@@ -35,6 +35,7 @@
* Stride in bytes of the destination.
*
* @param colorOrIndex
+ * If colorType is kF16, colorOrIndex is treated as a 64-bit color.
* If colorType is kN32, colorOrIndex is treated as a 32-bit color.
* If colorType is k565, colorOrIndex is treated as a 16-bit color.
* If colorType is kGray, colorOrIndex is treated as an 8-bit color.
@@ -46,13 +47,13 @@
*
*/
static void Fill(const SkImageInfo& info, void* dst, size_t rowBytes,
- uint32_t colorOrIndex, SkCodec::ZeroInitialized zeroInit);
+ uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit);
/**
* Allow subclasses to implement unique versions of fill().
*/
virtual void fill(const SkImageInfo& info, void* dst, size_t rowBytes,
- uint32_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {}
+ uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {}
virtual ~SkSampler() {}
private:
diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h
index 6172af5..a535298 100644
--- a/src/codec/SkSwizzler.h
+++ b/src/codec/SkSwizzler.h
@@ -56,7 +56,7 @@
/**
* Implement fill using a custom width.
*/
- void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint32_t colorOrIndex,
+ void fill(const SkImageInfo& info, void* dst, size_t rowBytes, uint64_t colorOrIndex,
SkCodec::ZeroInitialized zeroInit) override {
const SkImageInfo fillInfo = info.makeWH(fAllocatedWidth, info.height());
SkSampler::Fill(fillInfo, dst, rowBytes, colorOrIndex, zeroInit);