| OLD | NEW | 
|---|
| 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 "SkBmpCodec.h" | 8 #include "SkBmpCodec.h" | 
| 9 #include "SkBmpMaskCodec.h" | 9 #include "SkBmpMaskCodec.h" | 
| 10 #include "SkBmpRLECodec.h" | 10 #include "SkBmpRLECodec.h" | 
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 255         height = (int) get_short(iBuffer.get(), 2); | 255         height = (int) get_short(iBuffer.get(), 2); | 
| 256         bitsPerPixel = get_short(iBuffer.get(), 6); | 256         bitsPerPixel = get_short(iBuffer.get(), 6); | 
| 257         bytesPerColor = 3; | 257         bytesPerColor = 3; | 
| 258     } else { | 258     } else { | 
| 259         // There are no valid bmp headers | 259         // There are no valid bmp headers | 
| 260         SkCodecPrintf("Error: second bitmap header size is invalid.\n"); | 260         SkCodecPrintf("Error: second bitmap header size is invalid.\n"); | 
| 261         return false; | 261         return false; | 
| 262     } | 262     } | 
| 263 | 263 | 
| 264     // Check for valid dimensions from header | 264     // Check for valid dimensions from header | 
| 265     SkScanlineDecoder::SkScanlineOrder rowOrder = SkScanlineDecoder::kBottomUp_S
     kScanlineOrder; | 265     SkCodec::SkScanlineOrder rowOrder = SkCodec::kBottomUp_SkScanlineOrder; | 
