Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2134)

Unified Diff: dm/DMSrcSink.cpp

Issue 1406223002: Create an SkAndroidCodec API separate from SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: dm/DMSrcSink.cpp
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 394b84fa7bd568a6a44a0235cff6bfb08a1201f7..85c4b29784b71362714eb67a06bea278e814a28b 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -249,18 +249,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
if (!encoded) {
return SkStringPrintf("Couldn't read %s.", fPath.c_str());
}
- SkAutoTDelete<SkCodec> codec(NULL);
- if (kScaledCodec_Mode == fMode) {
- codec.reset(SkScaledCodec::NewFromData(encoded));
- // TODO (msarett): This should fall through to a fatal error once we support scaled
- // codecs for all image types.
- if (nullptr == codec.get()) {
- return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec for %s.",
- fPath.c_str()));
- }
- } else {
- codec.reset(SkCodec::NewFromData(encoded));
- }
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
if (nullptr == codec.get()) {
return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
}
@@ -323,7 +312,6 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
}
switch (fMode) {
- case kScaledCodec_Mode:
case kCodec_Mode: {
switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), nullptr,
colorPtr, colorCountPtr)) {
@@ -585,14 +573,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
SkISize CodecSrc::size() const {
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
- SkAutoTDelete<SkCodec> codec(nullptr);
-
- if (kScaledCodec_Mode == fMode) {
- codec.reset(SkScaledCodec::NewFromData(encoded));
- } else {
- codec.reset(SkCodec::NewFromData(encoded));
- }
-
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
if (nullptr == codec) {
return SkISize::Make(0, 0);
}
@@ -608,6 +589,183 @@ Name CodecSrc::name() const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+AndroidCodecSrc::AndroidCodecSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType,
+ int sampleSize)
+ : fPath(path)
+ , fMode(mode)
+ , fDstColorType(dstColorType)
+ , fSampleSize(sampleSize)
+{}
+
+bool AndroidCodecSrc::veto(SinkFlags flags) const {
+ // No need to test decoding to non-raster or indirect backend.
+ // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
+ // let the GPU handle it.
+ return flags.type != SinkFlags::kRaster
+ || flags.approach != SinkFlags::kDirect;
+}
+
+Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
+ SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
+ if (!encoded) {
+ return SkStringPrintf("Couldn't read %s.", fPath.c_str());
+ }
+ SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
+ if (nullptr == codec.get()) {
+ return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
+ }
+
+ // Choose the color type to decode to
+ SkImageInfo decodeInfo = codec->getInfo();
msarett 2015/10/16 18:42:16 Much of this code is shared with CodecSrc. I'm lo
+ SkColorType canvasColorType = canvas->imageInfo().colorType();
+ switch (fDstColorType) {
+ case CodecSrc::kIndex8_Always_DstColorType:
+ decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType);
+ if (kRGB_565_SkColorType == canvasColorType) {
+ return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
+ }
+ break;
+ case CodecSrc::kGrayscale_Always_DstColorType:
+ decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType);
+ if (kRGB_565_SkColorType == canvasColorType) {
+ return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
+ }
+ break;
+ default:
+ decodeInfo = decodeInfo.makeColorType(canvasColorType);
+ break;
+ }
+
+ // Scale the image if it is desired.
+ SkISize size = codec->getSampledDimensions(fSampleSize);
+
+ // Visually inspecting very small output images is not necessary. We will
+ // cover these cases in unit testing.
+ if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
+ return Error::Nonfatal("Scaling very small images is uninteresting.");
+ }
+ decodeInfo = decodeInfo.makeWH(size.width(), size.height());
+
+ // Construct a color table for the decode if necessary
+ SkAutoTUnref<SkColorTable> colorTable(nullptr);
+ SkPMColor* colorPtr = nullptr;
+ int* colorCountPtr = nullptr;
+ int maxColors = 256;
+ if (kIndex_8_SkColorType == decodeInfo.colorType()) {
+ SkPMColor colors[256];
+ colorTable.reset(new SkColorTable(colors, maxColors));
+ colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
+ colorCountPtr = &maxColors;
+ }
+
+ // FIXME: Currently we cannot draw unpremultiplied sources.
+ if (decodeInfo.alphaType() == kUnpremul_SkAlphaType) {
+ decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
+ }
+
+ SkBitmap bitmap;
+ if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) {
+ return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
+ decodeInfo.width(), decodeInfo.height());
+ }
+
+ // Create options for the codec.
+ SkAndroidCodec::AndroidOptions options;
+ options.fColorPtr = colorPtr;
+ options.fColorCount = colorCountPtr;
+ options.fSampleSize = fSampleSize;
+
+ switch (fMode) {
+ case kFullImage_Mode: {
+ switch (codec->getAndroidPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(),
+ &options)) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
+ break;
+ case SkCodec::kInvalidConversion:
+ return Error::Nonfatal("Cannot convert to requested color type.\n");
+ default:
+ return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
+ }
+ canvas->drawBitmap(bitmap, 0, 0);
+ return "";
+ }
+ case kDivisor_Mode: {
+ const int width = codec->getInfo().width();
+ const int height = codec->getInfo().height();
+ const int divisor = 2;
+ if (width < divisor || height < divisor) {
+ return Error::Nonfatal("Divisor is larger than image dimension.\n");
+ }
+
+ // Rounding the size of the subsets may leave some pixels uninitialized on the bottom
+ // and right edges of the bitmap.
+ bitmap.eraseColor(0);
+ for (uint32_t x = 0; x < divisor; x++) {
+ for (uint32_t y = 0; y < divisor; y++) {
+ // Calculate the subset dimensions
+ int subsetWidth = width / divisor;
+ int subsetHeight = height / divisor;
+ const int left = x * subsetWidth;
+ const int top = y * subsetHeight;
+
+ // Increase the size of the last subset in each row or column, when the
+ // divisor does not divide evenly into the image dimensions
+ subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
+ subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
+ SkIRect subset = SkIRect::MakeXYWH(left, top, subsetWidth, subsetHeight);
+ if (!codec->getSubset(&subset)) {
+ return "Could not get subset to decode.\n";
+ }
+ options.fSubset = &subset;
+ void* pixels = bitmap.getAddr(subset.left() / fSampleSize,
+ subset.top() / fSampleSize);
+ SkISize scaledSubsetSize = codec->getSampledSubsetDimensions(fSampleSize,
+ subset);
+ SkImageInfo subsetDecodeInfo = decodeInfo.makeWH(scaledSubsetSize.width(),
+ scaledSubsetSize.height());
+
+ switch (codec->getAndroidPixels(subsetDecodeInfo, pixels, bitmap.rowBytes(),
+ &options)) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
+ break;
+ case SkCodec::kInvalidConversion:
+ return Error::Nonfatal("Cannot convert to requested color type.\n");
+ default:
+ return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
+ }
+ }
+ }
+ canvas->drawBitmap(bitmap, 0, 0);
+ return "";
+ }
+ default:
+ SkASSERT(false);
+ return "Error: Should not be reached.\n";
+ }
+}
+
+SkISize AndroidCodecSrc::size() const {
+ SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
+ SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
+ if (nullptr == codec) {
scroggo 2015/10/16 21:13:55 Maybe this reproduces the old code, but is it nece
msarett 2015/10/19 16:06:10 We'll create the AndroidCodecSrc before verifying
scroggo 2015/10/19 20:03:20 sgtm
+ return SkISize::Make(0, 0);
+ }
+ return codec->getSampledDimensions(fSampleSize);
+}
+
+Name AndroidCodecSrc::name() const {
+ // We will replicate the names used by CodecSrc so that images can
+ // be compared in Gold.
+ if (1 == fSampleSize) {
+ return SkOSPath::Basename(fPath.c_str());
+ }
+ return get_scaled_name(fPath, get_scale_from_sample_size(fSampleSize));
+}
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {}
bool ImageSrc::veto(SinkFlags flags) const {

Powered by Google App Engine
This is Rietveld 408576698