OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCodec.h" | 8 #include "SkCodec.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 static uint8_t bit_to_bit(U8CPU bit) { return bit; } | 61 static uint8_t bit_to_bit(U8CPU bit) { return bit; } |
62 | 62 |
63 static uint8_t bit_to_grayscale(U8CPU bit) { | 63 static uint8_t bit_to_grayscale(U8CPU bit) { |
64 return bit ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; | 64 return bit ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; |
65 } | 65 } |
66 | 66 |
67 static uint16_t bit_to_rgb565(U8CPU bit) { | 67 static uint16_t bit_to_rgb565(U8CPU bit) { |
68 return bit ? RGB565_WHITE : RGB565_BLACK; | 68 return bit ? RGB565_WHITE : RGB565_BLACK; |
69 } | 69 } |
70 | 70 |
71 typedef void (*ExpandProc)(uint8_t*, const uint8_t*, int); | |
72 | |
73 // TODO(halcanary): Add this functionality (grayscale and indexed output) to | 71 // TODO(halcanary): Add this functionality (grayscale and indexed output) to |
74 // SkSwizzler and use it here. | 72 // SkSwizzler and use it here. |
75 template <typename T, T (*TRANSFORM)(U8CPU)> | 73 template <typename T, T (*TRANSFORM)(U8CPU)> |
76 static void expand_bits_to_T(uint8_t* dstptr, const uint8_t* src, int bits) { | 74 static void expand_bits_to_T(uint8_t* dstptr, const uint8_t* src, int bits) { |
77 T* dst = reinterpret_cast<T*>(dstptr); | 75 T* dst = reinterpret_cast<T*>(dstptr); |
78 int bytes = bits >> 3; | 76 int bytes = bits >> 3; |
79 for (int i = 0; i < bytes; i++) { | 77 for (int i = 0; i < bytes; i++) { |
80 U8CPU mask = *src++; | 78 U8CPU mask = *src++; |
81 for (int j = 0; j < 8; j++) { | 79 for (int j = 0; j < 8; j++) { |
82 dst[j] = TRANSFORM((mask >> (7 - j)) & 1); | 80 dst[j] = TRANSFORM((mask >> (7 - j)) & 1); |
83 } | 81 } |
84 dst += 8; | 82 dst += 8; |
85 } | 83 } |
86 bits &= 7; | 84 bits &= 7; |
87 if (bits > 0) { | 85 if (bits > 0) { |
88 U8CPU mask = *src; | 86 U8CPU mask = *src; |
89 do { | 87 do { |
90 *dst++ = TRANSFORM((mask >> 7) & 1); | 88 *dst++ = TRANSFORM((mask >> 7) & 1); |
91 mask <<= 1; | 89 mask <<= 1; |
92 } while (--bits != 0); | 90 } while (--bits != 0); |
93 } | 91 } |
94 } | 92 } |
95 | 93 |
94 bool SkWbmpCodec::setExpandProc(SkColorType colorType, SkPMColor* ctable, int* c tableCount) { | |
95 switch (colorType) { | |
96 case kGray_8_SkColorType: | |
97 fProc = expand_bits_to_T<uint8_t, bit_to_grayscale>; | |
98 return true; | |
99 case kN32_SkColorType: | |
100 fProc = expand_bits_to_T<SkPMColor, bit_to_pmcolor>; | |
101 return true; | |
102 case kIndex_8_SkColorType: | |
103 ctable[0] = BLACK; | |
104 ctable[1] = WHITE; | |
105 *ctableCount = 2; | |
106 fProc = expand_bits_to_T<uint8_t, bit_to_bit>; | |
107 return true; | |
108 case kRGB_565_SkColorType: | |
109 fProc = expand_bits_to_T<uint16_t, bit_to_rgb565>; | |
110 return true; | |
111 default: | |
112 return false; | |
113 } | |
114 } | |
115 | |
96 SkWbmpCodec::SkWbmpCodec(const SkImageInfo& info, SkStream* stream) | 116 SkWbmpCodec::SkWbmpCodec(const SkImageInfo& info, SkStream* stream) |
97 : INHERITED(info, stream) {} | 117 : INHERITED(info, stream) {} |
98 | 118 |
99 SkEncodedFormat SkWbmpCodec::onGetEncodedFormat() const { | 119 SkEncodedFormat SkWbmpCodec::onGetEncodedFormat() const { |
100 return kWBMP_SkEncodedFormat; | 120 return kWBMP_SkEncodedFormat; |
101 } | 121 } |
102 | 122 |
103 SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, | 123 SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, |
104 void* pixels, | 124 void* pixels, |
105 size_t rowBytes, | 125 size_t rowBytes, |
106 const Options& options, | 126 const Options& options, |
107 SkPMColor ctable[], | 127 SkPMColor ctable[], |
108 int* ctableCount) { | 128 int* ctableCount) { |
109 SkCodec::RewindState rewindState = this->rewindIfNeeded(); | 129 SkCodec::RewindState rewindState = this->rewindIfNeeded(); |
110 if (rewindState == kCouldNotRewind_RewindState) { | 130 if (rewindState == kCouldNotRewind_RewindState) { |
111 return kCouldNotRewind; | 131 return kCouldNotRewind; |
112 } else if (rewindState == kRewound_RewindState) { | 132 } else if (rewindState == kRewound_RewindState) { |
113 (void)read_header(this->stream(), NULL); | 133 (void)read_header(this->stream(), NULL); |
114 } | 134 } |
115 if (options.fSubset) { | 135 if (options.fSubset) { |
116 // Subsets are not supported. | 136 // Subsets are not supported. |
117 return kUnimplemented; | 137 return kUnimplemented; |
118 } | 138 } |
119 if (info.dimensions() != this->getInfo().dimensions()) { | 139 if (info.dimensions() != this->getInfo().dimensions()) { |
120 return kInvalidScale; | 140 return kInvalidScale; |
121 } | 141 } |
122 ExpandProc proc = NULL; | 142 |
123 switch (info.colorType()) { | 143 // Choose the expand routine based on the requested color type |
124 case kGray_8_SkColorType: | 144 if (!setExpandProc(info.colorType(), ctable, ctableCount)) { |
125 proc = expand_bits_to_T<uint8_t, bit_to_grayscale>; | 145 return kInvalidConversion; |
126 break; | |
127 case kN32_SkColorType: | |
128 proc = expand_bits_to_T<SkPMColor, bit_to_pmcolor>; | |
129 break; | |
130 case kIndex_8_SkColorType: | |
131 ctable[0] = BLACK; | |
132 ctable[1] = WHITE; | |
133 *ctableCount = 2; | |
134 proc = expand_bits_to_T<uint8_t, bit_to_bit>; | |
135 break; | |
136 case kRGB_565_SkColorType: | |
137 proc = expand_bits_to_T<uint16_t, bit_to_rgb565>; | |
138 break; | |
139 default: | |
140 return kInvalidConversion; | |
141 } | 146 } |
147 | |
emmaleer
2015/07/27 14:41:37
nit: added extra line
msarett
2015/07/27 23:42:30
Acknowledged.
| |
142 SkISize size = info.dimensions(); | 148 SkISize size = info.dimensions(); |
143 uint8_t* dst = static_cast<uint8_t*>(pixels); | 149 uint8_t* dst = static_cast<uint8_t*>(pixels); |
144 size_t srcRowBytes = SkAlign8(size.width()) >> 3; | 150 size_t srcRowBytes = SkAlign8(size.width()) >> 3; |
145 SkAutoTMalloc<uint8_t> src(srcRowBytes); | 151 SkAutoTMalloc<uint8_t> src(srcRowBytes); |
146 for (int y = 0; y < size.height(); ++y) { | 152 for (int y = 0; y < size.height(); ++y) { |
147 if (this->stream()->read(src.get(), srcRowBytes) != srcRowBytes) { | 153 if (this->stream()->read(src.get(), srcRowBytes) != srcRowBytes) { |
148 return kIncompleteInput; | 154 return kIncompleteInput; |
149 } | 155 } |
150 proc(dst, src.get(), size.width()); | 156 fProc(dst, src.get(), size.width()); |
151 dst += rowBytes; | 157 dst += rowBytes; |
152 } | 158 } |
153 return kSuccess; | 159 return kSuccess; |
154 } | 160 } |
155 | 161 |
156 bool SkWbmpCodec::IsWbmp(SkStream* stream) { | 162 bool SkWbmpCodec::IsWbmp(SkStream* stream) { |
157 return read_header(stream, NULL); | 163 return read_header(stream, NULL); |
158 } | 164 } |
159 | 165 |
160 SkCodec* SkWbmpCodec::NewFromStream(SkStream* stream) { | 166 SkCodec* SkWbmpCodec::NewFromStream(SkStream* stream) { |
161 SkAutoTDelete<SkStream> streamDeleter(stream); | 167 SkAutoTDelete<SkStream> streamDeleter(stream); |
162 SkISize size; | 168 SkISize size; |
163 if (!read_header(stream, &size)) { | 169 if (!read_header(stream, &size)) { |
164 return NULL; | 170 return NULL; |
165 } | 171 } |
166 SkImageInfo info = | 172 SkImageInfo info = |
167 SkImageInfo::Make(size.width(), size.height(), kGray_8_SkColorType, | 173 SkImageInfo::Make(size.width(), size.height(), kGray_8_SkColorType, |
168 kOpaque_SkAlphaType); | 174 kOpaque_SkAlphaType); |
169 return SkNEW_ARGS(SkWbmpCodec, (info, streamDeleter.detach())); | 175 return SkNEW_ARGS(SkWbmpCodec, (info, streamDeleter.detach())); |
170 } | 176 } |
177 | |
178 class SkWbmpScanlineDecoder : public SkScanlineDecoder { | |
179 public: | |
180 SkWbmpScanlineDecoder(const SkImageInfo& dstInfo, SkWbmpCodec* codec) | |
181 : INHERITED(dstInfo) | |
182 , fCodec(codec) | |
183 , fSrcRowBytes(SkAlign8(fCodec->getInfo().width()) >> 3) | |
scroggo
2015/07/27 14:16:45
Maybe add a static helper function for this, to sh
emmaleer
2015/07/27 14:41:37
Could you add a comment describing why the rowByte
msarett
2015/07/27 23:42:30
Done.
| |
184 , fSrcBuffer(fSrcRowBytes) | |
185 {} | |
186 | |
187 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { | |
188 for (int y = 0; y < count; ++y) { | |
189 if (fCodec->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRo wBytes) { | |
190 return SkCodec::kIncompleteInput; | |
191 } | |
192 fCodec->fProc((uint8_t*) dst, fSrcBuffer.get(), dstInfo().width()); | |
scroggo
2015/07/27 14:16:45
The scanline decoder will need to store fProc, but
emmaleer
2015/07/27 14:41:37
Why isn't the Swizzler being used? Does fProc do s
msarett
2015/07/27 23:42:30
fSwizzler is now a field of only the scanline deco
| |
193 dst += dstRowBytes; | |
194 } | |
195 return SkCodec::kSuccess; | |
196 } | |
197 | |
198 private: | |
199 SkAutoTDelete<SkWbmpCodec> fCodec; | |
200 const size_t fSrcRowBytes; | |
201 SkAutoTMalloc<uint8_t> fSrcBuffer; | |
202 | |
203 typedef SkScanlineDecoder INHERITED; | |
204 }; | |
205 | |
206 | |
207 SkScanlineDecoder* SkWbmpCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, | |
208 const Options& options, SkPMColor ctable[], int* ctableCount) { | |
209 if (options.fSubset) { | |
210 // Subsets are not supported. | |
211 return NULL; | |
212 } | |
213 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | |
214 return NULL; | |
215 } | |
216 // Create a new SkWbmpCodec, to be owned by the scanline decoder. | |
217 SkStream* stream = this->stream()->duplicate(); | |
218 if (!stream) { | |
219 return NULL; | |
220 } | |
221 SkAutoTDelete<SkWbmpCodec> codec(static_cast<SkWbmpCodec*>(SkWbmpCodec::NewF romStream(stream))); | |
222 if (!codec) { | |
223 return NULL; | |
224 } | |
225 | |
226 // Choose the expand routine based on the requested color type | |
227 if (!codec->setExpandProc(dstInfo.colorType(), ctable, ctableCount)) { | |
228 return NULL; | |
229 } | |
230 | |
231 return SkNEW_ARGS(SkWbmpScanlineDecoder, (dstInfo, codec.detach())); | |
232 } | |
OLD | NEW |