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

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

Issue 1013743003: Adding premul and 565 swizzles for bmp: (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Moved color table checks to onGetPixels, Disabled swizzles non-opaque swizzles to 565 Created 5 years, 9 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') | src/codec/SkMaskSwizzler.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"
11 #include "SkStream.h" 11 #include "SkStream.h"
12 12
13 /* 13 /*
14 * 14 *
15 * Checks if the conversion between the input image and the requested output 15 * Checks if the conversion between the input image and the requested output
16 * image has been implemented 16 * image has been implemented
17 * 17 *
18 */ 18 */
19 static bool conversion_possible(const SkImageInfo& dst, 19 static bool conversion_possible(const SkImageInfo& dst,
20 const SkImageInfo& src) { 20 const SkImageInfo& src) {
21 // All of the swizzles convert to kN32 21 // Check for supported color and alpha types
22 // TODO: Update this when more swizzles are supported 22 switch (dst.colorType()) {
23 if (kN32_SkColorType != dst.colorType()) { 23 case kN32_SkColorType:
24 return false; 24 return src.alphaType() == dst.alphaType() ||
25 premul_and_unpremul(dst.alphaType(), src.alphaType());
scroggo 2015/03/17 20:02:58 Oh, clever. You don't need to check this in both o
msarett 2015/03/18 13:02:52 Agreed.
26 case kRGB_565_SkColorType:
27 return src.alphaType() == dst.alphaType() &&
28 kOpaque_SkAlphaType == dst.alphaType();
29 default:
30 return false;
25 } 31 }
26 // Support the swizzle if the requested alpha type is the same as our guess
27 // for the input alpha type
28 if (src.alphaType() == dst.alphaType()) {
29 return true;
30 }
31 // TODO: Support more swizzles, especially premul
32 return false;
33 } 32 }
34 33
35 /* 34 /*
36 * 35 *
37 * Defines the version and type of the second bitmap header 36 * Defines the version and type of the second bitmap header
38 * 37 *
39 */ 38 */
40 enum BitmapHeaderType { 39 enum BitmapHeaderType {
41 kInfoV1_BitmapHeaderType, 40 kInfoV1_BitmapHeaderType,
42 kInfoV2_BitmapHeaderType, 41 kInfoV2_BitmapHeaderType,
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 } 239 }
241 static const int kBmpMaxDim = 1 << 16; 240 static const int kBmpMaxDim = 1 << 16;
242 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { 241 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
243 // TODO: Decide if we want to support really large bmps. 242 // TODO: Decide if we want to support really large bmps.
244 SkDebugf("Error: invalid bitmap dimensions.\n"); 243 SkDebugf("Error: invalid bitmap dimensions.\n");
245 return NULL; 244 return NULL;
246 } 245 }
247 246
248 // Create mask struct 247 // Create mask struct
249 SkMasks::InputMasks inputMasks; 248 SkMasks::InputMasks inputMasks;
250 memset(&inputMasks, 0, 4*sizeof(uint32_t)); 249 memset(&inputMasks, 0, 4*sizeof(uint32_t));
scroggo 2015/03/17 20:02:58 nit: Maybe this should be sizeof(SkMasks::InputMas
msarett 2015/03/18 13:02:52 Done.
251 250
252 // Determine the input compression format and set bit masks if necessary 251 // Determine the input compression format and set bit masks if necessary
253 uint32_t maskBytes = 0; 252 uint32_t maskBytes = 0;
254 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; 253 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
255 switch (compression) { 254 switch (compression) {
256 case kNone_BitmapCompressionMethod: 255 case kNone_BitmapCompressionMethod:
257 inputFormat = kStandard_BitmapInputFormat; 256 inputFormat = kStandard_BitmapInputFormat;
258 break; 257 break;
259 case k8BitRLE_BitmapCompressionMethod: 258 case k8BitRLE_BitmapCompressionMethod:
260 if (bitsPerPixel != 8) { 259 if (bitsPerPixel != 8) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 // Header types are matched based on size. If the header is 349 // Header types are matched based on size. If the header is
351 // V4+, we are guaranteed to be able to read at least this size. 350 // V4+, we are guaranteed to be able to read at least this size.
352 SkASSERT(infoBytesRemaining > 52); 351 SkASSERT(infoBytesRemaining > 52);
353 inputMasks.alpha = get_int(iBuffer.get(), 48); 352 inputMasks.alpha = get_int(iBuffer.get(), 48);
354 if (inputMasks.alpha != 0) { 353 if (inputMasks.alpha != 0) {
355 alphaType = kUnpremul_SkAlphaType; 354 alphaType = kUnpremul_SkAlphaType;
356 } 355 }
357 } 356 }
358 iBuffer.free(); 357 iBuffer.free();
359 358
359 // Check for a valid number of total bytes when in RLE mode
360 const int RLEBytes = totalBytes - offset;
scroggo 2015/03/17 20:02:58 size_t
msarett 2015/03/18 13:02:52 Done.
361 if (RLEBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
362 SkDebugf("Error: RLE requires valid input size.\n");
363 return NULL;
364 }
365
360 // Check for valid bits per pixel input 366 // Check for valid bits per pixel input
361 switch (bitsPerPixel) { 367 switch (bitsPerPixel) {
362 // In addition to more standard pixel compression formats, bmp supports 368 // In addition to more standard pixel compression formats, bmp supports
363 // the use of bit masks to determine pixel components. The standard 369 // the use of bit masks to determine pixel components. The standard
364 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 370 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
365 // which does not map well to any Skia color formats. For this reason, 371 // which does not map well to any Skia color formats. For this reason,
366 // we will always enable mask mode with 16 bits per pixel. 372 // we will always enable mask mode with 16 bits per pixel.
367 case 16: 373 case 16:
368 if (kBitMask_BitmapInputFormat != inputFormat) { 374 if (kBitMask_BitmapInputFormat != inputFormat) {
369 inputMasks.red = 0x7C00; 375 inputMasks.red = 0x7C00;
(...skipping 15 matching lines...) Expand all
385 } 391 }
386 392
387 // Check that input bit masks are valid and create the masks object 393 // Check that input bit masks are valid and create the masks object
388 SkAutoTDelete<SkMasks> 394 SkAutoTDelete<SkMasks>
389 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 395 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
390 if (NULL == masks) { 396 if (NULL == masks) {
391 SkDebugf("Error: invalid input masks.\n"); 397 SkDebugf("Error: invalid input masks.\n");
392 return NULL; 398 return NULL;
393 } 399 }
394 400
395 // Process the color table 401 // Calculate the number of bytes read so far
396 uint32_t colorBytes = 0; 402 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
397 SkPMColor* colorTable = NULL;
398 if (bitsPerPixel < 16) {
399 // Verify the number of colors for the color table
400 const uint32_t maxColors = 1 << bitsPerPixel;
401 // Zero is a default for maxColors
402 // Also set numColors to maxColors when input is too large
403 if (numColors <= 0 || numColors > maxColors) {
404 numColors = maxColors;
405 }
406 colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
407
408 // Construct the color table
409 colorBytes = numColors * bytesPerColor;
410 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
411 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
412 SkDebugf("Error: unable to read color table.\n");
413 return NULL;
414 }
415
416 // Fill in the color table (colors are stored unpremultiplied)
417 uint32_t i = 0;
418 for (; i < numColors; i++) {
419 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
420 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
421 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
422 uint8_t alpha = 0xFF;
423 if (kOpaque_SkAlphaType != alphaType) {
424 alpha = (inputMasks.alpha >> 24) &
425 get_byte(cBuffer.get(), i*bytesPerColor + 3);
426 }
427 // Store the unpremultiplied color
428 colorTable[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
429 }
430
431 // To avoid segmentation faults on bad pixel data, fill the end of the
432 // color table with black. This is the same the behavior as the
433 // chromium decoder.
434 for (; i < maxColors; i++) {
435 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
436 }
437 }
438
439 // Ensure that the stream now points to the start of the pixel array
440 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
441
442 // Check that we have not read past the pixel array offset
443 if(bytesRead > offset) {
444 // This may occur on OS 2.1 and other old versions where the color
445 // table defaults to max size, and the bmp tries to use a smaller color
446 // table. This is invalid, and our decision is to indicate an error,
447 // rather than try to guess the intended size of the color table and
448 // rewind the stream to display the image.
449 SkDebugf("Error: pixel data offset less than header size.\n");
450 return NULL;
451 }
452
453 // Skip to the start of the pixel array
454 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
455 SkDebugf("Error: unable to skip to image data.\n");
456 return NULL;
457 }
458
459 // Remaining bytes is only used for RLE
460 const int remainingBytes = totalBytes - offset;
461 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
462 SkDebugf("Error: RLE requires valid input size.\n");
463 return NULL;
464 }
465 403
466 // Return the codec 404 // Return the codec
467 // We will use ImageInfo to store width, height, and alpha type. We will 405 // We will use ImageInfo to store width, height, and alpha type. We will
468 // choose kN32_SkColorType as the input color type because that is the 406 // set color type to kN32_SkColorType because that should be the default
469 // expected choice for a destination color type. In reality, the input 407 // output.
470 // color type has many possible formats.
471 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 408 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
472 kN32_SkColorType, alphaType); 409 kN32_SkColorType, alphaType);
473 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 410 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
474 inputFormat, masks.detach(), colorTable, 411 inputFormat, masks.detach(), numColors,
475 rowOrder, remainingBytes)); 412 bytesPerColor, offset, bytesRead,
413 rowOrder, RLEBytes));
476 } 414 }
477 415
478 /* 416 /*
479 * 417 *
480 * Creates an instance of the decoder 418 * Creates an instance of the decoder
481 * Called only by NewFromStream 419 * Called only by NewFromStream
482 * 420 *
483 */ 421 */
484 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, 422 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
485 uint16_t bitsPerPixel, BitmapInputFormat inputFormat, 423 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
486 SkMasks* masks, SkPMColor* colorTable, 424 SkMasks* masks, uint32_t numColors,
487 RowOrder rowOrder, 425 uint32_t bytesPerColor, uint32_t offset,
488 const uint32_t remainingBytes) 426 uint32_t bytesRead, RowOrder rowOrder, uint32_t RLEBytes)
489 : INHERITED(info, stream) 427 : INHERITED(info, stream)
490 , fBitsPerPixel(bitsPerPixel) 428 , fBitsPerPixel(bitsPerPixel)
491 , fInputFormat(inputFormat) 429 , fInputFormat(inputFormat)
492 , fMasks(masks) 430 , fMasks(masks)
493 , fColorTable(colorTable) 431 , fColorTable(NULL)
432 , fNumColors(numColors)
433 , fBytesPerColor(bytesPerColor)
434 , fBytesRead(bytesRead)
435 , fOffset(offset)
494 , fRowOrder(rowOrder) 436 , fRowOrder(rowOrder)
495 , fRemainingBytes(remainingBytes) 437 , fRLEBytes(RLEBytes)
496 {} 438 {}
497 439
498 /* 440 /*
499 * 441 *
500 * Initiates the bitmap decode 442 * Initiates the bitmap decode
501 * 443 *
502 */ 444 */
503 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 445 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
504 void* dst, size_t dstRowBytes, 446 void* dst, size_t dstRowBytes,
505 const Options&, 447 const Options&,
506 SkPMColor*, int*) { 448 SkPMColor*, int*) {
449 // Check for proper input and output formats
507 if (!this->rewindIfNeeded()) { 450 if (!this->rewindIfNeeded()) {
508 return kCouldNotRewind; 451 return kCouldNotRewind;
509 } 452 }
510 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) { 453 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) {
511 SkDebugf("Error: scaling not supported.\n"); 454 SkDebugf("Error: scaling not supported.\n");
512 return kInvalidScale; 455 return kInvalidScale;
513 } 456 }
514 if (!conversion_possible(dstInfo, this->getOriginalInfo())) { 457 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
515 SkDebugf("Error: cannot convert input type to output type.\n"); 458 SkDebugf("Error: cannot convert input type to output type.\n");
516 return kInvalidConversion; 459 return kInvalidConversion;
517 } 460 }
518 461
462 // Create the color table if necessary and prepare the stream for decode
463 if (!createColorTable(dstInfo.alphaType())) {
464 SkDebugf("Error: could not create color table.\n");
465 return kInvalidInput;
466 }
467
468 // Perform the decode
519 switch (fInputFormat) { 469 switch (fInputFormat) {
520 case kBitMask_BitmapInputFormat: 470 case kBitMask_BitmapInputFormat:
521 return decodeMask(dstInfo, dst, dstRowBytes); 471 return decodeMask(dstInfo, dst, dstRowBytes);
522 case kRLE_BitmapInputFormat: 472 case kRLE_BitmapInputFormat:
523 return decodeRLE(dstInfo, dst, dstRowBytes); 473 return decodeRLE(dstInfo, dst, dstRowBytes);
524 case kStandard_BitmapInputFormat: 474 case kStandard_BitmapInputFormat:
525 return decode(dstInfo, dst, dstRowBytes); 475 return decode(dstInfo, dst, dstRowBytes);
526 default: 476 default:
527 SkASSERT(false); 477 SkASSERT(false);
528 return kInvalidInput; 478 return kInvalidInput;
529 } 479 }
530 } 480 }
531 481
532 /* 482 /*
533 * 483 *
484 * Process the color table for the bmp input
485 *
486 */
487 bool SkBmpCodec::createColorTable(SkAlphaType alphaType) {
488 SkAutoTDeleteArray<SkPMColor> colorTable(NULL);
489 uint32_t colorBytes = 0;
490 uint32_t maxColors = 0;
491 if (fBitsPerPixel < 16) {
492 // Allocate memory for a color table
493 maxColors = 1 << fBitsPerPixel;
494 colorTable.reset(SkNEW_ARRAY(SkPMColor, maxColors));
495
496 // Read the color table from the stream
497 colorBytes = fNumColors * fBytesPerColor;
498 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
499 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
500 SkDebugf("Error: unable to read color table.\n");
501 return NULL;
502 }
503
504 // Fill in the color table
505 uint32_t i = 0;
506 for (; i < fNumColors; i++) {
507 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
508 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
509 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
510 uint8_t alpha;
511 switch (alphaType) {
512 case kOpaque_SkAlphaType:
513 colorTable.get()[i] = SkPackARGB32NoCheck(0xFF, red, green,
514 blue);
515 break;
516 case kUnpremul_SkAlphaType:
517 alpha = (fMasks->getAlphaMask() >> 24) &
518 get_byte(cBuffer.get(), i*fBytesPerColor + 3);
519 colorTable.get()[i] = SkPackARGB32NoCheck(alpha, red, green,
520 blue);
521 break;
522 case kPremul_SkAlphaType:
523 alpha = (fMasks->getAlphaMask() >> 24) &
524 get_byte(cBuffer.get(), i*fBytesPerColor + 3);
525 colorTable.get()[i] = SkPreMultiplyARGB(alpha, red, green,
526 blue);
527 break;
528 default:
529 // This should not be reached because conversion possible
530 // should fail if the alpha type is not one of the above
531 // values.
532 SkASSERT(false);
533 break;
534 }
535 }
536
537 // To avoid segmentation faults on bad pixel data, fill the end of the
538 // color table with black. This is the same the behavior as the
539 // chromium decoder.
540 for (; i < maxColors; i++) {
541 colorTable.get()[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
542 }
543 }
544
545 // Calculate the number of bytes read so far (including the color table)
546 fBytesRead += colorBytes;
547
548 // Check that we have not read past the pixel array offset
549 if(fBytesRead > fOffset) {
550 // This may occur on OS 2.1 and other old versions where the color
551 // table defaults to max size, and the bmp tries to use a smaller color
552 // table. This is invalid, and our decision is to indicate an error,
553 // rather than try to guess the intended size of the color table.
554 SkDebugf("Error: pixel data offset less than header size.\n");
555 return NULL;
556 }
557
558 // After reading the color table, skip to the start of the pixel array
559 if (stream()->skip(fOffset - fBytesRead) != fOffset - fBytesRead) {
560 SkDebugf("Error: unable to skip to image data.\n");
561 return false;
562 }
563
564 // Set the color table and return true on success
565 fColorTable.reset(
566 SkNEW_ARGS(SkColorTable, (colorTable.detach(), maxColors)));
scroggo 2015/03/17 20:02:58 Unfortunately, this constructor doesn't do what yo
msarett 2015/03/18 13:02:52 Yeah I had no idea. This should be better.
567 return true;
568 }
569
570 /*
571 *
534 * Performs the bitmap decoding for bit masks input format 572 * Performs the bitmap decoding for bit masks input format
535 * 573 *
536 */ 574 */
537 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 575 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
538 void* dst, size_t dstRowBytes) { 576 void* dst, size_t dstRowBytes) {
539 // Set constant values 577 // Set constant values
540 const int width = dstInfo.width(); 578 const int width = dstInfo.width();
541 const int height = dstInfo.height(); 579 const int height = dstInfo.height();
542 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 580 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
543 581
544 // Allocate space for a row buffer and a source for the swizzler 582 // Allocate a buffer large enough to hold the full input stream
545 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 583 SkAutoTDeleteArray<uint8_t>
584 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
585 uint8_t* srcRow = srcBuffer.get();
546 586
547 // Get the destination start row and delta 587 // Get the destination start row and delta
588 SkPMColor* dstStart;
548 SkPMColor* dstRow; 589 SkPMColor* dstRow;
549 int delta; 590 int delta;
550 if (kTopDown_RowOrder == fRowOrder) { 591 if (kTopDown_RowOrder == fRowOrder) {
551 dstRow = (SkPMColor*) dst; 592 dstStart = (SkPMColor*) dst;
593 dstRow = dstStart;
552 delta = (int) dstRowBytes; 594 delta = (int) dstRowBytes;
553 } else { 595 } else {
554 dstRow = (SkPMColor*) SkTAddOffset<void>(dst, (height-1) * dstRowBytes); 596 dstStart = (SkPMColor*) SkTAddOffset<void>(
597 dst, (height - 1) * dstRowBytes);
598 dstRow = dstStart;
555 delta = -((int) dstRowBytes); 599 delta = -((int) dstRowBytes);
556 } 600 }
557 601
558 // Create the swizzler 602 // Create the swizzler
559 SkMaskSwizzler* swizzler = SkMaskSwizzler::CreateMaskSwizzler( 603 SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
560 dstInfo, fMasks, fBitsPerPixel); 604 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, fMasks, fBitsPerPixel));
561 605
562 // Iterate over rows of the image 606 // Iterate over rows of the image
563 bool transparent = true; 607 bool transparent = true;
564 for (int y = 0; y < height; y++) { 608 for (int y = 0; y < height; y++) {
565 // Read a row of the input 609 // Read a row of the input
566 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 610 if (stream()->read(srcRow, rowBytes) != rowBytes) {
567 SkDebugf("Warning: incomplete input stream.\n"); 611 SkDebugf("Warning: incomplete input stream.\n");
568 return kIncompleteInput; 612 return kIncompleteInput;
569 } 613 }
570 614
571 // Decode the row in destination format 615 // Decode the row in destination format
572 SkSwizzler::ResultAlpha r = swizzler->next(dstRow, srcBuffer.get()); 616 SkSwizzler::ResultAlpha r = maskSwizzler->next(dstRow, srcRow);
573 transparent &= SkSwizzler::IsTransparent(r); 617 transparent &= SkSwizzler::IsTransparent(r);
574 618
575 // Move to the next row 619 // Move to the next row
576 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta); 620 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
621 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
577 } 622 }
578 623
579 // Some fully transparent bmp images are intended to be opaque. Here, we 624 // Some fully transparent bmp images are intended to be opaque. Here, we
580 // correct for this possibility. 625 // correct for this possibility.
581 dstRow = (SkPMColor*) dst;
582 if (transparent) { 626 if (transparent) {
627 const SkImageInfo& opaqueInfo =
628 dstInfo.makeAlphaType(kOpaque_SkAlphaType);
629 SkAutoTDelete<SkMaskSwizzler> opaqueSwizzler(
630 SkMaskSwizzler::CreateMaskSwizzler(opaqueInfo, fMasks,
631 fBitsPerPixel));
632 srcRow = srcBuffer.get();
633 dstRow = dstStart;
583 for (int y = 0; y < height; y++) { 634 for (int y = 0; y < height; y++) {
584 for (int x = 0; x < width; x++) { 635 // Decode the row in new format
585 dstRow[x] |= 0xFF000000; 636 opaqueSwizzler->next(dstRow, srcRow);
586 } 637
587 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes); 638 // Move to the next row
639 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
640 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
588 } 641 }
589 } 642 }
590 643
591 // Finished decoding the entire image 644 // Finished decoding the entire image
592 return kSuccess; 645 return kSuccess;
593 } 646 }
594 647
595 /* 648 /*
596 * 649 *
597 * Set an RLE pixel using the color table 650 * Set an RLE pixel using the color table
598 * 651 *
599 */ 652 */
600 void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes, int height, 653 void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes,
601 uint32_t x, uint32_t y, uint8_t index) { 654 const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
655 uint8_t index) {
656 // Set the row
657 int height = dstInfo.height();
658 int row;
602 if (kBottomUp_RowOrder == fRowOrder) { 659 if (kBottomUp_RowOrder == fRowOrder) {
603 y = height - y - 1; 660 row = height - y - 1;
661 } else {
662 row = y;
604 } 663 }
605 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes); 664
606 dstRow[x] = fColorTable.get()[index]; 665 // Set the pixel based on destination color type
666 switch (dstInfo.colorType()) {
667 case kN32_SkColorType: {
668 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst,
669 row * (int) dstRowBytes);
670 dstRow[x] = fColorTable.get()[0][index];
scroggo 2015/03/17 20:02:58 Why do you need [0]? Does this get around the fac
msarett 2015/03/18 13:02:52 Yeah I think that's a little better. I kept going
scroggo 2015/03/18 13:33:20 Haha, yeah, it's an unfortunate bit of ambiguity t
671 break;
672 }
673 case kRGB_565_SkColorType: {
674 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
675 row * (int) dstRowBytes);
676 dstRow[x] = SkPixel32ToPixel16(fColorTable.get()[0][index]);
677 break;
678 }
679 default:
680 // This case should not be reached. We should catch an invalid
681 // color type when we check that the conversion is possible.
682 SkASSERT(false);
683 break;
684 }
607 } 685 }
608 686
609 /* 687 /*
688 *
689 * Set an RLE pixel from R, G, B values
690 *
691 */
692 void SkBmpCodec::setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes,
693 const SkImageInfo& dstInfo, uint32_t x,
694 uint32_t y, uint8_t red, uint8_t green,
695 uint8_t blue) {
696 // Set the row
697 int height = dstInfo.height();
698 int row;
699 if (kBottomUp_RowOrder == fRowOrder) {
700 row = height - y - 1;
701 } else {
702 row = y;
703 }
704
705 // Set the pixel based on destination color type
706 switch (dstInfo.colorType()) {
707 case kN32_SkColorType: {
708 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst,
709 row * (int) dstRowBytes);
710 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
711 break;
712 }
713 case kRGB_565_SkColorType: {
714 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
715 row * (int) dstRowBytes);
716 dstRow[x] = SkPack888ToRGB16(red, green, blue);
717 break;
718 }
719 default:
720 // This case should not be reached. We should catch an invalid
721 // color type when we check that the conversion is possible.
722 SkASSERT(false);
723 break;
724 }
725 }
726
727 /*
610 * 728 *
611 * Performs the bitmap decoding for RLE input format 729 * Performs the bitmap decoding for RLE input format
612 * RLE decoding is performed all at once, rather than a one row at a time 730 * RLE decoding is performed all at once, rather than a one row at a time
613 * 731 *
614 */ 732 */
615 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, 733 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
616 void* dst, size_t dstRowBytes) { 734 void* dst, size_t dstRowBytes) {
617 // Set RLE flags 735 // Set RLE flags
618 static const uint8_t RLE_ESCAPE = 0; 736 static const uint8_t RLE_ESCAPE = 0;
619 static const uint8_t RLE_EOL = 0; 737 static const uint8_t RLE_EOL = 0;
620 static const uint8_t RLE_EOF = 1; 738 static const uint8_t RLE_EOF = 1;
621 static const uint8_t RLE_DELTA = 2; 739 static const uint8_t RLE_DELTA = 2;
622 740
623 // Set constant values 741 // Set constant values
624 const int width = dstInfo.width(); 742 const int width = dstInfo.width();
625 const int height = dstInfo.height(); 743 const int height = dstInfo.height();
626 744
627 // Input buffer parameters 745 // Input buffer parameters
628 uint32_t currByte = 0; 746 uint32_t currByte = 0;
629 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes)); 747 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
630 size_t totalBytes = stream()->read(buffer.get(), fRemainingBytes); 748 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
631 if ((uint32_t) totalBytes < fRemainingBytes) { 749 if (totalBytes < fRLEBytes) {
632 SkDebugf("Warning: incomplete RLE file.\n"); 750 SkDebugf("Warning: incomplete RLE file.\n");
633 } else if (totalBytes <= 0) { 751 } else if (totalBytes <= 0) {
634 SkDebugf("Error: could not read RLE image data.\n"); 752 SkDebugf("Error: could not read RLE image data.\n");
635 return kInvalidInput; 753 return kInvalidInput;
636 } 754 }
637 755
638 // Destination parameters 756 // Destination parameters
639 int x = 0; 757 int x = 0;
640 int y = 0; 758 int y = 0;
641 // If the code skips pixels, remaining pixels are transparent or black 759 // If the code skips pixels, remaining pixels are transparent or black
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 fBitsPerPixel); 818 fBitsPerPixel);
701 // Abort if setting numPixels moves us off the edge of the 819 // Abort if setting numPixels moves us off the edge of the
702 // image. Also abort if there are not enough bytes 820 // image. Also abort if there are not enough bytes
703 // remaining in the stream to set numPixels. 821 // remaining in the stream to set numPixels.
704 if (x + numPixels > width || 822 if (x + numPixels > width ||
705 (int) totalBytes - currByte < SkAlign2(rowBytes)) { 823 (int) totalBytes - currByte < SkAlign2(rowBytes)) {
706 SkDebugf("Warning: invalid RLE input.\n"); 824 SkDebugf("Warning: invalid RLE input.\n");
707 return kIncompleteInput; 825 return kIncompleteInput;
708 } 826 }
709 // Set numPixels number of pixels 827 // Set numPixels number of pixels
710 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
711 dstPtr, y * dstRowBytes);
712 while (numPixels > 0) { 828 while (numPixels > 0) {
713 switch(fBitsPerPixel) { 829 switch(fBitsPerPixel) {
714 case 4: { 830 case 4: {
715 SkASSERT(currByte < totalBytes); 831 SkASSERT(currByte < totalBytes);
716 uint8_t val = buffer.get()[currByte++]; 832 uint8_t val = buffer.get()[currByte++];
717 setRLEPixel(dstPtr, dstRowBytes, height, x++, y, 833 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++,
718 val >> 4); 834 y, val >> 4);
719 numPixels--; 835 numPixels--;
720 if (numPixels != 0) { 836 if (numPixels != 0) {
721 setRLEPixel(dstPtr, dstRowBytes, height, 837 setRLEPixel(dstPtr, dstRowBytes, dstInfo,
722 x++, y, val & 0xF); 838 x++, y, val & 0xF);
723 numPixels--; 839 numPixels--;
724 } 840 }
725 break; 841 break;
726 } 842 }
727 case 8: 843 case 8:
728 SkASSERT(currByte < totalBytes); 844 SkASSERT(currByte < totalBytes);
729 setRLEPixel(dstPtr, dstRowBytes, height, x++, y, 845 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++,
730 buffer.get()[currByte++]); 846 y, buffer.get()[currByte++]);
731 numPixels--; 847 numPixels--;
732 break; 848 break;
733 case 24: { 849 case 24: {
734 SkASSERT(currByte + 2 < totalBytes); 850 SkASSERT(currByte + 2 < totalBytes);
735 uint8_t blue = buffer.get()[currByte++]; 851 uint8_t blue = buffer.get()[currByte++];
736 uint8_t green = buffer.get()[currByte++]; 852 uint8_t green = buffer.get()[currByte++];
737 uint8_t red = buffer.get()[currByte++]; 853 uint8_t red = buffer.get()[currByte++];
738 SkPMColor color = SkPackARGB32NoCheck( 854 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo,
739 0xFF, red, green, blue); 855 x++, y, red, green, blue);
740 dstRow[x++] = color;
741 numPixels--; 856 numPixels--;
742 } 857 }
743 default: 858 default:
744 SkASSERT(false); 859 SkASSERT(false);
745 return kInvalidInput; 860 return kInvalidInput;
746 } 861 }
747 } 862 }
748 // Skip a byte if necessary to maintain alignment 863 // Skip a byte if necessary to maintain alignment
749 if (!SkIsAlign2(rowBytes)) { 864 if (!SkIsAlign2(rowBytes)) {
750 currByte++; 865 currByte++;
(...skipping 13 matching lines...) Expand all
764 // color. 879 // color.
765 if ((int) totalBytes - currByte < 2) { 880 if ((int) totalBytes - currByte < 2) {
766 SkDebugf("Warning: incomplete RLE input\n"); 881 SkDebugf("Warning: incomplete RLE input\n");
767 return kIncompleteInput; 882 return kIncompleteInput;
768 } 883 }
769 884
770 // Fill the pixels up to endX with the specified color 885 // Fill the pixels up to endX with the specified color
771 uint8_t blue = task; 886 uint8_t blue = task;
772 uint8_t green = buffer.get()[currByte++]; 887 uint8_t green = buffer.get()[currByte++];
773 uint8_t red = buffer.get()[currByte++]; 888 uint8_t red = buffer.get()[currByte++];
774 SkPMColor color = SkPackARGB32NoCheck(0xFF, red, green, blue);
775 SkPMColor* dstRow =
776 SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
777 while (x < endX) { 889 while (x < endX) {
778 dstRow[x++] = color; 890 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red,
891 green, blue);
779 } 892 }
780 } else { 893 } else {
781 // In RLE8 or RLE4, the second byte read gives the index in the 894 // In RLE8 or RLE4, the second byte read gives the index in the
782 // color table to look up the pixel color. 895 // color table to look up the pixel color.
783 // RLE8 has one color index that gets repeated 896 // RLE8 has one color index that gets repeated
784 // RLE4 has two color indexes in the upper and lower 4 bits of 897 // RLE4 has two color indexes in the upper and lower 4 bits of
785 // the bytes, which are alternated 898 // the bytes, which are alternated
786 uint8_t indices[2] = { task, task }; 899 uint8_t indices[2] = { task, task };
787 if (4 == fBitsPerPixel) { 900 if (4 == fBitsPerPixel) {
788 indices[0] >>= 4; 901 indices[0] >>= 4;
789 indices[1] &= 0xf; 902 indices[1] &= 0xf;
790 } 903 }
791 904
792 // Set the indicated number of pixels 905 // Set the indicated number of pixels
793 for (int which = 0; x < endX; x++) { 906 for (int which = 0; x < endX; x++) {
794 setRLEPixel(dstPtr, dstRowBytes, height, x, y, 907 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x, y,
795 indices[which]); 908 indices[which]);
796 which = !which; 909 which = !which;
797 } 910 }
798 } 911 }
799 } 912 }
800 } 913 }
801 } 914 }
802 915
803 /* 916 /*
804 * 917 *
805 * Performs the bitmap decoding for standard input format 918 * Performs the bitmap decoding for standard input format
806 * 919 *
807 */ 920 */
808 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, 921 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
809 void* dst, size_t dstRowBytes) { 922 void* dst, size_t dstRowBytes) {
810 // Set constant values 923 // Set constant values
811 const int width = dstInfo.width(); 924 const int width = dstInfo.width();
812 const int height = dstInfo.height(); 925 const int height = dstInfo.height();
813 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 926 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
814 const uint32_t alphaMask = fMasks->getAlphaMask();
815 927
816 // Get swizzler configuration 928 // Get swizzler configuration
817 SkSwizzler::SrcConfig config; 929 SkSwizzler::SrcConfig config;
818 switch (fBitsPerPixel) { 930 switch (fBitsPerPixel) {
819 case 1: 931 case 1:
820 config = SkSwizzler::kIndex1; 932 config = SkSwizzler::kIndex1;
821 break; 933 break;
822 case 2: 934 case 2:
823 config = SkSwizzler::kIndex2; 935 config = SkSwizzler::kIndex2;
824 break; 936 break;
825 case 4: 937 case 4:
826 config = SkSwizzler::kIndex4; 938 config = SkSwizzler::kIndex4;
827 break; 939 break;
828 case 8: 940 case 8:
829 config = SkSwizzler::kIndex; 941 config = SkSwizzler::kIndex;
830 break; 942 break;
831 case 24: 943 case 24:
832 config = SkSwizzler::kBGR; 944 config = SkSwizzler::kBGR;
833 break; 945 break;
834 case 32: 946 case 32:
835 if (0 == alphaMask) { 947 if (kOpaque_SkAlphaType == dstInfo.alphaType()) {
836 config = SkSwizzler::kBGRX; 948 config = SkSwizzler::kBGRX;
837 } else { 949 } else {
838 config = SkSwizzler::kBGRA; 950 config = SkSwizzler::kBGRA;
839 } 951 }
840 break; 952 break;
841 default: 953 default:
842 SkASSERT(false); 954 SkASSERT(false);
843 return kInvalidInput; 955 return kInvalidInput;
844 } 956 }
845 957
846 // Create swizzler 958 // Create swizzler
847 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(), 959 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
848 dstInfo, dst, dstRowBytes, SkImageGenerator::kNo_ZeroInitialized); 960 fColorTable.get()->readColors(), dstInfo, dst, dstRowBytes,
scroggo 2015/03/17 20:02:58 SkAutoTDelete implements operator->, so you can dr
msarett 2015/03/18 13:02:52 Done.
961 SkImageGenerator::kNo_ZeroInitialized));
849 962
850 // Allocate space for a row buffer and a source for the swizzler 963 // Allocate space for a row buffer and a source for the swizzler
851 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 964 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
852 965
853 // Iterate over rows of the image 966 // Iterate over rows of the image
854 // FIXME: bool transparent = true; 967 // FIXME: bool transparent = true;
855 for (int y = 0; y < height; y++) { 968 for (int y = 0; y < height; y++) {
856 // Read a row of the input 969 // Read a row of the input
857 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 970 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
858 SkDebugf("Warning: incomplete input stream.\n"); 971 SkDebugf("Warning: incomplete input stream.\n");
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 } 1008 }
896 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes); 1009 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
897 } 1010 }
898 } 1011 }
899 } 1012 }
900 */ 1013 */
901 1014
902 // Finished decoding the entire image 1015 // Finished decoding the entire image
903 return kSuccess; 1016 return kSuccess;
904 } 1017 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkMaskSwizzler.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698