Support wbmp that are supported by SkImageDecoder

The wbmp version of SkImageDecoder will support decoding an image where
the second byte can be masked away with 0x9F. Prior to this CL, SkCodec
checked that the entire byte was zero. The SkCodec implementation
appears to be more correct (at least according to Wikipedia [1]), but
it also means we could regress if someone was using an image that did
not quite fit the specification.

[1] https://en.wikipedia.org/wiki/Wireless_Application_Protocol_Bitmap_Format

BUG=skia:3257

Review URL: https://codereview.chromium.org/1473673005
This commit is contained in:
scroggo 2015-11-30 06:25:31 -08:00 committed by Commit bot
parent 0e7029eaef
commit b9a1e34362
2 changed files with 47 additions and 4 deletions

View File

@ -29,6 +29,11 @@ static inline void setup_color_table(SkColorType colorType,
}
}
static bool read_byte(SkStream* stream, uint8_t* data)
{
return stream->read(data, 1) == 1;
}
// http://en.wikipedia.org/wiki/Variable-length_quantity
static bool read_mbf(SkStream* stream, uint64_t* value) {
uint64_t n = 0;
@ -49,11 +54,17 @@ static bool read_mbf(SkStream* stream, uint64_t* value) {
}
static bool read_header(SkStream* stream, SkISize* size) {
uint64_t width, height;
uint16_t data;
if (stream->read(&data, 2) != 2 || data != 0) {
return false;
{
uint8_t data;
if (!read_byte(stream, &data) || data != 0) { // unknown type
return false;
}
if (!read_byte(stream, &data) || (data & 0x9F)) { // skip fixed header
return false;
}
}
uint64_t width, height;
if (!read_mbf(stream, &width) || width > 0xFFFF || !width) {
return false;
}

View File

@ -10,9 +10,11 @@
#include "SkBitmap.h"
#include "SkCodec.h"
#include "SkData.h"
#include "SkImageDecoder.h"
#include "SkMD5.h"
#include "SkRandom.h"
#include "SkStream.h"
#include "SkStreamPriv.h"
#include "SkPngChunkReader.h"
#include "Test.h"
@ -845,3 +847,33 @@ DEF_TEST(Codec_pngChunkReader, r) {
REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen());
}
#endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
// SkCodec's wbmp decoder was initially more restrictive than SkImageDecoder.
// It required the second byte to be zero. But SkImageDecoder allowed a couple
// of bits to be 1 (so long as they do not overlap with 0x9F). Test that
// SkCodec now supports an image with these bits set.
DEF_TEST(Codec_wbmp, r) {
const char* path = "mandrill.wbmp";
SkAutoTDelete<SkStream> stream(resource(path));
if (!stream) {
SkDebugf("Missing resource '%s'\n", path);
return;
}
// Modify the stream to contain a second byte with some bits set.
SkAutoTUnref<SkData> data(SkCopyStreamToData(stream));
uint8_t* writeableData = static_cast<uint8_t*>(data->writable_data());
writeableData[1] = static_cast<uint8_t>(~0x9F);
// SkImageDecoder supports this.
SkBitmap bitmap;
REPORTER_ASSERT(r, SkImageDecoder::DecodeMemory(data->data(), data->size(), &bitmap));
// So SkCodec should, too.
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data));
REPORTER_ASSERT(r, codec);
if (!codec) {
return;
}
test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr);
}