Chromium Code Reviews| Index: src/images/SkImageDecoder_pkm.cpp |
| diff --git a/src/images/SkImageDecoder_pkm.cpp b/src/images/SkImageDecoder_pkm.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..70fcaefb0ed0271ef82ff528e0775f5c459c2d11 |
| --- /dev/null |
| +++ b/src/images/SkImageDecoder_pkm.cpp |
| @@ -0,0 +1,123 @@ |
| +/* |
| + * Copyright 2014 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "SkColorPriv.h" |
| +#include "SkImageDecoder.h" |
| +#include "SkStream.h" |
| +#include "SkStreamHelpers.h" |
| +#include "SkTypes.h" |
| + |
| +#include "etc1.h" |
| + |
| +class SkPKMImageDecoder : public SkImageDecoder { |
| +public: |
| + SkPKMImageDecoder() { } |
| + |
| + virtual Format getFormat() const SK_OVERRIDE { |
| + return kPKM_Format; |
| + } |
| + |
| +protected: |
| + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| + |
| +private: |
| + typedef SkImageDecoder INHERITED; |
| +}; |
| + |
| +///////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +bool SkPKMImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) |
| +{ |
|
reed1
2014/05/22 17:46:24
nit: function(params) {
krajcevski
2014/05/22 17:52:57
Done.
|
| + SkAutoMalloc autoMal; |
| + const size_t length = CopyStreamToStorage(&autoMal, stream); |
| + if (0 == length) { |
| + return false; |
| + } |
| + |
| + unsigned char* buf = (unsigned char*)autoMal.get(); |
| + |
| + // Make sure original PKM header is there... |
| + SkASSERT(etc1_pkm_is_valid(buf)); |
| + |
| + const unsigned short width = etc1_pkm_get_width(buf); |
| + const unsigned short height = etc1_pkm_get_height(buf); |
| + |
| + // should we allow the Chooser (if present) to pick a config for us??? |
| + if (!this->chooseFromOneChoice(SkBitmap::kARGB_8888_Config, width, height)) { |
| + return false; |
| + } |
| + |
| + bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0, kOpaque_SkAlphaType); |
| + if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
| + return true; |
| + } |
| + |
| + if (!this->allocPixelRef(bm, NULL)) { |
| + return false; |
| + } |
| + |
| + // Lock the pixels, since we're about to write to them... |
| + SkAutoLockPixels alp(*bm); |
| + |
| + // Advance buffer past the header |
| + buf += ETC_PKM_HEADER_SIZE; |
| + |
| + // ETC1 Data is encoded as RGB pixels, so we should extract it as such |
| + int nPixels = width * height; |
| + SkAutoMalloc outRGBData(nPixels * 3); |
| + etc1_byte *outRGBDataPtr = reinterpret_cast<etc1_byte *>(outRGBData.get()); |
| + |
| + // Decode ETC1 |
| + if (etc1_decode_image(buf, outRGBDataPtr, width, height, 3, width*3)) { |
| + return false; |
| + } |
| + |
| + // Set each of the pixels... |
| + const uint8_t *src = reinterpret_cast<uint8_t *>(outRGBDataPtr); |
| + uint8_t *dst = reinterpret_cast<uint8_t *>(bm->getPixels()); |
| + for (int i = 0; i < width*height; ++i) { |
| + *dst++ = src[2]; // B |
| + *dst++ = src[1]; // G |
| + *dst++ = src[0]; // R |
| + *dst++ = 0xFF; // Opaque alpha... |
| + src += 3; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +///////////////////////////////////////////////////////////////////////////////////////// |
| +DEFINE_DECODER_CREATOR(PKMImageDecoder); |
| +///////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +static bool is_pkm(SkStreamRewindable* stream) { |
| + // Read the PKM header and make sure it's valid. |
| + unsigned char buf[ETC_PKM_HEADER_SIZE]; |
| + if (stream->read((void*)buf, ETC_PKM_HEADER_SIZE) != ETC_PKM_HEADER_SIZE) { |
| + return false; |
| + } |
| + |
| + return etc1_pkm_is_valid(buf); |
| +} |
| + |
| +static SkImageDecoder* sk_libpkm_dfactory(SkStreamRewindable* stream) { |
| + if (is_pkm(stream)) { |
| + return SkNEW(SkPKMImageDecoder); |
| + } |
| + return NULL; |
| +} |
| + |
| +static SkImageDecoder_DecodeReg gReg(sk_libpkm_dfactory); |
| + |
| +static SkImageDecoder::Format get_format_pkm(SkStreamRewindable* stream) { |
| + if (is_pkm(stream)) { |
| + return SkImageDecoder::kPKM_Format; |
| + } |
| + return SkImageDecoder::kUnknown_Format; |
| +} |
| + |
| +static SkImageDecoder_FormatReg gFormatReg(get_format_pkm); |