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

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

Powered by Google App Engine
This is Rietveld 408576698