Chromium Code Reviews| 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 = ⊂ |
| + 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 { |