aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2015-08-05 12:58:26 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-05 12:58:26 -0700
commit99f567e617b6c5a81e6b822c30ccb0d357db21fc (patch)
treec119d5f8abfd674533ef2ccb04d9bfa1ec188a0d
parentdfcba473b0462be3ed4babc07b1d50f4fafaeded (diff)
Scanline decoding for wbmp
We are also changing the wbmp to use SkSwizzler. This will allow us to take advantage of the sampling routines that are being implemented in SkSwizzler. The image in this upload came from: https://commons.wikimedia.org/wiki/File:Android_robot.png It is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license. BUG=skia: Review URL: https://codereview.chromium.org/1254483004
-rw-r--r--resources/index8.pngbin0 -> 13418 bytes
-rw-r--r--src/codec/SkCodec.cpp5
-rw-r--r--src/codec/SkCodecPriv.h7
-rw-r--r--src/codec/SkCodec_libpng.cpp2
-rw-r--r--src/codec/SkCodec_wbmp.cpp227
-rw-r--r--src/codec/SkCodec_wbmp.h36
-rw-r--r--src/codec/SkScanlineDecoder.cpp19
-rw-r--r--src/codec/SkSwizzler.cpp102
-rw-r--r--src/codec/SkSwizzler.h2
-rw-r--r--tests/CodexTest.cpp37
10 files changed, 351 insertions, 86 deletions
diff --git a/resources/index8.png b/resources/index8.png
new file mode 100644
index 0000000000..2ff47a3bf4
--- /dev/null
+++ b/resources/index8.png
Binary files differ
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 6ef61b289a..ffe90af539 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -133,10 +133,5 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t
}
SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
- SkASSERT(kIndex_8_SkColorType != info.colorType());
- if (kIndex_8_SkColorType == info.colorType()) {
- return kInvalidConversion;
- }
return this->getPixels(info, pixels, rowBytes, NULL, NULL, NULL);
}
-
diff --git a/src/codec/SkCodecPriv.h b/src/codec/SkCodecPriv.h
index 90b16323a7..0c45fddff1 100644
--- a/src/codec/SkCodecPriv.h
+++ b/src/codec/SkCodecPriv.h
@@ -31,6 +31,13 @@
SkSwizzler::GetResult(zeroAlpha, maxAlpha);
/*
+ * If there is a color table, get a pointer to the colors, otherwise return NULL
+ */
+static const SkPMColor* get_color_ptr(SkColorTable* colorTable) {
+ return NULL != colorTable ? colorTable->readColors() : NULL;
+}
+
+/*
*
* Copy the codec color table back to the client when kIndex8 color type is requested
*
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index d29ca8a2a3..2b9603fd96 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -471,7 +471,7 @@ SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo,
copy_color_table(requestedInfo, fColorTable, ctable, ctableCount);
// Create the swizzler. SkPngCodec retains ownership of the color table.
- const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL;
+ const SkPMColor* colors = get_color_ptr(fColorTable.get());
fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo,
options.fZeroInitialized));
if (!fSwizzler) {
diff --git a/src/codec/SkCodec_wbmp.cpp b/src/codec/SkCodec_wbmp.cpp
index 35ac808219..86dce5cc89 100644
--- a/src/codec/SkCodec_wbmp.cpp
+++ b/src/codec/SkCodec_wbmp.cpp
@@ -6,10 +6,29 @@
*/
#include "SkCodec.h"
+#include "SkCodecPriv.h"
#include "SkColorPriv.h"
+#include "SkColorTable.h"
#include "SkStream.h"
#include "SkCodec_wbmp.h"
+// Each bit represents a pixel, so width is actually a number of bits.
+// A row will always be stored in bytes, so we round width up to the
+// nearest multiple of 8 to get the number of bits actually in the row.
+// We then divide by 8 to convert to bytes.
+static inline size_t get_src_row_bytes(int width) {
+ return SkAlign8(width) >> 3;
+}
+
+static inline void setup_color_table(SkColorType colorType,
+ SkPMColor* colorPtr, int* colorCount) {
+ if (kIndex_8_SkColorType == colorType) {
+ colorPtr[0] = SK_ColorBLACK;
+ colorPtr[1] = SK_ColorWHITE;
+ *colorCount = 2;
+ }
+}
+
// http://en.wikipedia.org/wiki/Variable-length_quantity
static bool read_mbf(SkStream* stream, uint64_t* value) {
uint64_t n = 0;
@@ -38,7 +57,7 @@ static bool read_header(SkStream* stream, SkISize* size) {
if (!read_mbf(stream, &width) || width > 0xFFFF || !width) {
return false;
}
- if (!read_mbf(stream, &height) || width > 0xFFFF || !height) {
+ if (!read_mbf(stream, &height) || height > 0xFFFF || !height) {
return false;
}
if (size) {
@@ -47,70 +66,59 @@ static bool read_header(SkStream* stream, SkISize* size) {
return true;
}
-#define BLACK SkPackARGB32NoCheck(0xFF, 0, 0, 0)
-#define WHITE SkPackARGB32NoCheck(0xFF, 0xFF, 0xFF, 0xFF)
-
-#define GRAYSCALE_BLACK 0
-#define GRAYSCALE_WHITE 0xFF
-
-#define RGB565_BLACK 0
-#define RGB565_WHITE 0xFFFF
-
-static SkPMColor bit_to_pmcolor(U8CPU bit) { return bit ? WHITE : BLACK; }
-
-static uint8_t bit_to_bit(U8CPU bit) { return bit; }
-
-static uint8_t bit_to_grayscale(U8CPU bit) {
- return bit ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
+bool SkWbmpCodec::handleRewind() {
+ SkCodec::RewindState rewindState = this->rewindIfNeeded();
+ if (rewindState == kCouldNotRewind_RewindState) {
+ return false;
+ } else if (rewindState == kRewound_RewindState) {
+ if (!read_header(this->stream(), NULL)) {
+ return false;
+ }
+ }
+ return true;
}
-static uint16_t bit_to_rgb565(U8CPU bit) {
- return bit ? RGB565_WHITE : RGB565_BLACK;
-}
+SkSwizzler* SkWbmpCodec::initializeSwizzler(const SkImageInfo& info,
+ const SkPMColor* ctable, const Options& opts) {
+ // TODO (msarett): Reenable support for 565 if it is desired
+ // skbug.com/3683
-typedef void (*ExpandProc)(uint8_t*, const uint8_t*, int);
-
-// TODO(halcanary): Add this functionality (grayscale and indexed output) to
-// SkSwizzler and use it here.
-template <typename T, T (*TRANSFORM)(U8CPU)>
-static void expand_bits_to_T(uint8_t* dstptr, const uint8_t* src, int bits) {
- T* dst = reinterpret_cast<T*>(dstptr);
- int bytes = bits >> 3;
- for (int i = 0; i < bytes; i++) {
- U8CPU mask = *src++;
- for (int j = 0; j < 8; j++) {
- dst[j] = TRANSFORM((mask >> (7 - j)) & 1);
- }
- dst += 8;
+ // Create the swizzler based on the desired color type
+ switch (info.colorType()) {
+ case kIndex_8_SkColorType:
+ case kN32_SkColorType:
+ case kGray_8_SkColorType:
+ return SkSwizzler::CreateSwizzler(
+ SkSwizzler::kBit, ctable, info, opts.fZeroInitialized);
+ default:
+ return NULL;
}
- bits &= 7;
- if (bits > 0) {
- U8CPU mask = *src;
- do {
- *dst++ = TRANSFORM((mask >> 7) & 1);
- mask <<= 1;
- } while (--bits != 0);
+}
+
+SkCodec::Result SkWbmpCodec::readRow(uint8_t* row) {
+ if (this->stream()->read(row, fSrcRowBytes) != fSrcRowBytes) {
+ return kIncompleteInput;
}
+ return kSuccess;
}
SkWbmpCodec::SkWbmpCodec(const SkImageInfo& info, SkStream* stream)
- : INHERITED(info, stream) {}
+ : INHERITED(info, stream)
+ , fSrcRowBytes(get_src_row_bytes(this->getInfo().width()))
+{}
SkEncodedFormat SkWbmpCodec::onGetEncodedFormat() const {
return kWBMP_SkEncodedFormat;
}
SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info,
- void* pixels,
+ void* dst,
size_t rowBytes,
const Options& options,
SkPMColor ctable[],
int* ctableCount) {
- SkCodec::RewindState rewindState = this->rewindIfNeeded();
- if (rewindState == kCouldNotRewind_RewindState) {
+ if (!this->handleRewind()) {
return kCouldNotRewind;
- } else if (rewindState == kRewound_RewindState) {
- (void)read_header(this->stream(), NULL);
}
if (options.fSubset) {
// Subsets are not supported.
@@ -119,36 +127,28 @@ SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info,
if (info.dimensions() != this->getInfo().dimensions()) {
return kInvalidScale;
}
- ExpandProc proc = NULL;
- switch (info.colorType()) {
- case kGray_8_SkColorType:
- proc = expand_bits_to_T<uint8_t, bit_to_grayscale>;
- break;
- case kN32_SkColorType:
- proc = expand_bits_to_T<SkPMColor, bit_to_pmcolor>;
- break;
- case kIndex_8_SkColorType:
- ctable[0] = BLACK;
- ctable[1] = WHITE;
- *ctableCount = 2;
- proc = expand_bits_to_T<uint8_t, bit_to_bit>;
- break;
- case kRGB_565_SkColorType:
- proc = expand_bits_to_T<uint16_t, bit_to_rgb565>;
- break;
- default:
- return kInvalidConversion;
+
+ // Prepare a color table if necessary
+ setup_color_table(info.colorType(), ctable, ctableCount);
+
+
+ // Initialize the swizzler
+ SkAutoTDelete<SkSwizzler> swizzler(this->initializeSwizzler(info, ctable, options));
+ if (NULL == swizzler.get()) {
+ return kInvalidConversion;
}
+
+ // Perform the decode
SkISize size = info.dimensions();
- uint8_t* dst = static_cast<uint8_t*>(pixels);
- size_t srcRowBytes = SkAlign8(size.width()) >> 3;
- SkAutoTMalloc<uint8_t> src(srcRowBytes);
+ SkAutoTMalloc<uint8_t> src(fSrcRowBytes);
+ void* dstRow = dst;
for (int y = 0; y < size.height(); ++y) {
- if (this->stream()->read(src.get(), srcRowBytes) != srcRowBytes) {
- return kIncompleteInput;
+ Result rowResult = this->readRow(src.get());
+ if (kSuccess != rowResult) {
+ return rowResult;
}
- proc(dst, src.get(), size.width());
- dst += rowBytes;
+ swizzler->swizzle(dstRow, src.get());
+ dstRow = SkTAddOffset<void>(dstRow, rowBytes);
}
return kSuccess;
}
@@ -163,8 +163,85 @@ SkCodec* SkWbmpCodec::NewFromStream(SkStream* stream) {
if (!read_header(stream, &size)) {
return NULL;
}
- SkImageInfo info =
- SkImageInfo::Make(size.width(), size.height(), kGray_8_SkColorType,
- kOpaque_SkAlphaType);
+ SkImageInfo info = SkImageInfo::Make(size.width(), size.height(),
+ kGray_8_SkColorType, kOpaque_SkAlphaType);
return SkNEW_ARGS(SkWbmpCodec, (info, streamDeleter.detach()));
}
+
+class SkWbmpScanlineDecoder : public SkScanlineDecoder {
+public:
+ /*
+ * Takes ownership of all pointer paramters.
+ */
+ SkWbmpScanlineDecoder(SkWbmpCodec* codec)
+ : INHERITED(codec->getInfo())
+ , fCodec(codec)
+ , fColorTable(NULL)
+ , fSwizzler(NULL)
+ , fSrcBuffer(codec->fSrcRowBytes)
+ {}
+
+ SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) override {
+ void* dstRow = dst;
+ for (int y = 0; y < count; ++y) {
+ SkCodec::Result rowResult = fCodec->readRow(fSrcBuffer.get());
+ if (SkCodec::kSuccess != rowResult) {
+ return rowResult;
+ }
+ fSwizzler->swizzle(dstRow, fSrcBuffer.get());
+ dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
+ }
+ return SkCodec::kSuccess;
+ }
+
+ SkCodec::Result onStart(const SkImageInfo& dstInfo,
+ const SkCodec::Options& options, SkPMColor inputColorTable[],
+ int* inputColorCount) {
+ if (!fCodec->handleRewind()) {
+ return SkCodec::kCouldNotRewind;
+ }
+ if (options.fSubset) {
+ // Subsets are not supported.
+ return SkCodec::kUnimplemented;
+ }
+ if (dstInfo.dimensions() != this->getInfo().dimensions()) {
+ return SkCodec::kInvalidScale;
+ }
+
+ // Fill in the color table
+ setup_color_table(dstInfo.colorType(), inputColorTable, inputColorCount);
+
+ // Copy the color table to a pointer that can be owned by the scanline decoder
+ if (kIndex_8_SkColorType == dstInfo.colorType()) {
+ fColorTable.reset(SkNEW_ARGS(SkColorTable, (inputColorTable, 2)));
+ }
+
+ // Initialize the swizzler
+ fSwizzler.reset(fCodec->initializeSwizzler(dstInfo,
+ get_color_ptr(fColorTable.get()), options));
+ if (NULL == fSwizzler.get()) {
+ return SkCodec::kInvalidInput;
+ }
+
+ return SkCodec::kSuccess;
+ }
+
+private:
+ SkAutoTDelete<SkWbmpCodec> fCodec;
+ SkAutoTUnref<SkColorTable> fColorTable;
+ SkAutoTDelete<SkSwizzler> fSwizzler;
+ SkAutoTMalloc<uint8_t> fSrcBuffer;
+
+ typedef SkScanlineDecoder INHERITED;
+};
+
+SkScanlineDecoder* SkWbmpCodec::NewSDFromStream(SkStream* stream) {
+ SkAutoTDelete<SkWbmpCodec> codec(static_cast<SkWbmpCodec*>(
+ SkWbmpCodec::NewFromStream(stream)));
+ if (!codec) {
+ return NULL;
+ }
+
+ // Return the new scanline decoder
+ return SkNEW_ARGS(SkWbmpScanlineDecoder, (codec.detach()));
+}
diff --git a/src/codec/SkCodec_wbmp.h b/src/codec/SkCodec_wbmp.h
index fece249728..cec398d34b 100644
--- a/src/codec/SkCodec_wbmp.h
+++ b/src/codec/SkCodec_wbmp.h
@@ -9,17 +9,53 @@
#define SkCodec_wbmp_DEFINED
#include "SkCodec.h"
+#include "SkScanlineDecoder.h"
+#include "SkSwizzler.h"
class SkWbmpCodec final : public SkCodec {
public:
static bool IsWbmp(SkStream*);
+
+ /*
+ * Assumes IsWbmp was called and returned true
+ * Creates a wbmp codec
+ * Takes ownership of the stream
+ */
static SkCodec* NewFromStream(SkStream*);
+
+ /*
+ * Assumes IsWbmp was called and returned true
+ * Creates a wbmp scanline decoder
+ * Takes ownership of the stream
+ */
+ static SkScanlineDecoder* NewSDFromStream(SkStream*);
protected:
SkEncodedFormat onGetEncodedFormat() const override;
Result onGetPixels(const SkImageInfo&, void*, size_t,
const Options&, SkPMColor[], int*) override;
private:
+
+ /*
+ * Calls rewindIfNeeded and returns true if the decoder can continue
+ */
+ bool handleRewind();
+
+ /*
+ * Returns a swizzler on success, NULL on failure
+ */
+ SkSwizzler* initializeSwizzler(const SkImageInfo& info, const SkPMColor* ctable,
+ const Options& opts);
+
+ /*
+ * Read a src row from the encoded stream
+ */
+ Result readRow(uint8_t* row);
+
SkWbmpCodec(const SkImageInfo&, SkStream*);
+
+ const size_t fSrcRowBytes;
+
+ friend class SkWbmpScanlineDecoder;
typedef SkCodec INHERITED;
};
diff --git a/src/codec/SkScanlineDecoder.cpp b/src/codec/SkScanlineDecoder.cpp
index 00c020c7c2..851e7e71d0 100644
--- a/src/codec/SkScanlineDecoder.cpp
+++ b/src/codec/SkScanlineDecoder.cpp
@@ -7,6 +7,7 @@
#include "SkScanlineDecoder.h"
#include "SkCodec_libpng.h"
+#include "SkCodec_wbmp.h"
#include "SkCodecPriv.h"
#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
#include "SkJpegCodec.h"
@@ -22,6 +23,7 @@ static const DecoderProc gDecoderProcs[] = {
#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
{ SkJpegCodec::IsJpeg, SkJpegCodec::NewSDFromStream },
#endif
+ { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewSDFromStream },
};
SkScanlineDecoder* SkScanlineDecoder::NewFromStream(SkStream* stream) {
@@ -66,6 +68,19 @@ SkScanlineDecoder* SkScanlineDecoder::NewFromData(SkData* data) {
SkCodec::Result SkScanlineDecoder::start(const SkImageInfo& dstInfo,
const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
+ // Ensure that valid color ptrs are passed in for kIndex8 color type
+ if (kIndex_8_SkColorType == dstInfo.colorType()) {
+ if (NULL == ctable || NULL == ctableCount) {
+ return SkCodec::kInvalidParameters;
+ }
+ } else {
+ if (ctableCount) {
+ *ctableCount = 0;
+ }
+ ctableCount = NULL;
+ ctable = NULL;
+ }
+
// Set options.
SkCodec::Options optsStorage;
if (NULL == options) {
@@ -83,10 +98,6 @@ SkCodec::Result SkScanlineDecoder::start(const SkImageInfo& dstInfo,
}
SkCodec::Result SkScanlineDecoder::start(const SkImageInfo& dstInfo) {
- SkASSERT(kIndex_8_SkColorType != dstInfo.colorType());
- if (kIndex_8_SkColorType == dstInfo.colorType()) {
- return SkCodec::kInvalidConversion;
- }
return this->start(dstInfo, NULL, NULL, NULL);
}
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp
index 998fbeb851..f8e89c7acb 100644
--- a/src/codec/SkSwizzler.cpp
+++ b/src/codec/SkSwizzler.cpp
@@ -19,6 +19,93 @@ SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
}
+// kBit
+// These routines exclusively choose between white and black
+
+#define GRAYSCALE_BLACK 0
+#define GRAYSCALE_WHITE 0xFF
+
+static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale(
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+ int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
+ uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
+
+ // Determine how many full bytes are in the row
+ int bytesInRow = width >> 3;
+ int i;
+ for (i = 0; i < bytesInRow; i++) {
+ U8CPU currByte = src[i];
+ for (int j = 0; j < 8; j++) {
+ dst[j] = ((currByte >> (7 - j)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
+ }
+ dst += 8;
+ }
+
+ // Finish the remaining bits
+ width &= 7;
+ U8CPU currByte = src[i];
+ for (int j = 0; j < width; j++) {
+ dst[j] = ((currByte >> 7) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
+ currByte <<= 1;
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+#undef GRAYSCALE_BLACK
+#undef GRAYSCALE_WHITE
+
+static SkSwizzler::ResultAlpha swizzle_bit_to_index(
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+ int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
+ uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
+
+ // Determine how many full bytes are in the row
+ int bytesInRow = width >> 3;
+ int i;
+ for (i = 0; i < bytesInRow; i++) {
+ U8CPU currByte = src[i];
+ for (int j = 0; j < 8; j++) {
+ dst[j] = (currByte >> (7 - j)) & 1;
+ }
+ dst += 8;
+ }
+
+ // Finish the remaining bits
+ width &= 7;
+ U8CPU currByte = src[i];
+ for (int j = 0; j < width; j++) {
+ dst[j] = ((currByte >> 7) & 1);
+ currByte <<= 1;
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_bit_to_n32(
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
+ int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) {
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
+
+ // Determine how many full bytes are in the row
+ int bytesInRow = width >> 3;
+ int i;
+ for (i = 0; i < bytesInRow; i++) {
+ U8CPU currByte = src[i];
+ for (int j = 0; j < 8; j++) {
+ dst[j] = ((currByte >> (7 - j)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
+ }
+ dst += 8;
+ }
+
+ // Finish the remaining bits
+ width &= 7;
+ U8CPU currByte = src[i];
+ for (int j = 0; j < width; j++) {
+ dst[j] = ((currByte >> 7) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
+ currByte <<= 1;
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
// kIndex1, kIndex2, kIndex4
static SkSwizzler::ResultAlpha swizzle_small_index_to_index(
@@ -284,6 +371,21 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
}
RowProc proc = NULL;
switch (sc) {
+ case kBit:
+ switch (info.colorType()) {
+ case kN32_SkColorType:
+ proc = &swizzle_bit_to_n32;
+ break;
+ case kIndex_8_SkColorType:
+ proc = &swizzle_bit_to_index;
+ break;
+ case kGray_8_SkColorType:
+ proc = &swizzle_bit_to_grayscale;
+ break;
+ default:
+ break;
+ }
+ break;
case kIndex1:
case kIndex2:
case kIndex4:
diff --git a/src/codec/SkSwizzler.h b/src/codec/SkSwizzler.h
index 76ca74877a..2fab7f66b6 100644
--- a/src/codec/SkSwizzler.h
+++ b/src/codec/SkSwizzler.h
@@ -19,6 +19,7 @@ public:
*/
enum SrcConfig {
kUnknown, // Invalid type.
+ kBit, // A single bit to distinguish between white and black
kGray,
kIndex1,
kIndex2,
@@ -76,6 +77,7 @@ public:
*/
static int BitsPerPixel(SrcConfig sc) {
switch (sc) {
+ case kBit:
case kIndex1:
return 1;
case kIndex2:
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp
index 1dd64d9a6d..b7f1584a16 100644
--- a/tests/CodexTest.cpp
+++ b/tests/CodexTest.cpp
@@ -152,7 +152,7 @@ static void check(skiatest::Reporter* r,
DEF_TEST(Codec, r) {
// WBMP
- check(r, "mandrill.wbmp", SkISize::Make(512, 512), false, false);
+ check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false);
// WEBP
check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true);
@@ -289,3 +289,38 @@ DEF_TEST(Codec_Empty, r) {
test_empty(r, "empty_images/zero-width.wbmp");
test_empty(r, "empty_images/zero-height.wbmp");
}
+
+static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
+ SkAutoTDelete<SkStream> stream(resource(path));
+ if (!stream) {
+ SkDebugf("Missing resource '%s'\n", path);
+ return;
+ }
+ SkAutoTDelete<SkScanlineDecoder> decoder(SkScanlineDecoder::NewFromStream(
+ stream.detach()));
+
+ // This should return kSuccess because kIndex8 is supported.
+ SkPMColor colorStorage[256];
+ int colorCount;
+ SkCodec::Result result = decoder->start(
+ decoder->getInfo().makeColorType(kIndex_8_SkColorType), NULL, colorStorage, &colorCount);
+ REPORTER_ASSERT(r, SkCodec::kSuccess == result);
+ // The rest of the test is uninteresting if kIndex8 is not supported
+ if (SkCodec::kSuccess != result) {
+ return;
+ }
+
+ // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
+ // colorPtr and a valid colorCountPtr.
+ result = decoder->start(
+ decoder->getInfo().makeColorType(kIndex_8_SkColorType), NULL, NULL, NULL);
+ REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
+ result = decoder->start(
+ decoder->getInfo().makeColorType(kIndex_8_SkColorType));
+ REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
+}
+
+DEF_TEST(Codec_Params, r) {
+ test_invalid_parameters(r, "index8.png");
+ test_invalid_parameters(r, "mandrill.wbmp");
+}