1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/images/SkImageDecoder_wbmp.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,173 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkImageDecoder.h" 1.14 +#include "SkColor.h" 1.15 +#include "SkColorPriv.h" 1.16 +#include "SkMath.h" 1.17 +#include "SkStream.h" 1.18 +#include "SkTemplates.h" 1.19 +#include "SkUtils.h" 1.20 + 1.21 +class SkWBMPImageDecoder : public SkImageDecoder { 1.22 +public: 1.23 + virtual Format getFormat() const SK_OVERRIDE { 1.24 + return kWBMP_Format; 1.25 + } 1.26 + 1.27 +protected: 1.28 + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 1.29 + 1.30 +private: 1.31 + typedef SkImageDecoder INHERITED; 1.32 +}; 1.33 + 1.34 +static bool read_byte(SkStream* stream, uint8_t* data) 1.35 +{ 1.36 + return stream->read(data, 1) == 1; 1.37 +} 1.38 + 1.39 +static bool read_mbf(SkStream* stream, int* value) 1.40 +{ 1.41 + int n = 0; 1.42 + uint8_t data; 1.43 + do { 1.44 + if (!read_byte(stream, &data)) { 1.45 + return false; 1.46 + } 1.47 + n = (n << 7) | (data & 0x7F); 1.48 + } while (data & 0x80); 1.49 + 1.50 + *value = n; 1.51 + return true; 1.52 +} 1.53 + 1.54 +struct wbmp_head { 1.55 + int fWidth; 1.56 + int fHeight; 1.57 + 1.58 + bool init(SkStream* stream) 1.59 + { 1.60 + uint8_t data; 1.61 + 1.62 + if (!read_byte(stream, &data) || data != 0) { // unknown type 1.63 + return false; 1.64 + } 1.65 + if (!read_byte(stream, &data) || (data & 0x9F)) { // skip fixed header 1.66 + return false; 1.67 + } 1.68 + if (!read_mbf(stream, &fWidth) || (unsigned)fWidth > 0xFFFF) { 1.69 + return false; 1.70 + } 1.71 + if (!read_mbf(stream, &fHeight) || (unsigned)fHeight > 0xFFFF) { 1.72 + return false; 1.73 + } 1.74 + return fWidth != 0 && fHeight != 0; 1.75 + } 1.76 +}; 1.77 + 1.78 +static void expand_bits_to_bytes(uint8_t dst[], const uint8_t src[], int bits) 1.79 +{ 1.80 + int bytes = bits >> 3; 1.81 + 1.82 + for (int i = 0; i < bytes; i++) { 1.83 + unsigned mask = *src++; 1.84 + dst[0] = (mask >> 7) & 1; 1.85 + dst[1] = (mask >> 6) & 1; 1.86 + dst[2] = (mask >> 5) & 1; 1.87 + dst[3] = (mask >> 4) & 1; 1.88 + dst[4] = (mask >> 3) & 1; 1.89 + dst[5] = (mask >> 2) & 1; 1.90 + dst[6] = (mask >> 1) & 1; 1.91 + dst[7] = (mask >> 0) & 1; 1.92 + dst += 8; 1.93 + } 1.94 + 1.95 + bits &= 7; 1.96 + if (bits > 0) { 1.97 + unsigned mask = *src; 1.98 + do { 1.99 + *dst++ = (mask >> 7) & 1;; 1.100 + mask <<= 1; 1.101 + } while (--bits != 0); 1.102 + } 1.103 +} 1.104 + 1.105 +bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, 1.106 + Mode mode) 1.107 +{ 1.108 + wbmp_head head; 1.109 + 1.110 + if (!head.init(stream)) { 1.111 + return false; 1.112 + } 1.113 + 1.114 + int width = head.fWidth; 1.115 + int height = head.fHeight; 1.116 + 1.117 + decodedBitmap->setConfig(SkBitmap::kIndex8_Config, width, height, 0, 1.118 + kOpaque_SkAlphaType); 1.119 + 1.120 + if (SkImageDecoder::kDecodeBounds_Mode == mode) { 1.121 + return true; 1.122 + } 1.123 + 1.124 + const SkPMColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; 1.125 + SkColorTable* ct = SkNEW_ARGS(SkColorTable, (colors, 2)); 1.126 + SkAutoUnref aur(ct); 1.127 + 1.128 + if (!this->allocPixelRef(decodedBitmap, ct)) { 1.129 + return false; 1.130 + } 1.131 + 1.132 + SkAutoLockPixels alp(*decodedBitmap); 1.133 + 1.134 + uint8_t* dst = decodedBitmap->getAddr8(0, 0); 1.135 + // store the 1-bit valuess at the end of our pixels, so we won't stomp 1.136 + // on them before we're read them. Just trying to avoid a temp allocation 1.137 + size_t srcRB = SkAlign8(width) >> 3; 1.138 + size_t srcSize = height * srcRB; 1.139 + uint8_t* src = dst + decodedBitmap->getSize() - srcSize; 1.140 + if (stream->read(src, srcSize) != srcSize) { 1.141 + return false; 1.142 + } 1.143 + 1.144 + for (int y = 0; y < height; y++) 1.145 + { 1.146 + expand_bits_to_bytes(dst, src, width); 1.147 + dst += decodedBitmap->rowBytes(); 1.148 + src += srcRB; 1.149 + } 1.150 + 1.151 + return true; 1.152 +} 1.153 + 1.154 +/////////////////////////////////////////////////////////////////////////////// 1.155 +DEFINE_DECODER_CREATOR(WBMPImageDecoder); 1.156 +/////////////////////////////////////////////////////////////////////////////// 1.157 + 1.158 +static SkImageDecoder* sk_wbmp_dfactory(SkStreamRewindable* stream) { 1.159 + wbmp_head head; 1.160 + 1.161 + if (head.init(stream)) { 1.162 + return SkNEW(SkWBMPImageDecoder); 1.163 + } 1.164 + return NULL; 1.165 +} 1.166 + 1.167 +static SkImageDecoder::Format get_format_wbmp(SkStreamRewindable* stream) { 1.168 + wbmp_head head; 1.169 + if (head.init(stream)) { 1.170 + return SkImageDecoder::kWBMP_Format; 1.171 + } 1.172 + return SkImageDecoder::kUnknown_Format; 1.173 +} 1.174 + 1.175 +static SkImageDecoder_DecodeReg gDReg(sk_wbmp_dfactory); 1.176 +static SkImageDecoder_FormatReg gFormatReg(get_format_wbmp);