From 7aa846c6837f527067e7ab5fdeacdbd502696382 Mon Sep 17 00:00:00 2001 From: tomhudson Date: Tue, 24 Mar 2015 13:47:41 -0700 Subject: [PATCH] Revert of Enabling ico decoding with use of png and bmp decoders (patchset #10 id:280001 of https://codereview.chromium.org/1011343003/) Reason for revert: Reverting on suspicion of massive bot failures - possible command line too long? Original issue's description: > Enabling ico decoding with use of png and bmp decoders > > BUG=skia:3257 > > Committed: https://skia.googlesource.com/skia/+/15bfd075d38e4422a477e22940d06a137f66cc97 TBR=scroggo@google.com,reed@google.com,djsollen@google.com,msarett@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia:3257 Review URL: https://codereview.chromium.org/1022843005 --- dm/DM.cpp | 4 +- dm/DMSrcSink.cpp | 6 +- gyp/codec.gyp | 4 +- include/codec/SkCodec.h | 3 + src/codec/SkCodec.cpp | 2 - src/codec/SkCodec_libbmp.cpp | 216 ++++++++--------------------- src/codec/SkCodec_libbmp.h | 30 +---- src/codec/SkCodec_libico.cpp | 254 ----------------------------------- src/codec/SkCodec_libico.h | 62 --------- src/codec/SkCodec_libpng.cpp | 6 +- tools/dm_flags.py | 20 --- 11 files changed, 73 insertions(+), 534 deletions(-) delete mode 100644 src/codec/SkCodec_libico.cpp delete mode 100644 src/codec/SkCodec_libico.h diff --git a/dm/DM.cpp b/dm/DM.cpp index 44090ca1ce..833af0edba 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -146,9 +146,7 @@ static void push_src(const char* tag, Src* s) { static bool codec_supported(const char* ext) { // FIXME: Once other versions of SkCodec are available, we can add them to this // list (and eventually we can remove this check once they are all supported). - return strcmp(ext, "png") == 0 || strcmp(ext, "PNG") == 0 || - strcmp(ext, "bmp") == 0 || strcmp(ext, "BMP") == 0 || - strcmp(ext, "ico") == 0 || strcmp(ext, "ICO") == 0; + return strcmp(ext, "png") == 0 || strcmp(ext, "PNG") == 0; } static void gather_srcs() { diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index fe31d61ef0..638f670834 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -88,11 +88,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const { SkISize CodecSrc::size() const { SkAutoTUnref encoded(SkData::NewFromFileName(fPath.c_str())); SkAutoTDelete codec(SkCodec::NewFromData(encoded)); - if (NULL != codec) { - return codec->getInfo().dimensions(); - } else { - return SkISize::Make(0, 0); - } + return codec->getInfo().dimensions(); } Name CodecSrc::name() const { diff --git a/gyp/codec.gyp b/gyp/codec.gyp index c9e3ad88d5..ce601cca7d 100644 --- a/gyp/codec.gyp +++ b/gyp/codec.gyp @@ -13,13 +13,11 @@ 'include_dirs': [ '../include/codec', '../src/codec', - '../src/core', ], 'sources': [ '../src/codec/SkCodec.cpp', - '../src/codec/SkCodec_libbmp.cpp', - '../src/codec/SkCodec_libico.cpp', '../src/codec/SkCodec_libpng.cpp', + '../src/codec/SkCodec_libbmp.cpp', '../src/codec/SkMaskSwizzler.cpp', '../src/codec/SkMasks.cpp', '../src/codec/SkSwizzler.cpp', diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h index c3840354f1..ec4b3e1cc8 100644 --- a/include/codec/SkCodec.h +++ b/include/codec/SkCodec.h @@ -71,6 +71,9 @@ protected: } #endif + // Helper for subclasses. + const SkImageInfo& getOriginalInfo() { return fInfo; } + virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { // By default, scaling is not supported. return fInfo.dimensions(); diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index 0411e44069..12341f5929 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -8,7 +8,6 @@ #include "SkCodec.h" #include "SkData.h" #include "SkCodec_libbmp.h" -#include "SkCodec_libico.h" #include "SkCodec_libpng.h" #include "SkStream.h" @@ -19,7 +18,6 @@ struct DecoderProc { static const DecoderProc gDecoderProcs[] = { { SkPngCodec::IsPng, SkPngCodec::NewFromStream }, - { SkIcoCodec::IsIco, SkIcoCodec::NewFromStream }, { SkBmpCodec::IsBmp, SkBmpCodec::NewFromStream } }; diff --git a/src/codec/SkCodec_libbmp.cpp b/src/codec/SkCodec_libbmp.cpp index ac6cf3a443..e9551cbb6f 100644 --- a/src/codec/SkCodec_libbmp.cpp +++ b/src/codec/SkCodec_libbmp.cpp @@ -29,6 +29,9 @@ static bool conversion_possible(const SkImageInfo& dst, return src.alphaType() == dst.alphaType() || (kPremul_SkAlphaType == dst.alphaType() && kUnpremul_SkAlphaType == src.alphaType()); + case kRGB_565_SkColorType: + return src.alphaType() == dst.alphaType() && + kOpaque_SkAlphaType == dst.alphaType(); default: return false; } @@ -85,31 +88,11 @@ bool SkBmpCodec::IsBmp(SkStream* stream) { /* * * Assumes IsBmp was called and returned true - * Creates a bmp decoder + * Creates a bitmap decoder * Reads enough of the stream to determine the image format * */ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) { - return SkBmpCodec::NewFromStream(stream, false); -} - -/* - * - * Creates a bmp decoder for a bmp embedded in ico - * Reads enough of the stream to determine the image format - * - */ -SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) { - return SkBmpCodec::NewFromStream(stream, true); -} - -/* - * - * Creates a bmp decoder - * Reads enough of the stream to determine the image format - * - */ -SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { // Header size constants static const uint32_t kBmpHeaderBytes = 14; static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; @@ -123,68 +106,37 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { static const uint32_t kBmpInfoV5Bytes = 124; static const uint32_t kBmpMaskBytes = 12; - // The total bytes in the bmp file - // We only need to use this value for RLE decoding, so we will only - // check that it is valid in the RLE case. - uint32_t totalBytes; - // The offset from the start of the file where the pixel data begins - uint32_t offset; - // The size of the second (info) header in bytes - uint32_t infoBytes; - - // Bmps embedded in Icos skip the first Bmp header - if (!isIco) { - // Read the first header and the size of the second header - SkAutoTDeleteArray hBuffer( - SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); - if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != - kBmpHeaderBytesPlusFour) { - SkDebugf("Error: unable to read first bitmap header.\n"); - return NULL; - } + // Read the first header and the size of the second header + SkAutoTDeleteArray hBuffer( + SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); + if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != + kBmpHeaderBytesPlusFour) { + SkDebugf("Error: unable to read first bitmap header.\n"); + return NULL; + } - totalBytes = get_int(hBuffer.get(), 2); - offset = get_int(hBuffer.get(), 10); - if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { - SkDebugf("Error: invalid starting location for pixel data\n"); - return NULL; - } + // The total bytes in the bmp file + // We only need to use this value for RLE decoding, so we will only check + // that it is valid in the RLE case. + const uint32_t totalBytes = get_int(hBuffer.get(), 2); - // The size of the second (info) header in bytes - // The size is the first field of the second header, so we have already - // read the first four infoBytes. - infoBytes = get_int(hBuffer.get(), 14); - if (infoBytes < kBmpOS2V1Bytes) { - SkDebugf("Error: invalid second header size.\n"); - return NULL; - } - } else { - // This value is only used by RLE compression. Bmp in Ico files do not - // use RLE. If the compression field is incorrectly signaled as RLE, - // we will catch this and signal an error below. - totalBytes = 0; - - // Bmps in Ico cannot specify an offset. We will always assume that - // pixel data begins immediately after the color table. This value - // will be corrected below. - offset = 0; - - // Read the size of the second header - SkAutoTDeleteArray hBuffer( - SkNEW_ARRAY(uint8_t, 4)); - if (stream->read(hBuffer.get(), 4) != 4) { - SkDebugf("Error: unable to read size of second bitmap header.\n"); - return NULL; - } - infoBytes = get_int(hBuffer.get(), 0); - if (infoBytes < kBmpOS2V1Bytes) { - SkDebugf("Error: invalid second header size.\n"); - return NULL; - } + // The offset from the start of the file where the pixel data begins + const uint32_t offset = get_int(hBuffer.get(), 10); + if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { + SkDebugf("Error: invalid starting location for pixel data\n"); + return NULL; } - // We already read the first four bytes of the info header to get the size + // The size of the second (info) header in bytes + // The size is the first field of the second header, so we have already + // read the first four infoBytes. + const uint32_t infoBytes = get_int(hBuffer.get(), 14); + if (infoBytes < kBmpOS2V1Bytes) { + SkDebugf("Error: invalid second header size.\n"); + return NULL; + } const uint32_t infoBytesRemaining = infoBytes - 4; + hBuffer.free(); // Read the second header SkAutoTDeleteArray iBuffer( @@ -291,11 +243,6 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { height = -height; rowOrder = kTopDown_RowOrder; } - // The height field for bmp in ico is double the actual height because they - // contain an XOR mask followed by an AND mask - if (isIco) { - height /= 2; - } static const int kBmpMaxDim = 1 << 16; if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { // TODO: Decide if we want to support really large bmps. @@ -397,19 +344,16 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { // Most versions of bmps should be rendered as opaque. Either they do // not have an alpha channel, or they expect the alpha channel to be - // ignored. V3+ bmp files introduce an alpha mask and allow the creator + // ignored. V4+ bmp files introduce an alpha mask and allow the creator // of the image to use the alpha channels. However, many of these images - // leave the alpha channel blank and expect to be rendered as opaque. This - // is the case for almost all V3 images, so we render these as opaque. For - // V4+, we will use the alpha channel, and fix the image later if it turns - // out to be fully transparent. - // As an exception, V3 bmp-in-ico may use an alpha mask. + // leave the alpha channel blank and expect to be rendered as opaque. For + // this reason, we set the alpha type to kUnknown for V4+ bmps and figure + // out the alpha type during the decode. SkAlphaType alphaType = kOpaque_SkAlphaType; - if ((kInfoV3_BitmapHeaderType == headerType && isIco) || - kInfoV4_BitmapHeaderType == headerType || + if (kInfoV4_BitmapHeaderType == headerType || kInfoV5_BitmapHeaderType == headerType) { // Header types are matched based on size. If the header is - // V3+, we are guaranteed to be able to read at least this size. + // V4+, we are guaranteed to be able to read at least this size. SkASSERT(infoBytesRemaining > 52); inputMasks.alpha = get_int(iBuffer.get(), 48); if (inputMasks.alpha != 0) { @@ -418,11 +362,6 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { } iBuffer.free(); - // Additionally, 32 bit bmp-in-icos use the alpha channel - if (isIco && 32 == bitsPerPixel) { - alphaType = kUnpremul_SkAlphaType; - } - // Check for valid bits per pixel input switch (bitsPerPixel) { // In addition to more standard pixel compression formats, bmp supports @@ -467,7 +406,7 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { // Calculate the number of bytes read so far const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; - if (!isIco && offset < bytesRead) { + if (offset < bytesRead) { SkDebugf("Error: pixel data offset less than header size.\n"); return NULL; } @@ -481,7 +420,7 @@ SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) { return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, inputFormat, masks.detach(), numColors, bytesPerColor, offset - bytesRead, - rowOrder, RLEBytes, isIco)); + rowOrder, RLEBytes)); } /* @@ -494,7 +433,7 @@ SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, uint16_t bitsPerPixel, BitmapInputFormat inputFormat, SkMasks* masks, uint32_t numColors, uint32_t bytesPerColor, uint32_t offset, - RowOrder rowOrder, size_t RLEBytes, bool isIco) + RowOrder rowOrder, size_t RLEBytes) : INHERITED(info, stream) , fBitsPerPixel(bitsPerPixel) , fInputFormat(inputFormat) @@ -505,8 +444,6 @@ SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, , fOffset(offset) , fRowOrder(rowOrder) , fRLEBytes(RLEBytes) - , fIsIco(isIco) - {} /* @@ -522,11 +459,11 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, if (!this->rewindIfNeeded()) { return kCouldNotRewind; } - if (dstInfo.dimensions() != this->getInfo().dimensions()) { + if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) { SkDebugf("Error: scaling not supported.\n"); return kInvalidScale; } - if (!conversion_possible(dstInfo, this->getInfo())) { + if (!conversion_possible(dstInfo, this->getOriginalInfo())) { SkDebugf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } @@ -616,29 +553,26 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, } } - // Bmp-in-Ico files do not use an offset to indicate where the pixel data - // begins. Pixel data always begins immediately after the color table. - if (!fIsIco) { - // Check that we have not read past the pixel array offset - if(fOffset < colorBytes) { - // This may occur on OS 2.1 and other old versions where the color - // table defaults to max size, and the bmp tries to use a smaller - // color table. This is invalid, and our decision is to indicate - // an error, rather than try to guess the intended size of the - // color table. - SkDebugf("Error: pixel data offset less than color table size.\n"); - return false; - } + // Check that we have not read past the pixel array offset + if(fOffset < colorBytes) { + // This may occur on OS 2.1 and other old versions where the color + // table defaults to max size, and the bmp tries to use a smaller color + // table. This is invalid, and our decision is to indicate an error, + // rather than try to guess the intended size of the color table. + SkDebugf("Error: pixel data offset less than color table size.\n"); + return false; + } - // After reading the color table, skip to the start of the pixel array - if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { - SkDebugf("Error: unable to skip to image data.\n"); - return false; - } + // After reading the color table, skip to the start of the pixel array + if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { + SkDebugf("Error: unable to skip to image data.\n"); + return false; } // Set the color table and return true on success - fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); + if (maxColors > 0) { + fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); + } return true; } @@ -1055,6 +989,7 @@ SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, // SkSwizzler does not support. Firstly, all bmp images that contain // alpha are masked by the alpha mask. Secondly, many fully transparent // bmp images are intended to be opaque. Here, we make those corrections. + // Modifying alpha is safe because colors are stored unpremultiplied. /* SkPMColor* dstRow = (SkPMColor*) dst; if (SkSwizzler::kBGRA == config) { @@ -1071,41 +1006,6 @@ SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, } */ - // Finally, apply the AND mask for bmp-in-ico images - if (fIsIco) { - // The AND mask is always 1 bit per pixel - const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); - - SkPMColor* dstPtr = (SkPMColor*) dst; - for (int y = 0; y < height; y++) { - // The srcBuffer will at least be large enough - if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { - SkDebugf("Warning: incomplete AND mask for bmp-in-ico.\n"); - return kIncompleteInput; - } - - int row; - if (kBottomUp_RowOrder == fRowOrder) { - row = height - y - 1; - } else { - row = y; - } - - SkPMColor* dstRow = - SkTAddOffset(dstPtr, row * dstRowBytes); - - for (int x = 0; x < width; x++) { - int quotient; - int modulus; - SkTDivMod(x, 8, "ient, &modulus); - uint32_t shift = 7 - modulus; - uint32_t alphaBit = - (srcBuffer.get()[quotient] >> shift) & 0x1; - dstRow[x] &= alphaBit - 1; - } - } - } - // Finished decoding the entire image return kSuccess; } diff --git a/src/codec/SkCodec_libbmp.h b/src/codec/SkCodec_libbmp.h index 4dda117d5a..fb23716f77 100644 --- a/src/codec/SkCodec_libbmp.h +++ b/src/codec/SkCodec_libbmp.h @@ -7,6 +7,7 @@ #include "SkCodec.h" #include "SkColorTable.h" +#include "SkEncodedFormat.h" #include "SkImageInfo.h" #include "SkMaskSwizzler.h" #include "SkStream.h" @@ -35,7 +36,7 @@ public: /* * - * Checks the start of the stream to see if the image is a bmp + * Checks the start of the stream to see if the image is a bitmap * */ static bool IsBmp(SkStream*); @@ -43,25 +44,17 @@ public: /* * * Assumes IsBmp was called and returned true - * Creates a bmp decoder + * Creates a bitmap decoder * Reads enough of the stream to determine the image format * */ static SkCodec* NewFromStream(SkStream*); - /* - * - * Creates a bmp decoder for a bmp embedded in ico - * Reads enough of the stream to determine the image format - * - */ - static SkCodec* NewFromIco(SkStream*); - protected: /* * - * Initiates the bmp decode + * Initiates the bitmap decode * */ virtual Result onGetPixels(const SkImageInfo& dstInfo, void* dst, @@ -69,12 +62,11 @@ protected: int*) SK_OVERRIDE; SkEncodedFormat onGetEncodedFormat() const SK_OVERRIDE { return kBMP_SkEncodedFormat; } - private: /* * - * Used to define the input format of the bmp + * Used to define the input format of the bitmap * */ enum BitmapInputFormat { @@ -91,14 +83,6 @@ private: */ bool createColorTable(SkAlphaType alphaType); - /* - * - * Creates a bmp decoder - * Reads enough of the stream to determine the image format - * - */ - static SkCodec* NewFromStream(SkStream*, bool isIco); - /* * * Performs the bitmap decoding for bit masks input format @@ -165,8 +149,7 @@ private: SkBmpCodec(const SkImageInfo& srcInfo, SkStream* stream, uint16_t bitsPerPixel, BitmapInputFormat format, SkMasks* masks, uint32_t numColors, uint32_t bytesPerColor, - uint32_t offset, RowOrder rowOrder, size_t RLEBytes, - bool isIco); + uint32_t offset, RowOrder rowOrder, size_t RLEByes); // Fields const uint16_t fBitsPerPixel; @@ -178,7 +161,6 @@ private: const uint32_t fOffset; const RowOrder fRowOrder; const size_t fRLEBytes; - const bool fIsIco; typedef SkCodec INHERITED; }; diff --git a/src/codec/SkCodec_libico.cpp b/src/codec/SkCodec_libico.cpp deleted file mode 100644 index 2adfa9cfde..0000000000 --- a/src/codec/SkCodec_libico.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkCodec_libbmp.h" -#include "SkCodec_libico.h" -#include "SkCodec_libpng.h" -#include "SkCodecPriv.h" -#include "SkColorPriv.h" -#include "SkData.h" -#include "SkStream.h" -#include "SkTDArray.h" -#include "SkTSort.h" - -/* - * Checks the start of the stream to see if the image is an Ico or Cur - */ -bool SkIcoCodec::IsIco(SkStream* stream) { - const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' }; - const char curSig[] = { '\x00', '\x00', '\x02', '\x00' }; - char buffer[sizeof(icoSig)]; - return stream->read(buffer, sizeof(icoSig)) == sizeof(icoSig) && - (!memcmp(buffer, icoSig, sizeof(icoSig)) || - !memcmp(buffer, curSig, sizeof(curSig))); -} - -/* - * Assumes IsIco was called and returned true - * Creates an Ico decoder - * Reads enough of the stream to determine the image format - */ -SkCodec* SkIcoCodec::NewFromStream(SkStream* stream) { - // Header size constants - static const uint32_t kIcoDirectoryBytes = 6; - static const uint32_t kIcoDirEntryBytes = 16; - - // Read the directory header - SkAutoTDeleteArray dirBuffer( - SkNEW_ARRAY(uint8_t, kIcoDirectoryBytes)); - if (stream->read(dirBuffer.get(), kIcoDirectoryBytes) != - kIcoDirectoryBytes) { - SkDebugf("Error: unable to read ico directory header.\n"); - return NULL; - } - - // Process the directory header - const uint16_t numImages = get_short(dirBuffer.get(), 4); - if (0 == numImages) { - SkDebugf("Error: No images embedded in ico.\n"); - return NULL; - } - - // Ensure that we can read all of indicated directory entries - SkAutoTDeleteArray entryBuffer( - SkNEW_ARRAY(uint8_t, numImages*kIcoDirEntryBytes)); - if (stream->read(entryBuffer.get(), numImages*kIcoDirEntryBytes) != - numImages*kIcoDirEntryBytes) { - SkDebugf("Error: unable to read ico directory entries.\n"); - return NULL; - } - - // This structure is used to represent the vital information about entries - // in the directory header. We will obtain this information for each - // directory entry. - struct Entry { - uint32_t offset; - uint32_t size; - }; - SkAutoTDeleteArray directoryEntries(SkNEW_ARRAY(Entry, numImages)); - - // Iterate over directory entries - for (uint32_t i = 0; i < numImages; i++) { - // The directory entry contains information such as width, height, - // bits per pixel, and number of colors in the color palette. We will - // ignore these fields since they are repeated in the header of the - // embedded image. In the event of an inconsistency, we would always - // defer to the value in the embedded header anyway. - - // Specifies the size of the embedded image, including the header - uint32_t size = get_int(entryBuffer.get(), 8 + i*kIcoDirEntryBytes); - - // Specifies the offset of the embedded image from the start of file. - // It does not indicate the start of the pixel data, but rather the - // start of the embedded image header. - uint32_t offset = get_int(entryBuffer.get(), 12 + i*kIcoDirEntryBytes); - - // Save the vital fields - directoryEntries.get()[i].offset = offset; - directoryEntries.get()[i].size = size; - } - - // It is "customary" that the embedded images will be stored in order of - // increasing offset. However, the specification does not indicate that - // they must be stored in this order, so we will not trust that this is the - // case. Here we sort the embedded images by increasing offset. - struct EntryLessThan { - bool operator() (Entry a, Entry b) const { - return a.offset < b.offset; - } - }; - EntryLessThan lessThan; - SkTQSort(directoryEntries.get(), directoryEntries.get() + numImages - 1, - lessThan); - - // Now will construct a candidate codec for each of the embedded images - uint32_t bytesRead = kIcoDirectoryBytes + numImages * kIcoDirEntryBytes; - SkAutoTDelete, true>> codecs( - SkNEW_ARGS((SkTArray, true>), (numImages))); - for (uint32_t i = 0; i < numImages; i++) { - uint32_t offset = directoryEntries.get()[i].offset; - uint32_t size = directoryEntries.get()[i].size; - - // Ensure that the offset is valid - if (offset < bytesRead) { - SkDebugf("Warning: invalid ico offset.\n"); - continue; - } - - // If we cannot skip, assume we have reached the end of the stream and - // stop trying to make codecs - if (stream->skip(offset - bytesRead) != offset - bytesRead) { - SkDebugf("Warning: could not skip to ico offset.\n"); - break; - } - bytesRead = offset; - - // Create a new stream for the embedded codec - SkAutoTUnref data(SkData::NewFromStream(stream, size)); - if (NULL == data.get()) { - SkDebugf("Warning: could not create embedded stream.\n"); - break; - } - SkAutoTDelete - embeddedStream(SkNEW_ARGS(SkMemoryStream, (data.get()))); - bytesRead += size; - - // Check if the embedded codec is bmp or png and create the codec - const bool isPng = SkPngCodec::IsPng(embeddedStream); - SkAssertResult(embeddedStream->rewind()); - SkCodec* codec = NULL; - if (isPng) { - codec = SkPngCodec::NewFromStream(embeddedStream.detach()); - } else { - codec = SkBmpCodec::NewFromIco(embeddedStream.detach()); - } - - // Save a valid codec - if (NULL != codec) { - codecs->push_back().reset(codec); - } - } - - // Recognize if there are no valid codecs - if (0 == codecs->count()) { - SkDebugf("Error: could not find any valid embedded ico codecs.\n"); - return NULL; - } - - // Use the largest codec as a "suggestion" for image info - uint32_t maxSize = 0; - uint32_t maxIndex = 0; - for (int32_t i = 0; i < codecs->count(); i++) { - SkImageInfo info = codecs->operator[](i)->getInfo(); - uint32_t size = info.width() * info.height(); - if (size > maxSize) { - maxSize = size; - maxIndex = i; - } - } - SkImageInfo info = codecs->operator[](maxIndex)->getInfo(); - - // Note that stream is owned by the embedded codec, the ico does not need - // direct access to the stream. - return SkNEW_ARGS(SkIcoCodec, (info, codecs.detach())); -} - -/* - * Creates an instance of the decoder - * Called only by NewFromStream - */ -SkIcoCodec::SkIcoCodec(const SkImageInfo& info, - SkTArray, true>* codecs) - : INHERITED(info, NULL) - , fEmbeddedCodecs(codecs) -{} - -/* - * Chooses the best dimensions given the desired scale - */ -SkISize SkIcoCodec::onGetScaledDimensions(float desiredScale) const { - // We set the dimensions to the largest candidate image by default. - // Regardless of the scale request, this is the largest image that we - // will decode. - if (desiredScale >= 1.0) { - return this->getInfo().dimensions(); - } - - int origWidth = this->getInfo().width(); - int origHeight = this->getInfo().height(); - float desiredSize = desiredScale * origWidth * origHeight; - // At least one image will have smaller error than this initial value - float minError = ((float) (origWidth * origHeight)) - desiredSize + 1.0f; - int32_t minIndex = -1; - for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) { - int width = fEmbeddedCodecs->operator[](i)->getInfo().width(); - int height = fEmbeddedCodecs->operator[](i)->getInfo().height(); - float error = SkTAbs(((float) (width * height)) - desiredSize); - if (error < minError) { - minError = error; - minIndex = i; - } - } - SkASSERT(minIndex >= 0); - - return fEmbeddedCodecs->operator[](minIndex)->getInfo().dimensions(); -} - -/* - * Initiates the Ico decode - */ -SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo, - void* dst, size_t dstRowBytes, - const Options& opts, SkPMColor* ct, - int* ptr) { - // We return invalid scale if there is no candidate image with matching - // dimensions. - Result result = kInvalidScale; - for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) { - // If the dimensions match, try to decode - if (dstInfo.dimensions() == - fEmbeddedCodecs->operator[](i)->getInfo().dimensions()) { - - // Perform the decode - result = fEmbeddedCodecs->operator[](i)->getPixels(dstInfo, - dst, dstRowBytes, &opts, ct, ptr); - - // On a fatal error, keep trying to find an image to decode - if (kInvalidConversion == result || kInvalidInput == result || - kInvalidScale == result) { - SkDebugf("Warning: Attempt to decode candidate ico failed.\n"); - continue; - } - - // On success or partial success, return the result - return result; - } - } - - SkDebugf("Error: No matching candidate image in ico.\n"); - return result; -} diff --git a/src/codec/SkCodec_libico.h b/src/codec/SkCodec_libico.h deleted file mode 100644 index 778bcd2c54..0000000000 --- a/src/codec/SkCodec_libico.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkCodec.h" -#include "SkImageInfo.h" -#include "SkStream.h" -#include "SkTypes.h" - -/* - * This class implements the decoding for bmp images - */ -class SkIcoCodec : public SkCodec { -public: - - /* - * Checks the start of the stream to see if the image is a Ico or Cur - */ - static bool IsIco(SkStream*); - - /* - * Assumes IsIco was called and returned true - * Creates an Ico decoder - * Reads enough of the stream to determine the image format - */ - static SkCodec* NewFromStream(SkStream*); - -protected: - - /* - * Chooses the best dimensions given the desired scale - */ - SkISize onGetScaledDimensions(float desiredScale) const SK_OVERRIDE; - - /* - * Initiates the Ico decode - */ - Result onGetPixels(const SkImageInfo& dstInfo, void* dst, - size_t dstRowBytes, const Options&, SkPMColor*, int*) - SK_OVERRIDE; - - SkEncodedFormat onGetEncodedFormat() const SK_OVERRIDE { - return kICO_SkEncodedFormat; - } - -private: - - /* - * Constructor called by NewFromStream - * @param embeddedCodecs codecs for the embedded images, takes ownership - */ - SkIcoCodec(const SkImageInfo& srcInfo, - SkTArray, true>* embeddedCodecs); - - SkAutoTDelete, true>> - fEmbeddedCodecs; // owned - - typedef SkCodec INHERITED; -}; diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp index e113a0e1b6..57653e74df 100644 --- a/src/codec/SkCodec_libpng.cpp +++ b/src/codec/SkCodec_libpng.cpp @@ -368,10 +368,10 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* if (!this->rewindIfNeeded()) { return kCouldNotRewind; } - if (requestedInfo.dimensions() != this->getInfo().dimensions()) { + if (requestedInfo.dimensions() != this->getOriginalInfo().dimensions()) { return kInvalidScale; } - if (!conversion_possible(requestedInfo, this->getInfo())) { + if (!conversion_possible(requestedInfo, this->getOriginalInfo())) { return kInvalidConversion; } @@ -424,7 +424,7 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* // told png to upscale. SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); sc = SkSwizzler::kGray; - } else if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { + } else if (this->getOriginalInfo().alphaType() == kOpaque_SkAlphaType) { sc = SkSwizzler::kRGBX; } else { sc = SkSwizzler::kRGBA; diff --git a/tools/dm_flags.py b/tools/dm_flags.py index 448d1e2d9b..f05bb22416 100755 --- a/tools/dm_flags.py +++ b/tools/dm_flags.py @@ -51,26 +51,6 @@ def get_args(bot): blacklist.extend('gpu _ PANO_20121023_214540.jpg'.split(' ')) blacklist.extend('msaa _ PANO_20121023_214540.jpg'.split(' ')) - # Several of the newest version bmps fail on SkImageDecoder - blacklist.extend('_ image pal8os2v2.bmp'.split(' ')) - blacklist.extend('_ image pal8v4.bmp'.split(' ')) - blacklist.extend('_ image pal8v5.bmp'.split(' ')) - blacklist.extend('_ image rgb16-565.bmp'.split(' ')) - blacklist.extend('_ image rgb16-565pal.bmp'.split(' ')) - blacklist.extend('_ image rgb32-111110.bmp'.split(' ')) - blacklist.extend('_ image rgb32bf.bmp'.split(' ')) - blacklist.extend('_ image rgba32.bmp'.split(' ')) - blacklist.extend('_ image rgba32abf.bmp'.split(' ')) - blacklist.extend('_ image rgb24largepal.bmp'.split(' ')) - blacklist.extend('_ image pal8os2v2-16.bmp'.split(' ')) - blacklist.extend('_ image pal8oversizepal.bmp'.split(' ')) - blacklist.extend('_ subset rgb24largepal.bmp'.split(' ')) - blacklist.extend('_ subset pal8os2v2-16.bmp'.split(' ')) - blacklist.extend('_ subset pal8oversizepal.bmp'.split(' ')) - - # New ico files that fail on SkImageDecoder - blacklist.extend('_ image Hopstarter-Mac-Folders-Apple.ico'.split(' ')) - # Leon doesn't care about this, so why run it? if 'Win' in bot: blacklist.extend('_ image _'.split(' ')) -- 2.34.1