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
This commit is contained in:
parent
dfcba473b0
commit
99f567e617
BIN
resources/index8.png
Normal file
BIN
resources/index8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -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);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,13 @@
|
||||
#define COMPUTE_RESULT_ALPHA \
|
||||
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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
static uint16_t bit_to_rgb565(U8CPU bit) {
|
||||
return bit ? RGB565_WHITE : RGB565_BLACK;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
dst += 8;
|
||||
}
|
||||
bits &= 7;
|
||||
if (bits > 0) {
|
||||
U8CPU mask = *src;
|
||||
do {
|
||||
*dst++ = TRANSFORM((mask >> 7) & 1);
|
||||
mask <<= 1;
|
||||
} while (--bits != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user