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

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

Powered by Google App Engine
This is Rietveld 408576698