| 266     if (height < 0) { | 266     if (height < 0) { | 
| 267         height = -height; | 267         height = -height; | 
| 268         rowOrder = SkScanlineDecoder::kTopDown_SkScanlineOrder; | 268         rowOrder = SkCodec::kTopDown_SkScanlineOrder; | 
| 269     } | 269     } | 
| 270     // The height field for bmp in ico is double the actual height because they | 270     // The height field for bmp in ico is double the actual height because they | 
| 271     // contain an XOR mask followed by an AND mask | 271     // contain an XOR mask followed by an AND mask | 
| 272     if (inIco) { | 272     if (inIco) { | 
| 273         height /= 2; | 273         height /= 2; | 
| 274     } | 274     } | 
| 275     if (width <= 0 || height <= 0) { | 275     if (width <= 0 || height <= 0) { | 
| 276         // TODO: Decide if we want to disable really large bmps as well. | 276         // TODO: Decide if we want to disable really large bmps as well. | 
| 277         // https://code.google.com/p/skia/issues/detail?id=3617 | 277         // https://code.google.com/p/skia/issues/detail?id=3617 | 
| 278         SkCodecPrintf("Error: invalid bitmap dimensions.\n"); | 278         SkCodecPrintf("Error: invalid bitmap dimensions.\n"); | 
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 524         // codec has taken ownership of stream, so we do not need to | 524         // codec has taken ownership of stream, so we do not need to | 
| 525         // delete it. | 525         // delete it. | 
| 526         SkASSERT(codec); | 526         SkASSERT(codec); | 
| 527         streamDeleter.detach(); | 527         streamDeleter.detach(); | 
| 528         return codec; | 528         return codec; | 
| 529     } | 529     } | 
| 530     return nullptr; | 530     return nullptr; | 
| 531 } | 531 } | 
| 532 | 532 | 
| 533 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, | 533 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, | 
| 534         uint16_t bitsPerPixel, SkScanlineDecoder::SkScanlineOrder rowOrder) | 534         uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) | 
| 535     : INHERITED(info, stream) | 535     : INHERITED(info, stream) | 
| 536     , fBitsPerPixel(bitsPerPixel) | 536     , fBitsPerPixel(bitsPerPixel) | 
| 537     , fRowOrder(rowOrder) | 537     , fRowOrder(rowOrder) | 
| 538 {} | 538 {} | 
| 539 | 539 | 
| 540 bool SkBmpCodec::onRewind() { | 540 bool SkBmpCodec::onRewind() { | 
| 541     return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); | 541     return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); | 
| 542 } | 542 } | 
| 543 | 543 | 
| 544 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) { | 544 int32_t SkBmpCodec::getDstRow(int32_t y, int32_t height) const { | 
| 545     if (SkScanlineDecoder::kTopDown_SkScanlineOrder == fRowOrder) { | 545     if (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) { | 
| 546         return y; | 546         return y; | 
| 547     } | 547     } | 
| 548     SkASSERT(SkScanlineDecoder::kBottomUp_SkScanlineOrder == fRowOrder); | 548     SkASSERT(SkCodec::kBottomUp_SkScanlineOrder == fRowOrder); | 
| 549     return height - y - 1; | 549     return height - y - 1; | 
| 550 } | 550 } | 
| 551 | 551 | 
| 552 /* | 552 /* | 
| 553  * Get the destination row to start filling from | 553  * Get the destination row to start filling from | 
| 554  * Used to fill the remainder of the image on incomplete input for bmps | 554  * Used to fill the remainder of the image on incomplete input for bmps | 
| 555  * This is tricky since bmps may be kTopDown or kBottomUp.  For kTopDown, | 555  * This is tricky since bmps may be kTopDown or kBottomUp.  For kTopDown, | 
| 556  * we start filling from where we left off, but for kBottomUp we start | 556  * we start filling from where we left off, but for kBottomUp we start | 
| 557  * filling at the top of the image. | 557  * filling at the top of the image. | 
| 558  */ | 558  */ | 
| 559 void* SkBmpCodec::getDstStartRow(void* dst, size_t dstRowBytes, int32_t y) const
      { | 559 void* SkBmpCodec::getDstStartRow(void* dst, size_t dstRowBytes, int32_t y) const
      { | 
| 560     return (SkScanlineDecoder::kTopDown_SkScanlineOrder == fRowOrder) ? | 560     return (SkCodec::kTopDown_SkScanlineOrder == fRowOrder) ? | 
| 561             SkTAddOffset<void*>(dst, y * dstRowBytes) : dst; | 561             SkTAddOffset<void*>(dst, y * dstRowBytes) : dst; | 
| 562 } | 562 } | 
| 563 | 563 | 
| 564 /* | 564 /* | 
| 565  * Compute the number of colors in the color table | 565  * Compute the number of colors in the color table | 
| 566  */ | 566  */ | 
| 567 uint32_t SkBmpCodec::computeNumColors(uint32_t numColors) { | 567 uint32_t SkBmpCodec::computeNumColors(uint32_t numColors) { | 
| 568     // Zero is a default for maxColors | 568     // Zero is a default for maxColors | 
| 569     // Also set numColors to maxColors when it is too large | 569     // Also set numColors to maxColors when it is too large | 
| 570     uint32_t maxColors = 1 << fBitsPerPixel; | 570     uint32_t maxColors = 1 << fBitsPerPixel; | 
| 571     if (numColors == 0 || numColors >= maxColors) { | 571     if (numColors == 0 || numColors >= maxColors) { | 
| 572         return maxColors; | 572         return maxColors; | 
| 573     } | 573     } | 
| 574     return numColors; | 574     return numColors; | 
| 575 } | 575 } | 
| 576 | 576 | 
| 577 /* | 577 SkCodec::Result SkBmpCodec::onStart(const SkImageInfo& dstInfo, const SkCodec::O
     ptions& options, | 
| 578  * Scanline decoder for bmps | 578         SkPMColor inputColorPtr[], int* inputColorCount) { | 
| 579  */ | 579     if (!this->rewindIfNeeded()) { | 
| 580 class SkBmpScanlineDecoder : public SkScanlineDecoder { | 580         return kCouldNotRewind; | 
| 581 public: | 581     } | 
| 582     SkBmpScanlineDecoder(SkBmpCodec* codec) | 582     if (options.fSubset) { | 
| 583         : INHERITED(codec->getInfo()) | 583         // Subsets are not supported. | 
| 584         , fCodec(codec) | 584         return kUnimplemented; | 
| 585     {} | 585     } | 
| 586 | 586     if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 
| 587     SkEncodedFormat onGetEncodedFormat() const override { | 587         if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI
     nfo)) { | 
| 588         return kBMP_SkEncodedFormat; | 588             return SkCodec::kInvalidScale; | 
|  | 589         } | 
|  | 590     } | 
|  | 591     if (!conversion_possible(dstInfo, this->getInfo())) { | 
|  | 592         SkCodecPrintf("Error: cannot convert input type to output type.\n"); | 
|  | 593         return kInvalidConversion; | 
| 589     } | 594     } | 
| 590 | 595 | 
| 591     SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& 
     options, | 596     return prepareToDecode(dstInfo, options, inputColorPtr, inputColorCount); | 
