skia2/tests/WebpTest.cpp
Leon Scroggins 23cbb99c8e Fix blending bug in animated webp decodes
Bug: webp:490

Depending on the encoded image, SkWebpCodec may need to blend the
the output from libwebp with the prior frame. It does so using the
method blend_line, which expects the libwebp output to be unpremul.

Prior to this commit, SkWebpCodec sometimes told libwebp to premultiply,
and then passed that premultiplied data to blend_line, which
premultiplied again.

Use webpInfo's alphaType to decide whether to premultiply. Consolidate
choosing its alphaType into one block. The functional difference is that
if (blendWithPrevFrame), we no longer premul if the dst is kPremul.

Move declaration of webDst to where it's used.

Add a test.

Change-Id: Ic0cfb4d918c2ab434c6787ed5a532c4d1e67fa17
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/342618
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Derek Sollenberger <djsollen@google.com>
Auto-Submit: Leon Scroggins <scroggo@google.com>
2020-12-10 16:24:08 +00:00

60 lines
2.3 KiB
C++

/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/codec/SkCodec.h"
#include "tests/Test.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
DEF_TEST(WebpCodecBlend, r) {
const char* path = "images/blendBG.webp";
auto codec = SkCodec::MakeFromData(GetResourceAsData(path));
if (!codec) {
ERRORF(r, "Failed to open/decode %s", path);
return;
}
// Previously, a bug in SkWebpCodec resulted in different output depending
// on whether kPremul or kOpaque SkAlphaType was passed to getPixels().
// Decode each frame twice, once with kPremul and once with kOpaque if the
// frame is opaque, and verify they look the same.
auto premulInfo = codec->getInfo().makeAlphaType(kPremul_SkAlphaType);
SkBitmap premulBm, changeBm;
premulBm.allocPixels(premulInfo);
changeBm.allocPixels(premulInfo); // The SkBitmap's SkAlphaType is unrelated to the bug.
for (int i = 0; i < codec->getFrameCount(); i++) {
SkCodec::Options options;
options.fFrameIndex = i;
auto result = codec->getPixels(premulBm.pixmap(), &options);
if (result != SkCodec::kSuccess) {
ERRORF(r, "Failed to decode %s frame %i (premul) - error %s", path, i,
SkCodec::ResultToString(result));
return;
}
SkCodec::FrameInfo frameInfo;
if (!codec->getFrameInfo(i, &frameInfo)) {
ERRORF(r, "Failed to getFrameInfo for %s frame %i", path, i);
return;
}
auto alphaType = frameInfo.fAlphaType == kOpaque_SkAlphaType ? kOpaque_SkAlphaType
: kPremul_SkAlphaType;
result = codec->getPixels(premulInfo.makeAlphaType(alphaType), changeBm.getPixels(),
changeBm.rowBytes(), &options);
if (result != SkCodec::kSuccess) {
ERRORF(r, "Failed to decode %s frame %i (change) - error %s", path, i,
SkCodec::ResultToString(result));
return;
}
REPORTER_ASSERT(r, ToolUtils::equal_pixels(premulBm, changeBm), "%s frame %i does not match"
" with mismatched SkAlphaType", path, i);
}
}