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

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

Issue 1057483003: Handle rewinds in SkBmpCodec. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Initialize codec to defeat warning. Created 5 years, 8 months 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
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | tests/CodexTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "SkCodec_libbmp.h" 8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 * Creates a bmp decoder for a bmp embedded in ico 98 * Creates a bmp decoder for a bmp embedded in ico
99 * Reads enough of the stream to determine the image format 99 * Reads enough of the stream to determine the image format
100 * 100 *
101 */ 101 */
102 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) { 102 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
103 return SkBmpCodec::NewFromStream(stream, true); 103 return SkBmpCodec::NewFromStream(stream, true);
104 } 104 }
105 105
106 /* 106 /*
107 * 107 *
108 * Creates a bmp decoder 108 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
109 * Reads enough of the stream to determine the image format 109 * representing success or failure. If it returned true, and codecOut was
110 * not NULL, it will be set to a new SkBmpCodec.
110 * 111 *
111 */ 112 */
112 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { 113 bool SkBmpCodec::ReadHeader(SkStream* stream, bool isIco, SkCodec** codecOut) {
113 // Header size constants 114 // Header size constants
114 static const uint32_t kBmpHeaderBytes = 14; 115 static const uint32_t kBmpHeaderBytes = 14;
115 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; 116 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
116 static const uint32_t kBmpOS2V1Bytes = 12; 117 static const uint32_t kBmpOS2V1Bytes = 12;
117 static const uint32_t kBmpOS2V2Bytes = 64; 118 static const uint32_t kBmpOS2V2Bytes = 64;
118 static const uint32_t kBmpInfoBaseBytes = 16; 119 static const uint32_t kBmpInfoBaseBytes = 16;
119 static const uint32_t kBmpInfoV1Bytes = 40; 120 static const uint32_t kBmpInfoV1Bytes = 40;
120 static const uint32_t kBmpInfoV2Bytes = 52; 121 static const uint32_t kBmpInfoV2Bytes = 52;
121 static const uint32_t kBmpInfoV3Bytes = 56; 122 static const uint32_t kBmpInfoV3Bytes = 56;
122 static const uint32_t kBmpInfoV4Bytes = 108; 123 static const uint32_t kBmpInfoV4Bytes = 108;
(...skipping 10 matching lines...) Expand all
133 uint32_t infoBytes; 134 uint32_t infoBytes;
134 135
135 // Bmps embedded in Icos skip the first Bmp header 136 // Bmps embedded in Icos skip the first Bmp header
136 if (!isIco) { 137 if (!isIco) {
137 // Read the first header and the size of the second header 138 // Read the first header and the size of the second header
138 SkAutoTDeleteArray<uint8_t> hBuffer( 139 SkAutoTDeleteArray<uint8_t> hBuffer(
139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); 140 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != 141 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
141 kBmpHeaderBytesPlusFour) { 142 kBmpHeaderBytesPlusFour) {
142 SkCodecPrintf("Error: unable to read first bitmap header.\n"); 143 SkCodecPrintf("Error: unable to read first bitmap header.\n");
143 return NULL; 144 return false;
144 } 145 }
145 146
146 totalBytes = get_int(hBuffer.get(), 2); 147 totalBytes = get_int(hBuffer.get(), 2);
147 offset = get_int(hBuffer.get(), 10); 148 offset = get_int(hBuffer.get(), 10);
148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { 149 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
149 SkCodecPrintf("Error: invalid starting location for pixel data\n"); 150 SkCodecPrintf("Error: invalid starting location for pixel data\n");
150 return NULL; 151 return false;
151 } 152 }
152 153
153 // The size of the second (info) header in bytes 154 // The size of the second (info) header in bytes
154 // The size is the first field of the second header, so we have already 155 // The size is the first field of the second header, so we have already
155 // read the first four infoBytes. 156 // read the first four infoBytes.
156 infoBytes = get_int(hBuffer.get(), 14); 157 infoBytes = get_int(hBuffer.get(), 14);
157 if (infoBytes < kBmpOS2V1Bytes) { 158 if (infoBytes < kBmpOS2V1Bytes) {
158 SkCodecPrintf("Error: invalid second header size.\n"); 159 SkCodecPrintf("Error: invalid second header size.\n");
159 return NULL; 160 return false;
160 } 161 }
161 } else { 162 } else {
162 // This value is only used by RLE compression. Bmp in Ico files do not 163 // This value is only used by RLE compression. Bmp in Ico files do not
163 // use RLE. If the compression field is incorrectly signaled as RLE, 164 // use RLE. If the compression field is incorrectly signaled as RLE,
164 // we will catch this and signal an error below. 165 // we will catch this and signal an error below.
165 totalBytes = 0; 166 totalBytes = 0;
166 167
167 // Bmps in Ico cannot specify an offset. We will always assume that 168 // Bmps in Ico cannot specify an offset. We will always assume that
168 // pixel data begins immediately after the color table. This value 169 // pixel data begins immediately after the color table. This value
169 // will be corrected below. 170 // will be corrected below.
170 offset = 0; 171 offset = 0;
171 172
172 // Read the size of the second header 173 // Read the size of the second header
173 SkAutoTDeleteArray<uint8_t> hBuffer( 174 SkAutoTDeleteArray<uint8_t> hBuffer(
174 SkNEW_ARRAY(uint8_t, 4)); 175 SkNEW_ARRAY(uint8_t, 4));
175 if (stream->read(hBuffer.get(), 4) != 4) { 176 if (stream->read(hBuffer.get(), 4) != 4) {
176 SkCodecPrintf("Error: unable to read size of second bitmap header.\n "); 177 SkCodecPrintf("Error: unable to read size of second bitmap header.\n ");
177 return NULL; 178 return false;
178 } 179 }
179 infoBytes = get_int(hBuffer.get(), 0); 180 infoBytes = get_int(hBuffer.get(), 0);
180 if (infoBytes < kBmpOS2V1Bytes) { 181 if (infoBytes < kBmpOS2V1Bytes) {
181 SkCodecPrintf("Error: invalid second header size.\n"); 182 SkCodecPrintf("Error: invalid second header size.\n");
182 return NULL; 183 return false;
183 } 184 }
184 } 185 }
185 186
186 // We already read the first four bytes of the info header to get the size 187 // We already read the first four bytes of the info header to get the size
187 const uint32_t infoBytesRemaining = infoBytes - 4; 188 const uint32_t infoBytesRemaining = infoBytes - 4;
188 189
189 // Read the second header 190 // Read the second header
190 SkAutoTDeleteArray<uint8_t> iBuffer( 191 SkAutoTDeleteArray<uint8_t> iBuffer(
191 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); 192 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 193 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
193 SkCodecPrintf("Error: unable to read second bitmap header.\n"); 194 SkCodecPrintf("Error: unable to read second bitmap header.\n");
194 return NULL; 195 return false;
195 } 196 }
196 197
197 // The number of bits used per pixel in the pixel data 198 // The number of bits used per pixel in the pixel data
198 uint16_t bitsPerPixel; 199 uint16_t bitsPerPixel;
199 200
200 // The compression method for the pixel data 201 // The compression method for the pixel data
201 uint32_t compression = kNone_BitmapCompressionMethod; 202 uint32_t compression = kNone_BitmapCompressionMethod;
202 203
203 // Number of colors in the color table, defaults to 0 or max (see below) 204 // Number of colors in the color table, defaults to 0 or max (see below)
204 uint32_t numColors = 0; 205 uint32_t numColors = 0;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } else if (infoBytes >= kBmpOS2V1Bytes) { 276 } else if (infoBytes >= kBmpOS2V1Bytes) {
276 // The OS2V1 is treated separately because it has a unique format 277 // The OS2V1 is treated separately because it has a unique format
277 headerType = kOS2V1_BitmapHeaderType; 278 headerType = kOS2V1_BitmapHeaderType;
278 width = (int) get_short(iBuffer.get(), 0); 279 width = (int) get_short(iBuffer.get(), 0);
279 height = (int) get_short(iBuffer.get(), 2); 280 height = (int) get_short(iBuffer.get(), 2);
280 bitsPerPixel = get_short(iBuffer.get(), 6); 281 bitsPerPixel = get_short(iBuffer.get(), 6);
281 bytesPerColor = 3; 282 bytesPerColor = 3;
282 } else { 283 } else {
283 // There are no valid bmp headers 284 // There are no valid bmp headers
284 SkCodecPrintf("Error: second bitmap header size is invalid.\n"); 285 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
285 return NULL; 286 return false;
286 } 287 }
287 288
288 // Check for valid dimensions from header 289 // Check for valid dimensions from header
289 RowOrder rowOrder = kBottomUp_RowOrder; 290 RowOrder rowOrder = kBottomUp_RowOrder;
290 if (height < 0) { 291 if (height < 0) {
291 height = -height; 292 height = -height;
292 rowOrder = kTopDown_RowOrder; 293 rowOrder = kTopDown_RowOrder;
293 } 294 }
294 // The height field for bmp in ico is double the actual height because they 295 // The height field for bmp in ico is double the actual height because they
295 // contain an XOR mask followed by an AND mask 296 // contain an XOR mask followed by an AND mask
296 if (isIco) { 297 if (isIco) {
297 height /= 2; 298 height /= 2;
298 } 299 }
299 static const int kBmpMaxDim = 1 << 16; 300 static const int kBmpMaxDim = 1 << 16;
300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { 301 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
301 // TODO: Decide if we want to support really large bmps. 302 // TODO: Decide if we want to support really large bmps.
302 SkCodecPrintf("Error: invalid bitmap dimensions.\n"); 303 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
303 return NULL; 304 return false;
304 } 305 }
305 306
306 // Create mask struct 307 // Create mask struct
307 SkMasks::InputMasks inputMasks; 308 SkMasks::InputMasks inputMasks;
308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 309 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
309 310
310 // Determine the input compression format and set bit masks if necessary 311 // Determine the input compression format and set bit masks if necessary
311 uint32_t maskBytes = 0; 312 uint32_t maskBytes = 0;
312 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; 313 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
313 switch (compression) { 314 switch (compression) {
(...skipping 19 matching lines...) Expand all
333 // Load the masks 334 // Load the masks
334 inputFormat = kBitMask_BitmapInputFormat; 335 inputFormat = kBitMask_BitmapInputFormat;
335 switch (headerType) { 336 switch (headerType) {
336 case kInfoV1_BitmapHeaderType: { 337 case kInfoV1_BitmapHeaderType: {
337 // The V1 header stores the bit masks after the header 338 // The V1 header stores the bit masks after the header
338 SkAutoTDeleteArray<uint8_t> mBuffer( 339 SkAutoTDeleteArray<uint8_t> mBuffer(
339 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); 340 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
340 if (stream->read(mBuffer.get(), kBmpMaskBytes) != 341 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
341 kBmpMaskBytes) { 342 kBmpMaskBytes) {
342 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ; 343 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ;
343 return NULL; 344 return false;
344 } 345 }
345 maskBytes = kBmpMaskBytes; 346 maskBytes = kBmpMaskBytes;
346 inputMasks.red = get_int(mBuffer.get(), 0); 347 inputMasks.red = get_int(mBuffer.get(), 0);
347 inputMasks.green = get_int(mBuffer.get(), 4); 348 inputMasks.green = get_int(mBuffer.get(), 4);
348 inputMasks.blue = get_int(mBuffer.get(), 8); 349 inputMasks.blue = get_int(mBuffer.get(), 8);
349 break; 350 break;
350 } 351 }
351 case kInfoV2_BitmapHeaderType: 352 case kInfoV2_BitmapHeaderType:
352 case kInfoV3_BitmapHeaderType: 353 case kInfoV3_BitmapHeaderType:
353 case kInfoV4_BitmapHeaderType: 354 case kInfoV4_BitmapHeaderType:
354 case kInfoV5_BitmapHeaderType: 355 case kInfoV5_BitmapHeaderType:
355 // Header types are matched based on size. If the header 356 // Header types are matched based on size. If the header
356 // is V2+, we are guaranteed to be able to read at least 357 // is V2+, we are guaranteed to be able to read at least
357 // this size. 358 // this size.
358 SkASSERT(infoBytesRemaining >= 48); 359 SkASSERT(infoBytesRemaining >= 48);
359 inputMasks.red = get_int(iBuffer.get(), 36); 360 inputMasks.red = get_int(iBuffer.get(), 36);
360 inputMasks.green = get_int(iBuffer.get(), 40); 361 inputMasks.green = get_int(iBuffer.get(), 40);
361 inputMasks.blue = get_int(iBuffer.get(), 44); 362 inputMasks.blue = get_int(iBuffer.get(), 44);
362 break; 363 break;
363 case kOS2VX_BitmapHeaderType: 364 case kOS2VX_BitmapHeaderType:
364 // TODO: Decide if we intend to support this. 365 // TODO: Decide if we intend to support this.
365 // It is unsupported in the previous version and 366 // It is unsupported in the previous version and
366 // in chromium. I have not come across a test case 367 // in chromium. I have not come across a test case
367 // that uses this format. 368 // that uses this format.
368 SkCodecPrintf("Error: huffman format unsupported.\n"); 369 SkCodecPrintf("Error: huffman format unsupported.\n");
369 return NULL; 370 return false;
370 default: 371 default:
371 SkCodecPrintf("Error: invalid bmp bit masks header.\n"); 372 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
372 return NULL; 373 return false;
373 } 374 }
374 break; 375 break;
375 case kJpeg_BitmapCompressionMethod: 376 case kJpeg_BitmapCompressionMethod:
376 if (24 == bitsPerPixel) { 377 if (24 == bitsPerPixel) {
377 inputFormat = kRLE_BitmapInputFormat; 378 inputFormat = kRLE_BitmapInputFormat;
378 break; 379 break;
379 } 380 }
380 // Fall through 381 // Fall through
381 case kPng_BitmapCompressionMethod: 382 case kPng_BitmapCompressionMethod:
382 // TODO: Decide if we intend to support this. 383 // TODO: Decide if we intend to support this.
383 // It is unsupported in the previous version and 384 // It is unsupported in the previous version and
384 // in chromium. I think it is used mostly for printers. 385 // in chromium. I think it is used mostly for printers.
385 SkCodecPrintf("Error: compression format not supported.\n"); 386 SkCodecPrintf("Error: compression format not supported.\n");
386 return NULL; 387 return false;
387 case kCMYK_BitmapCompressionMethod: 388 case kCMYK_BitmapCompressionMethod:
388 case kCMYK8BitRLE_BitmapCompressionMethod: 389 case kCMYK8BitRLE_BitmapCompressionMethod:
389 case kCMYK4BitRLE_BitmapCompressionMethod: 390 case kCMYK4BitRLE_BitmapCompressionMethod:
390 // TODO: Same as above. 391 // TODO: Same as above.
391 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n"); 392 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
392 return NULL; 393 return false;
393 default: 394 default:
394 SkCodecPrintf("Error: invalid format for bitmap decoding.\n"); 395 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
395 return NULL; 396 return false;
396 } 397 }
397 398
398 // Most versions of bmps should be rendered as opaque. Either they do 399 // Most versions of bmps should be rendered as opaque. Either they do
399 // not have an alpha channel, or they expect the alpha channel to be 400 // not have an alpha channel, or they expect the alpha channel to be
400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator 401 // ignored. V3+ bmp files introduce an alpha mask and allow the creator
401 // of the image to use the alpha channels. However, many of these images 402 // of the image to use the alpha channels. However, many of these images
402 // leave the alpha channel blank and expect to be rendered as opaque. This 403 // leave the alpha channel blank and expect to be rendered as opaque. This
403 // is the case for almost all V3 images, so we render these as opaque. For 404 // is the case for almost all V3 images, so we render these as opaque. For
404 // V4+, we will use the alpha channel, and fix the image later if it turns 405 // V4+, we will use the alpha channel, and fix the image later if it turns
405 // out to be fully transparent. 406 // out to be fully transparent.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 break; 441 break;
441 case 1: 442 case 1:
442 case 2: 443 case 2:
443 case 4: 444 case 4:
444 case 8: 445 case 8:
445 case 24: 446 case 24:
446 case 32: 447 case 32:
447 break; 448 break;
448 default: 449 default:
449 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 450 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
450 return NULL; 451 return false;
451 } 452 }
452 453
453 // Check that input bit masks are valid and create the masks object 454 // Check that input bit masks are valid and create the masks object
454 SkAutoTDelete<SkMasks> 455 SkAutoTDelete<SkMasks>
455 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 456 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
456 if (NULL == masks) { 457 if (NULL == masks) {
457 SkCodecPrintf("Error: invalid input masks.\n"); 458 SkCodecPrintf("Error: invalid input masks.\n");
458 return NULL; 459 return false;
459 } 460 }
460 461
461 // Check for a valid number of total bytes when in RLE mode 462 // Check for a valid number of total bytes when in RLE mode
462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { 463 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
463 SkCodecPrintf("Error: RLE requires valid input size.\n"); 464 SkCodecPrintf("Error: RLE requires valid input size.\n");
464 return NULL; 465 return false;
465 } 466 }
466 const size_t RLEBytes = totalBytes - offset; 467 const size_t RLEBytes = totalBytes - offset;
467 468
468 // Calculate the number of bytes read so far 469 // Calculate the number of bytes read so far
469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 470 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
470 if (!isIco && offset < bytesRead) { 471 if (!isIco && offset < bytesRead) {
471 SkCodecPrintf("Error: pixel data offset less than header size.\n"); 472 SkCodecPrintf("Error: pixel data offset less than header size.\n");
472 return NULL; 473 return false;
473 } 474 }
474 475
475 // Return the codec 476 if (codecOut) {
476 // We will use ImageInfo to store width, height, and alpha type. We will 477 // Return the codec
477 // set color type to kN32_SkColorType because that should be the default 478 // We will use ImageInfo to store width, height, and alpha type. We
478 // output. 479 // will set color type to kN32_SkColorType because that should be the
479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 480 // default output.
480 kN32_SkColorType, alphaType); 481 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 482 kN32_SkColorType, alphaType);
482 inputFormat, masks.detach(), numColors, 483 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
483 bytesPerColor, offset - bytesRead, 484 inputFormat, masks.detach(),
484 rowOrder, RLEBytes, isIco)); 485 numColors, bytesPerColor,
486 offset - bytesRead, rowOrder,
487 RLEBytes, isIco));
488 }
489 return true;
485 } 490 }
486 491
487 /* 492 /*
493 *
494 * Creates a bmp decoder
495 * Reads enough of the stream to determine the image format
496 *
497 */
498 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) {
499 SkCodec* codec = NULL;
500 if (ReadHeader(stream, isIco, &codec)) {
501 return codec;
502 }
503 return NULL;
504 }
505
506 /*
488 * 507 *
489 * Creates an instance of the decoder 508 * Creates an instance of the decoder
490 * Called only by NewFromStream 509 * Called only by NewFromStream
491 * 510 *
492 */ 511 */
493 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, 512 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
494 uint16_t bitsPerPixel, BitmapInputFormat inputFormat, 513 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
495 SkMasks* masks, uint32_t numColors, 514 SkMasks* masks, uint32_t numColors,
496 uint32_t bytesPerColor, uint32_t offset, 515 uint32_t bytesPerColor, uint32_t offset,
497 RowOrder rowOrder, size_t RLEBytes, bool isIco) 516 RowOrder rowOrder, size_t RLEBytes, bool isIco)
(...skipping 18 matching lines...) Expand all
516 */ 535 */
517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 536 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
518 void* dst, size_t dstRowBytes, 537 void* dst, size_t dstRowBytes,
519 const Options&, 538 const Options&,
520 SkPMColor*, int*) { 539 SkPMColor*, int*) {
521 // Check for proper input and output formats 540 // Check for proper input and output formats
522 SkCodec::RewindState rewindState = this->rewindIfNeeded(); 541 SkCodec::RewindState rewindState = this->rewindIfNeeded();
523 if (rewindState == kCouldNotRewind_RewindState) { 542 if (rewindState == kCouldNotRewind_RewindState) {
524 return kCouldNotRewind; 543 return kCouldNotRewind;
525 } else if (rewindState == kRewound_RewindState) { 544 } else if (rewindState == kRewound_RewindState) {
526 return kCouldNotRewind; // TODO(msarett): handle rewinds 545 if (!ReadHeader(this->stream(), fIsIco, NULL)) {
546 return kCouldNotRewind;
547 }
527 } 548 }
528 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 549 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
529 SkCodecPrintf("Error: scaling not supported.\n"); 550 SkCodecPrintf("Error: scaling not supported.\n");
530 return kInvalidScale; 551 return kInvalidScale;
531 } 552 }
532 if (!conversion_possible(dstInfo, this->getInfo())) { 553 if (!conversion_possible(dstInfo, this->getInfo())) {
533 SkCodecPrintf("Error: cannot convert input type to output type.\n"); 554 SkCodecPrintf("Error: cannot convert input type to output type.\n");
534 return kInvalidConversion; 555 return kInvalidConversion;
535 } 556 }
536 557
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 uint32_t alphaBit = 1126 uint32_t alphaBit =
1106 (srcBuffer.get()[quotient] >> shift) & 0x1; 1127 (srcBuffer.get()[quotient] >> shift) & 0x1;
1107 dstRow[x] &= alphaBit - 1; 1128 dstRow[x] &= alphaBit - 1;
1108 } 1129 }
1109 } 1130 }
1110 } 1131 }
1111 1132
1112 // Finished decoding the entire image 1133 // Finished decoding the entire image
1113 return kSuccess; 1134 return kSuccess;
1114 } 1135 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | tests/CodexTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698