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

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: Win bot fix 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
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/codec.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dm/DMSrcSink.cpp
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 394b84fa7bd568a6a44a0235cff6bfb08a1201f7..24ae2d6087ebd4da20775ca7710072190a42d8e3 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -7,6 +7,7 @@
#include "DMSrcSink.h"
#include "SamplePipeControllers.h"
+#include "SkAndroidCodec.h"
#include "SkCodec.h"
#include "SkCodecTools.h"
#include "SkCommonFlags.h"
@@ -25,11 +26,9 @@
#include "SkRecorder.h"
#include "SkRemote.h"
#include "SkSVGCanvas.h"
-#include "SkScaledCodec.h"
#include "SkStream.h"
#include "SkTLogic.h"
#include "SkXMLWriter.h"
-#include "SkScaledCodec.h"
#include "SkSwizzler.h"
DEFINE_bool(multiPage, false, "For document-type backends, render the source"
@@ -244,46 +243,47 @@ bool CodecSrc::veto(SinkFlags flags) const {
|| flags.approach != SinkFlags::kDirect;
}
+bool get_decode_info(SkImageInfo* decodeInfo, const SkImageInfo& defaultInfo,
+ 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);
+ break;
+ case CodecSrc::kGrayscale_Always_DstColorType:
+ if (kRGB_565_SkColorType == canvasColorType) {
+ return false;
+ }
+ *decodeInfo = defaultInfo.makeColorType(kGray_8_SkColorType);
+ break;
+ default:
+ *decodeInfo = defaultInfo.makeColorType(canvasColorType);
+ break;
+ }
+
+ // FIXME: Currently we cannot draw unpremultiplied sources.
+ if (decodeInfo->alphaType() == kUnpremul_SkAlphaType) {
+ decodeInfo->makeAlphaType(kPremul_SkAlphaType);
+ }
+ return true;
+}
+
Error CodecSrc::draw(SkCanvas* canvas) const {
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
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());
}
- // Choose the color type to decode to
- SkImageInfo decodeInfo = codec->getInfo();
- SkColorType canvasColorType = canvas->imageInfo().colorType();
- switch (fDstColorType) {
- case 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 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;
+ SkImageInfo decodeInfo;
+ if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
+ fDstColorType)) {
+ return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
}
// Try to scale the image if it is desired
@@ -311,11 +311,6 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
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(),
@@ -323,7 +318,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 +579,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 +595,163 @@ 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());
+ }
+
+ SkImageInfo decodeInfo;
+ if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
+ fDstColorType)) {
+ return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
+ }
+
+ // 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;
+ }
+
+ 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 (int x = 0; x < divisor; x++) {
+ for (int 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->getSupportedSubset(&subset)) {
+ return "Could not get supported 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) {
+ 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 {
« no previous file with comments | « dm/DMSrcSink.h ('k') | gyp/codec.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698