DM testing for skipping and scaling

BUG=skia:

Review URL: https://codereview.chromium.org/1175993005
This commit is contained in:
msarett 2015-06-11 14:27:27 -07:00 committed by Commit bot
parent 8f086023bf
commit 0a24297be4
3 changed files with 142 additions and 37 deletions

View File

@ -205,38 +205,54 @@ static void push_codec_srcs(Path path) {
return;
}
// Build additional test cases for images that decode natively to non-canvas types
switch(codec->getInfo().colorType()) {
case kGray_8_SkColorType:
push_src("image", "codec_kGray8", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kGrayscale_Always_DstColorType));
push_src("image", "scanline_kGray8", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kGrayscale_Always_DstColorType));
push_src("image", "scanline_subset_kGray8", new CodecSrc(path,
CodecSrc::kScanline_Subset_Mode, CodecSrc::kGrayscale_Always_DstColorType));
// Intentional fall through
// FIXME: Is this a long term solution for testing wbmps decodes to kIndex8?
// Further discussion on this topic is at skbug.com/3683
case kIndex_8_SkColorType:
push_src("image", "codec_kIndex8", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kIndex8_Always_DstColorType));
push_src("image", "scanline_kIndex8", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kIndex8_Always_DstColorType));
push_src("image", "scanline_subset_kIndex8", new CodecSrc(path,
CodecSrc::kScanline_Subset_Mode, CodecSrc::kIndex8_Always_DstColorType));
break;
default:
// Do nothing
break;
}
// Choose scales for scaling tests.
// TODO (msarett): Add more scaling tests as we implement more flexible scaling.
// TODO (msarett): Implement scaling tests for SkImageDecoder in order to compare with these
// tests. SkImageDecoder supports downscales by integer factors.
const float scales[] = { 0.125f, 0.25f, 0.5f, 1.0f };
// Decode all images to the canvas color type
push_src("image", "codec", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kGetFromCanvas_DstColorType));
push_src("image", "scanline", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kGetFromCanvas_DstColorType));
push_src("image", "scanline_subset", new CodecSrc(path, CodecSrc::kScanline_Subset_Mode,
CodecSrc::kGetFromCanvas_DstColorType));
for (float scale : scales) {
// Build additional test cases for images that decode natively to non-canvas types
switch(codec->getInfo().colorType()) {
case kGray_8_SkColorType:
push_src("image", "codec_kGray8", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kGrayscale_Always_DstColorType, scale));
push_src("image", "scanline_kGray8", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kGrayscale_Always_DstColorType, scale));
push_src("image", "scanline_subset_kGray8", new CodecSrc(path,
CodecSrc::kScanline_Subset_Mode, CodecSrc::kGrayscale_Always_DstColorType,
scale));
push_src("image", "stripe_kGray8", new CodecSrc(path, CodecSrc::kStripe_Mode,
CodecSrc::kGrayscale_Always_DstColorType, scale));
// Intentional fall through
// FIXME: Is this a long term solution for testing wbmps decodes to kIndex8?
// Further discussion on this topic is at skbug.com/3683
case kIndex_8_SkColorType:
push_src("image", "codec_kIndex8", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kIndex8_Always_DstColorType, scale));
push_src("image", "scanline_kIndex8", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kIndex8_Always_DstColorType, scale));
push_src("image", "scanline_subset_kIndex8", new CodecSrc(path,
CodecSrc::kScanline_Subset_Mode, CodecSrc::kIndex8_Always_DstColorType,
scale));
push_src("image", "stripe_kIndex8", new CodecSrc(path, CodecSrc::kStripe_Mode,
CodecSrc::kIndex8_Always_DstColorType, scale));
break;
default:
// Do nothing
break;
}
// Decode all images to the canvas color type
push_src("image", "codec", new CodecSrc(path, CodecSrc::kNormal_Mode,
CodecSrc::kGetFromCanvas_DstColorType, scale));
push_src("image", "scanline", new CodecSrc(path, CodecSrc::kScanline_Mode,
CodecSrc::kGetFromCanvas_DstColorType, scale));
push_src("image", "scanline_subset", new CodecSrc(path, CodecSrc::kScanline_Subset_Mode,
CodecSrc::kGetFromCanvas_DstColorType, scale));
push_src("image", "stripe", new CodecSrc(path, CodecSrc::kStripe_Mode,
CodecSrc::kGetFromCanvas_DstColorType, scale));
}
}
static bool codec_supported(const char* ext) {

View File

@ -64,10 +64,11 @@ void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType)
CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale)
: fPath(path)
, fMode(mode)
, fDstColorType(dstColorType)
, fScale(scale)
{}
Error CodecSrc::draw(SkCanvas* canvas) const {
@ -108,6 +109,13 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
break;
}
// Try to scale the image if it is desired
SkISize size = codec->getScaledDimensions(fScale);
if (size == decodeInfo.dimensions() && 1.0f != fScale) {
return Error::Nonfatal("Test without scaling is uninteresting.");
}
decodeInfo = decodeInfo.makeWH(size.width(), size.height());
// Construct a color table for the decode if necessary
SkAutoTUnref<SkColorTable> colorTable(NULL);
SkPMColor* colorPtr = NULL;
@ -195,7 +203,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
* subsetBm's size is determined based on the current subset and may be larger for end
* subsets.
*/
SkImageInfo largestSubsetDecodeInfo =
SkImageInfo largestSubsetDecodeInfo =
decodeInfo.makeWH(subsetWidth + extraX, subsetHeight + extraY);
SkBitmap largestSubsetBm;
if (!largestSubsetBm.tryAllocPixels(largestSubsetDecodeInfo, NULL, colorTable.get())) {
@ -226,7 +234,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
}
}
//skip to first line of subset
const SkImageGenerator::Result skipResult =
const SkImageGenerator::Result skipResult =
subsetScanlineDecoder->skipScanlines(y);
switch (skipResult) {
case SkImageGenerator::kSuccess:
@ -262,6 +270,80 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
}
break;
}
case kStripe_Mode: {
const int height = decodeInfo.height();
// This value is chosen arbitrarily. We exercise more cases by choosing a value that
// does not align with image blocks.
const int stripeHeight = 37;
const int numStripes = (height + stripeHeight - 1) / stripeHeight;
// Decode odd stripes
SkScanlineDecoder* decoder = codec->getScanlineDecoder(decodeInfo, NULL, colorPtr,
colorCountPtr);
if (NULL == decoder) {
return Error::Nonfatal("Cannot use scanline decoder for all images");
}
for (int i = 0; i < numStripes; i += 2) {
// Skip a stripe
const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
SkImageGenerator::Result result = decoder->skipScanlines(linesToSkip);
switch (result) {
case SkImageGenerator::kSuccess:
case SkImageGenerator::kIncompleteInput:
break;
default:
return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str());
}
// Read a stripe
const int startY = (i + 1) * stripeHeight;
const int linesToRead = SkTMin(stripeHeight, height - startY);
if (linesToRead > 0) {
result = decoder->getScanlines(bitmap.getAddr(0, startY),
linesToRead, bitmap.rowBytes());
switch (result) {
case SkImageGenerator::kSuccess:
case SkImageGenerator::kIncompleteInput:
break;
default:
return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str());
}
}
}
// Decode even stripes
decoder = codec->getScanlineDecoder(decodeInfo, NULL, colorPtr, colorCountPtr);
if (NULL == decoder) {
return "Failed to create second scanline decoder.";
}
for (int i = 0; i < numStripes; i += 2) {
// Read a stripe
const int startY = i * stripeHeight;
const int linesToRead = SkTMin(stripeHeight, height - startY);
SkImageGenerator::Result result = decoder->getScanlines(bitmap.getAddr(0, startY),
linesToRead, bitmap.rowBytes());
switch (result) {
case SkImageGenerator::kSuccess:
case SkImageGenerator::kIncompleteInput:
break;
default:
return SkStringPrintf("Cannot get scanlines for %s.", fPath.c_str());
}
// Skip a stripe
const int linesToSkip = SkTMax(0, SkTMin(stripeHeight,
height - (i + 1) * stripeHeight));
result = decoder->skipScanlines(linesToSkip);
switch (result) {
case SkImageGenerator::kSuccess:
case SkImageGenerator::kIncompleteInput:
break;
default:
return SkStringPrintf("Cannot skip scanlines for %s.", fPath.c_str());
}
}
canvas->drawBitmap(bitmap, 0, 0);
}
}
return "";
}
@ -270,14 +352,19 @@ SkISize CodecSrc::size() const {
SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
if (NULL != codec) {
return codec->getInfo().dimensions();
SkISize size = codec->getScaledDimensions(fScale);
return size;
} else {
return SkISize::Make(0, 0);
}
}
Name CodecSrc::name() const {
return SkOSPath::Basename(fPath.c_str());
if (1.0f == fScale) {
return SkOSPath::Basename(fPath.c_str());
} else {
return SkStringPrintf("%s_%.3f", SkOSPath::Basename(fPath.c_str()).c_str(), fScale);
}
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

View File

@ -98,13 +98,14 @@ public:
kNormal_Mode,
kScanline_Mode,
kScanline_Subset_Mode,
kStripe_Mode, // Tests the skipping of scanlines
};
enum DstColorType {
kGetFromCanvas_DstColorType,
kIndex8_Always_DstColorType,
kGrayscale_Always_DstColorType,
};
CodecSrc(Path, Mode, DstColorType);
CodecSrc(Path, Mode, DstColorType, float);
Error draw(SkCanvas*) const override;
SkISize size() const override;
@ -113,6 +114,7 @@ private:
Path fPath;
Mode fMode;
DstColorType fDstColorType;
float fScale;
};