| 592                             SkPMColor inputColorPtr[], int* inputColorCount) ove
     rride { | 597 } | 
| 593         if (!fCodec->rewindIfNeeded()) { |  | 
| 594             return SkCodec::kCouldNotRewind; |  | 
| 595         } |  | 
| 596         if (options.fSubset) { |  | 
| 597             // Subsets are not supported. |  | 
| 598             return SkCodec::kUnimplemented; |  | 
| 599         } |  | 
| 600         if (dstInfo.dimensions() != this->getInfo().dimensions()) { |  | 
| 601             if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), 
     dstInfo)) { |  | 
| 602                 return SkCodec::kInvalidScale; |  | 
| 603             } |  | 
| 604         } |  | 
| 605         if (!conversion_possible(dstInfo, this->getInfo())) { |  | 
| 606             SkCodecPrintf("Error: cannot convert input type to output type.\n"); |  | 
| 607             return SkCodec::kInvalidConversion; |  | 
| 608         } |  | 
| 609 | 598 | 
| 610         return fCodec->prepareToDecode(dstInfo, options, inputColorPtr, inputCol
     orCount); | 599 SkCodec::Result SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes
     ) { | 
| 611     } | 600     // Create a new image info representing the portion of the image to decode | 
|  | 601     SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), count)
     ; | 
| 612 | 602 | 
| 613     SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri
     de { | 603     // Decode the requested rows | 
| 614         // Create a new image info representing the portion of the image to deco
     de | 604     return this->decodeRows(rowInfo, dst, rowBytes, this->options()); | 
| 615         SkImageInfo rowInfo = this->dstInfo().makeWH(this->dstInfo().width(), co
     unt); | 605 } | 
| 616 | 606 | 
| 617         // Decode the requested rows | 607 int SkBmpCodec::onGetY() const { | 
| 618         return fCodec->decodeRows(rowInfo, dst, rowBytes, this->options()); | 608     return this->getDstRow(this->INHERITED::onGetY(), this->dstInfo().height()); | 
| 619     } |  | 
| 620 |  | 
| 621     SkScanlineOrder onGetScanlineOrder() const override { |  | 
| 622         return fCodec->fRowOrder; |  | 
| 623     } |  | 
| 624 |  | 
| 625     int onGetY() const override { |  | 
| 626         return fCodec->getDstRow(this->INHERITED::onGetY(), this->dstInfo().heig
     ht()); |  | 
| 627     } |  | 
| 628 |  | 
| 629     // TODO(msarett): Override default skipping with something more clever. |  | 
| 630 |  | 
| 631 private: |  | 
| 632     SkAutoTDelete<SkBmpCodec> fCodec; |  | 
| 633 |  | 
| 634     typedef SkScanlineDecoder INHERITED; |  | 
| 635 }; |  | 
| 636 |  | 
| 637 SkScanlineDecoder* SkBmpCodec::NewSDFromStream(SkStream* stream) { |  | 
| 638     SkAutoTDelete<SkBmpCodec> codec(static_cast<SkBmpCodec*>(SkBmpCodec::NewFrom
     Stream(stream))); |  | 
| 639     if (!codec) { |  | 
| 640         return NULL; |  | 
| 641     } |  | 
| 642 |  | 
| 643     return new SkBmpScanlineDecoder(codec.detach()); |  | 
| 644 } | 609 } | 
| OLD | NEW | 
|---|