}
static void push_codec_src(Path path, CodecSrc::Mode mode, CodecSrc::DstColorType dstColorType,
- float scale) {
+ SkAlphaType dstAlphaType, float scale) {
SkString folder;
switch (mode) {
case CodecSrc::kCodec_Mode:
break;
}
+ switch (dstAlphaType) {
+ case kOpaque_SkAlphaType:
+ folder.append("_opaque");
+ break;
+ case kPremul_SkAlphaType:
+ folder.append("_premul");
+ break;
+ case kUnpremul_SkAlphaType:
+ folder.append("_unpremul");
+ break;
+ default:
+ break;
+ }
+
if (1.0f != scale) {
folder.appendf("_%.3f", scale);
}
- CodecSrc* src = new CodecSrc(path, mode, dstColorType, scale);
+ CodecSrc* src = new CodecSrc(path, mode, dstColorType, dstAlphaType, scale);
push_src("image", folder, src);
}
static void push_android_codec_src(Path path, AndroidCodecSrc::Mode mode,
- CodecSrc::DstColorType dstColorType, int sampleSize) {
+ CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType, int sampleSize) {
SkString folder;
switch (mode) {
case AndroidCodecSrc::kFullImage_Mode:
break;
}
+ switch (dstAlphaType) {
+ case kOpaque_SkAlphaType:
+ folder.append("_opaque");
+ break;
+ case kPremul_SkAlphaType:
+ folder.append("_premul");
+ break;
+ default:
+ break;
+ }
+
if (1 != sampleSize) {
folder.appendf("_%.3f", 1.0f / (float) sampleSize);
}
- AndroidCodecSrc* src = new AndroidCodecSrc(path, mode, dstColorType, sampleSize);
+ AndroidCodecSrc* src = new AndroidCodecSrc(path, mode, dstColorType, dstAlphaType, sampleSize);
push_src("image", folder, src);
}
break;
}
+ SkTArray<SkAlphaType> alphaModes;
+ alphaModes.push_back(kPremul_SkAlphaType);
+ // FIXME: Currently we cannot draw unpremultiplied sources. skbug.com/3338 and skbug.com/3339
+ // alphaModes.push_back(kUnpremul_SkAlphaType);
+ if (codec->getInfo().alphaType() == kOpaque_SkAlphaType) {
+ alphaModes.push_back(kOpaque_SkAlphaType);
+ }
for (CodecSrc::Mode mode : nativeModes) {
// SkCodecImageGenerator only runs for the default colorType
if (CodecSrc::kGen_Mode == mode) {
// FIXME: The gpu backend does not draw kGray sources correctly. (skbug.com/4822)
if (kGray_8_SkColorType != codec->getInfo().colorType()) {
- push_codec_src(path, mode, CodecSrc::kGetFromCanvas_DstColorType, 1.0f);
+ push_codec_src(path, mode, CodecSrc::kGetFromCanvas_DstColorType,
+ codec->getInfo().alphaType(), 1.0f);
}
continue;
}
for (float scale : nativeScales) {
for (uint32_t i = 0; i < numColorTypes; i++) {
- push_codec_src(path, mode, colorTypes[i], scale);
+ for (SkAlphaType alphaType : alphaModes) {
+ push_codec_src(path, mode, colorTypes[i], alphaType, scale);
+ }
}
}
}
for (int sampleSize : sampleSizes) {
for (uint32_t i = 0; i < numColorTypes; i++) {
- push_android_codec_src(path, AndroidCodecSrc::kFullImage_Mode, colorTypes[i],
- sampleSize);
- if (subset) {
- push_android_codec_src(path, AndroidCodecSrc::kDivisor_Mode, colorTypes[i],
- sampleSize);
+ for (SkAlphaType alphaType : alphaModes) {
+ push_android_codec_src(path, AndroidCodecSrc::kFullImage_Mode, colorTypes[i],
+ alphaType, sampleSize);
+ if (subset) {
+ push_android_codec_src(path, AndroidCodecSrc::kDivisor_Mode, colorTypes[i],
+ alphaType, sampleSize);
+ }
}
}
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale)
+CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType dstAlphaType,
+ float scale)
: fPath(path)
, fMode(mode)
, fDstColorType(dstColorType)
+ , fDstAlphaType(dstAlphaType)
, fScale(scale)
{}
return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}
-bool get_decode_info(SkImageInfo* decodeInfo, const SkImageInfo& defaultInfo,
- SkColorType canvasColorType, CodecSrc::DstColorType dstColorType) {
+bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
+ CodecSrc::DstColorType dstColorType) {
switch (dstColorType) {
case CodecSrc::kIndex8_Always_DstColorType:
if (kRGB_565_SkColorType == canvasColorType) {
return false;
}
- *decodeInfo = defaultInfo.makeColorType(kIndex_8_SkColorType);
+ *decodeInfo = decodeInfo->makeColorType(kIndex_8_SkColorType);
break;
case CodecSrc::kGrayscale_Always_DstColorType:
if (kRGB_565_SkColorType == canvasColorType) {
return false;
}
- *decodeInfo = defaultInfo.makeColorType(kGray_8_SkColorType);
+ *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
break;
default:
- *decodeInfo = defaultInfo.makeColorType(canvasColorType);
+ *decodeInfo = decodeInfo->makeColorType(canvasColorType);
break;
}
- // FIXME: Currently we cannot draw unpremultiplied sources.
- if (decodeInfo->alphaType() == kUnpremul_SkAlphaType) {
- *decodeInfo = decodeInfo->makeAlphaType(kPremul_SkAlphaType);
- }
return true;
}
return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
}
- SkImageInfo decodeInfo;
- if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
- fDstColorType)) {
+ SkImageInfo decodeInfo = codec->getInfo().makeAlphaType(fDstAlphaType);
+ if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType)) {
return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
AndroidCodecSrc::AndroidCodecSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType,
- int sampleSize)
+ SkAlphaType dstAlphaType, int sampleSize)
: fPath(path)
, fMode(mode)
, fDstColorType(dstColorType)
+ , fDstAlphaType(dstAlphaType)
, fSampleSize(sampleSize)
{}
return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
}
- SkImageInfo decodeInfo;
- if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
- fDstColorType)) {
+ SkImageInfo decodeInfo = codec->getInfo().makeAlphaType(fDstAlphaType);
+ if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType)) {
return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
}
kIndex8_Always_DstColorType,
kGrayscale_Always_DstColorType,
};
- CodecSrc(Path, Mode, DstColorType, float);
+ CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
Error draw(SkCanvas*) const override;
SkISize size() const override;
Path fPath;
Mode fMode;
DstColorType fDstColorType;
+ SkAlphaType fDstAlphaType;
float fScale;
};
kDivisor_Mode,
};
- AndroidCodecSrc(Path, Mode, CodecSrc::DstColorType, int sampleSize);
+ AndroidCodecSrc(Path, Mode, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
Error draw(SkCanvas*) const override;
SkISize size() const override;
Path fPath;
Mode fMode;
CodecSrc::DstColorType fDstColorType;
+ SkAlphaType fDstAlphaType;
int fSampleSize;
};
* scanlines. This allows the subclass to indicate what value to fill with.
*
* @param colorType Destination color type.
- * @param alphaType Destination alpha type.
* @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.
*/
- uint32_t getFillValue(SkColorType colorType, SkAlphaType alphaType) const {
- return this->onGetFillValue(colorType, alphaType);
+ uint32_t getFillValue(SkColorType colorType) const {
+ return this->onGetFillValue(colorType);
}
/**
* types that we support. Note that for color types that do not use the full 32-bits,
* we will simply take the low bits of the fill value.
*
- * kN32_SkColorType: Transparent or Black
+ * 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*/, SkAlphaType alphaType) const {
- return kOpaque_SkAlphaType == alphaType ? SK_ColorBLACK : SK_ColorTRANSPARENT;
+ virtual uint32_t onGetFillValue(SkColorType /*colorType*/) const {
+ return kOpaque_SkAlphaType == fSrcInfo.alphaType() ? SK_ColorBLACK : SK_ColorTRANSPARENT;
}
/**
config = SkSwizzler::kBGR;
break;
case 32:
- if (kOpaque_SkAlphaType == dstInfo.alphaType()) {
+ if (kOpaque_SkAlphaType == this->getInfo().alphaType()) {
config = SkSwizzler::kBGRX;
} else {
config = SkSwizzler::kBGRA;
}
}
-uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
+uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
if (colorPtr) {
return get_color_table_fill_value(colorType, colorPtr, 0);
}
- return INHERITED::onGetFillValue(colorType, alphaType);
+ return INHERITED::onGetFillValue(colorType);
}
int* inputColorCount) override;
- uint32_t onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const override;
+ uint32_t onGetFillValue(SkColorType) const override;
SkSampler* getSampler(bool createIfNecessary) override {
SkASSERT(fSwizzler);
ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
void* fillDst;
- const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaType());
+ const uint32_t fillValue = this->getFillValue(info.colorType());
const int linesRemaining = linesRequested - linesDecoded;
SkSampler* sampler = this->getSampler(false);
#include "SkTypes.h"
#include "SkUtils.h"
+#ifdef SK_PRINT_CODEC_MESSAGES
+ #define SkCodecPrintf SkDebugf
+#else
+ #define SkCodecPrintf(...)
+#endif
+
// FIXME: Consider sharing with dm, nanbench, and tools.
inline float get_scale_from_sample_size(int sampleSize) {
return 1.0f / ((float) sampleSize);
}
inline bool valid_alpha(SkAlphaType dstAlpha, SkAlphaType srcAlpha) {
- // Check for supported alpha types
+ if (kUnknown_SkAlphaType == dstAlpha) {
+ return false;
+ }
+
if (srcAlpha != dstAlpha) {
if (kOpaque_SkAlphaType == srcAlpha) {
- // If the source is opaque, we must decode to opaque
- return false;
+ // If the source is opaque, we can support any.
+ SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
+ "- it is being decoded as non-opaque, which will draw slower\n");
+ return true;
}
// The source is not opaque
/*
* Most of our codecs support the same conversions:
* - profileType must be the same
- * - opaque only to opaque (and 565 only if opaque)
+ * - opaque to any alpha type
+ * - 565 only if opaque
* - premul to unpremul and vice versa
* - always support N32
* - otherwise match the src color type
#endif
}
-#ifdef SK_PRINT_CODEC_MESSAGES
- #define SkCodecPrintf SkDebugf
-#else
- #define SkCodecPrintf(...)
-#endif
-
#endif // SkCodecPriv_DEFINED
// Initialize the swizzler
if (fFrameIsSubset) {
// Fill the background
- SkSampler::Fill(dstInfo, dst, dstRowBytes,
- this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
+ SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo.colorType()),
opts.fZeroInitialized);
}
// 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, SkAlphaType alphaType) const {
+uint32_t SkGifCodec::onGetFillValue(SkColorType colorType) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
}
if (fFrameIsSubset) {
// Fill the requested rows
SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
- uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType(),
- this->dstInfo().alphaType());
+ uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType());
fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized);
// Start to write pixels at the start of the image frame
bool onRewind() override;
- uint32_t onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const override;
+ uint32_t onGetFillValue(SkColorType) const override;
int onOutputScanline(int inputScanline) const override;
return false;
}
- // Ensure that the alpha type is opaque
- if (kOpaque_SkAlphaType != dst.alphaType()) {
+ if (kUnknown_SkAlphaType == dst.alphaType()) {
return false;
}
+ if (kOpaque_SkAlphaType != dst.alphaType()) {
+ SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
+ "- it is being decoded as non-opaque, which will draw slower\n");
+ }
+
// Check if we will decode to CMYK because a conversion to RGBA is not supported
J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;
}
break;
case kRGB_565_SkColorType:
- switch (dstInfo.alphaType()) {
- case kOpaque_SkAlphaType:
- proc = &swizzle_mask16_to_565;
- break;
- default:
- break;
- }
+ proc = &swizzle_mask16_to_565;
break;
default:
break;
}
break;
case kRGB_565_SkColorType:
- switch (dstInfo.alphaType()) {
- case kOpaque_SkAlphaType:
- proc = &swizzle_mask24_to_565;
- break;
- default:
- break;
- }
+ proc = &swizzle_mask24_to_565;
break;
default:
break;
}
break;
case kRGB_565_SkColorType:
- switch (dstInfo.alphaType()) {
- case kOpaque_SkAlphaType:
- proc = &swizzle_mask32_to_565;
- break;
- default:
- break;
- }
+ proc = &swizzle_mask32_to_565;
break;
default:
break;
return kSuccess;
}
-uint32_t SkPngCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
+uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const {
const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
if (colorPtr) {
return get_color_table_fill_value(colorType, colorPtr, 0);
}
- return INHERITED::onGetFillValue(colorType, alphaType);
+ return INHERITED::onGetFillValue(colorType);
}
// Subclass of SkPngCodec which supports scanline decoding
override;
SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; }
bool onRewind() override;
- uint32_t onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const override;
+ uint32_t onGetFillValue(SkColorType) const override;
// Helper to set up swizzler and color table. Also calls png_read_update_info.
Result initializeSwizzler(const SkImageInfo& requestedInfo, const Options&,
// 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(),
- info.alphaType());
+ const uint32_t fillValue = this->codec()->getFillValue(info.colorType());
const SkImageInfo fillInfo = info.makeWH(info.width(), 1);
for (; y < nativeSize.height(); y++) {
int srcY = this->codec()->outputScanline(y);
// Check alpha type conversions
if (info.alphaType() == kOpaque_SkAlphaType) {
test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType),
- SkCodec::kInvalidConversion, nullptr);
+ expectedResult, digest);
test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType),
- SkCodec::kInvalidConversion, nullptr);
+ expectedResult, digest);
} else {
// Decoding to opaque should fail
test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType),
// Check alpha type conversions
if (info.alphaType() == kOpaque_SkAlphaType) {
test_android_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType),
- SkCodec::kInvalidConversion, nullptr);
+ expectedResult, digest);
test_android_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType),
- SkCodec::kInvalidConversion, nullptr);
+ expectedResult, digest);
} else {
// Decoding to opaque should fail
test_android_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType),