Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: src/codec/SkBmpStandardCodec.cpp

Issue 1472933002: Make SkAndroidCodec support ico (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "SkBmpStandardCodec.h" 8 #include "SkBmpStandardCodec.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 53
54 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol orCount); 54 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol orCount);
55 if (kSuccess != result) { 55 if (kSuccess != result) {
56 return result; 56 return result;
57 } 57 }
58 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts); 58 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
59 if (rows != dstInfo.height()) { 59 if (rows != dstInfo.height()) {
60 *rowsDecoded = rows; 60 *rowsDecoded = rows;
61 return kIncompleteInput; 61 return kIncompleteInput;
62 } 62 }
63 if (fInIco) {
64 return this->decodeIcoMask(dstInfo, dst, dstRowBytes);
65 }
66 return kSuccess; 63 return kSuccess;
67 } 64 }
68 65
69 /* 66 /*
70 * Process the color table for the bmp input 67 * Process the color table for the bmp input
71 */ 68 */
72 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) { 69 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) {
73 // Allocate memory for color table 70 // Allocate memory for color table
74 uint32_t colorBytes = 0; 71 uint32_t colorBytes = 0;
75 SkPMColor colorTable[256]; 72 SkPMColor colorTable[256];
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (!this->initializeSwizzler(dstInfo, options)) { 217 if (!this->initializeSwizzler(dstInfo, options)) {
221 SkCodecPrintf("Error: cannot initialize swizzler.\n"); 218 SkCodecPrintf("Error: cannot initialize swizzler.\n");
222 return SkCodec::kInvalidConversion; 219 return SkCodec::kInvalidConversion;
223 } 220 }
224 return SkCodec::kSuccess; 221 return SkCodec::kSuccess;
225 } 222 }
226 223
227 /* 224 /*
228 * Performs the bitmap decoding for standard input format 225 * Performs the bitmap decoding for standard input format
229 */ 226 */
230 int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, 227 int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
231 void* dst, size_t dstRowBytes, 228 const Options& opts) {
232 const Options& opts) {
233 // Iterate over rows of the image 229 // Iterate over rows of the image
234 const int height = dstInfo.height(); 230 const int height = dstInfo.height();
235 for (int y = 0; y < height; y++) { 231 for (int y = 0; y < height; y++) {
236 // Read a row of the input 232 // Read a row of the input
237 if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes ) { 233 if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes ) {
238 SkCodecPrintf("Warning: incomplete input stream.\n"); 234 SkCodecPrintf("Warning: incomplete input stream.\n");
239 return y; 235 return y;
240 } 236 }
241 237
242 // Decode the row in destination format 238 // Decode the row in destination format
243 uint32_t row = this->getDstRow(y, dstInfo.height()); 239 uint32_t row = this->getDstRow(y, dstInfo.height());
244 240
245 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); 241 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
246 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 242 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
247 } 243 }
248 244
249 // Finished decoding the entire image 245 if (fInIco) {
246 const int startScanline = this->currScanline();
247 const size_t andMaskRowBytes = SkAlign4(compute_row_bytes(this->getInfo( ).width(), 1));
248 if (startScanline < 0) {
249 // We are not performing a scanline decode.
250 // Just decode the entire ICO mask and return.
251 decodeIcoMask(dstInfo, dst, dstRowBytes, andMaskRowBytes);
252 return height;
253 }
254
255 // In order to perform a scanline ICO decode, we must be able
256 // to skip ahead in the stream in order to apply the AND mask
257 // to the requested scanlines. We also must be able to return
258 // the stream to its original position in order to decode the
259 // next scanline on a subsequent request.
260 // We will do this by taking advantage of the fact that
261 // SkIcoCodec always uses a SkMemoryStream as its underlying
262 // representation of the stream.
263 SkMemoryStream* stream = (SkMemoryStream*) this->stream();
264 const size_t startPosition = stream->getPosition();
265
266 const int remainingScanlines = this->getInfo().height() - startScanline - height;
267 const size_t bytesToSkip = remainingScanlines * fSrcRowBytes +
268 startScanline * andMaskRowBytes;
269 if (bytesToSkip != stream->skip(bytesToSkip)) {
270 // FIXME: How can we indicate that this decode was actually incomple te?
271 stream->seek(startPosition);
272 return height;
273 }
274 // FIXME: If decodeIcoMask does not succeed, is there a way that we can
275 // indicate the decode was incomplete?
276 decodeIcoMask(dstInfo, dst, dstRowBytes, andMaskRowBytes);
277 stream->seek(startPosition);
278 }
279
250 return height; 280 return height;
251 } 281 }
252 282
253 // TODO (msarett): This function will need to be modified in order to perform ro w by row decodes 283 void SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo,
254 // when the Ico scanline decoder is implemented. 284 void* dst, size_t dstRowBytes, size_t srcRowBytes) {
255 SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo,
256 void* dst, size_t dstRowBytes) {
257 // BMP in ICO have transparency, so this cannot be 565, and this mask 285 // BMP in ICO have transparency, so this cannot be 565, and this mask
258 // prevents us from using kIndex8. The below code depends on the output 286 // prevents us from using kIndex8. The below code depends on the output
259 // being an SkPMColor. 287 // being an SkPMColor.
260 SkASSERT(dstInfo.colorType() == kN32_SkColorType); 288 SkASSERT(dstInfo.colorType() == kN32_SkColorType);
261 289
262 // The AND mask is always 1 bit per pixel
263 const int width = this->getInfo().width();
264 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
265
266 SkPMColor* dstPtr = (SkPMColor*) dst; 290 SkPMColor* dstPtr = (SkPMColor*) dst;
267 for (int y = 0; y < dstInfo.height(); y++) { 291 for (int y = 0; y < dstInfo.height(); y++) {
268 // The srcBuffer will at least be large enough 292 // The srcBuffer will at least be large enough
269 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { 293 if (this->stream()->read(fSrcBuffer.get(), srcRowBytes) != srcRowBytes) {
270 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); 294 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
271 return kIncompleteInput; 295 return;
272 } 296 }
273 297
274 int row = this->getDstRow(y, dstInfo.height()); 298 int row = this->getDstRow(y, dstInfo.height());
275 299
276 SkPMColor* dstRow = 300 SkPMColor* dstRow =
277 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); 301 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
278 302
279 for (int x = 0; x < width; x++) { 303 for (int x = 0; x < this->getInfo().width(); x++) {
280 int quotient; 304 int quotient;
281 int modulus; 305 int modulus;
282 SkTDivMod(x, 8, &quotient, &modulus); 306 SkTDivMod(x, 8, &quotient, &modulus);
283 uint32_t shift = 7 - modulus; 307 uint32_t shift = 7 - modulus;
284 uint32_t alphaBit = 308 uint32_t alphaBit =
285 (fSrcBuffer.get()[quotient] >> shift) & 0x1; 309 (fSrcBuffer.get()[quotient] >> shift) & 0x1;
286 dstRow[x] &= alphaBit - 1; 310 dstRow[x] &= alphaBit - 1;
msarett 2015/11/24 22:43:35 This is currently broken. We either need to know
287 } 311 }
288 } 312 }
289 return kSuccess;
290 } 313 }
291 314
292 uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType a lphaType) const { 315 uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType a lphaType) const {
293 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 316 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
294 if (colorPtr) { 317 if (colorPtr) {
295 return get_color_table_fill_value(colorType, colorPtr, 0); 318 return get_color_table_fill_value(colorType, colorPtr, 0);
296 } 319 }
297 return INHERITED::onGetFillValue(colorType, alphaType); 320 return INHERITED::onGetFillValue(colorType, alphaType);
298 } 321 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698