diff options
author | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-05-22 18:40:29 +0000 |
---|---|---|
committer | robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-05-22 18:40:29 +0000 |
commit | 8cf81e0f4fa2a8054ac4cea1e7490028809cb893 (patch) | |
tree | fc1688c45056891962dc6676560eac15c9126ea0 /src/images/SkImageDecoder_pkm.cpp | |
parent | 0be2d8354b0c99bd099c4c6dd78a7fcb69955fa4 (diff) | |
download | platform_external_skqp-8cf81e0f4fa2a8054ac4cea1e7490028809cb893.tar.gz platform_external_skqp-8cf81e0f4fa2a8054ac4cea1e7490028809cb893.tar.bz2 platform_external_skqp-8cf81e0f4fa2a8054ac4cea1e7490028809cb893.zip |
Simple PKM image decoder.
https://codereview.chromium.org/292663011/
git-svn-id: http://skia.googlecode.com/svn/trunk@14852 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/images/SkImageDecoder_pkm.cpp')
-rw-r--r-- | src/images/SkImageDecoder_pkm.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/images/SkImageDecoder_pkm.cpp b/src/images/SkImageDecoder_pkm.cpp new file mode 100644 index 0000000000..07f162b4e9 --- /dev/null +++ b/src/images/SkImageDecoder_pkm.cpp @@ -0,0 +1,122 @@ +/* + * 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) { + 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 SkToBool(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); |