diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkImageDecoder.cpp | 39 | ||||
-rw-r--r-- | src/images/SkImageDecoder_FactoryRegistrar.cpp | 22 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libbmp.cpp | 19 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libgif.cpp | 27 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libico.cpp | 26 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 27 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 18 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libwebp.cpp | 9 | ||||
-rw-r--r-- | src/images/SkImageDecoder_wbmp.cpp | 9 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 42 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_WIC.cpp | 88 |
11 files changed, 285 insertions, 41 deletions
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index c16efcf1f3..16cba641db 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -18,17 +18,6 @@ SK_DEFINE_INST_COUNT(SkImageDecoder::Peeker) SK_DEFINE_INST_COUNT(SkImageDecoder::Chooser) SK_DEFINE_INST_COUNT(SkImageDecoderFactory) -const char *SkImageDecoder::sFormatName[] = { - "Unknown Format", - "BMP", - "GIF", - "ICO", - "JPEG", - "PNG", - "WBMP", - "WEBP", -}; - static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; SkBitmap::Config SkImageDecoder::GetDeviceConfig() @@ -60,8 +49,27 @@ SkImageDecoder::Format SkImageDecoder::getFormat() const { } const char* SkImageDecoder::getFormatName() const { - SkASSERT(SK_ARRAY_COUNT(sFormatName) == kLastKnownFormat); - return sFormatName[this->getFormat()]; + switch (this->getFormat()) { + case kUnknown_Format: + return "Unknown Format"; + case kBMP_Format: + return "BMP"; + case kGIF_Format: + return "GIF"; + case kICO_Format: + return "ICO"; + case kJPEG_Format: + return "JPEG"; + case kPNG_Format: + return "PNG"; + case kWBMP_Format: + return "WBMP"; + case kWEBP_Format: + return "WEBP"; + default: + SkASSERT(!"Invalid format type!"); + } + return "Unknown Format"; } SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { @@ -321,6 +329,11 @@ bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, success = codec->decode(stream, bm, pref, mode); if (success && format) { *format = codec->getFormat(); + if (kUnknown_Format == *format) { + if (stream->rewind()) { + *format = GetStreamFormat(stream); + } + } } delete codec; } diff --git a/src/images/SkImageDecoder_FactoryRegistrar.cpp b/src/images/SkImageDecoder_FactoryRegistrar.cpp index 6cc417a46f..f1eca3d03a 100644 --- a/src/images/SkImageDecoder_FactoryRegistrar.cpp +++ b/src/images/SkImageDecoder_FactoryRegistrar.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkErrorInternals.h" #include "SkImageDecoder.h" #include "SkStream.h" #include "SkTRegistry.h" @@ -45,3 +46,24 @@ SkImageDecoder* image_decoder_from_stream(SkStream* stream) { } return NULL; } + +typedef SkTRegistry<SkImageDecoder::Format, SkStream*> FormatReg; + +template FormatReg* SkTRegistry<SkImageDecoder::Format, SkStream*>::gHead; + +SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStream* stream) { + const FormatReg* curr = FormatReg::Head(); + while (curr != NULL) { + Format format = curr->factory()(stream); + if (!stream->rewind()) { + SkErrorInternals::SetError(kInvalidOperation_SkError, + "Unable to rewind the image stream\n"); + return kUnknown_Format; + } + if (format != kUnknown_Format) { + return format; + } + curr = curr->next(); + } + return kUnknown_Format; +} diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp index 488eddce1e..5c2299b77c 100644 --- a/src/images/SkImageDecoder_libbmp.cpp +++ b/src/images/SkImageDecoder_libbmp.cpp @@ -34,14 +34,18 @@ private: DEFINE_DECODER_CREATOR(BMPImageDecoder); /////////////////////////////////////////////////////////////////////////////// -static SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) { +static bool is_bmp(SkStream* stream) { static const char kBmpMagic[] = { 'B', 'M' }; char buffer[sizeof(kBmpMagic)]; - if (stream->read(buffer, sizeof(kBmpMagic)) == sizeof(kBmpMagic) && - !memcmp(buffer, kBmpMagic, sizeof(kBmpMagic))) { + return stream->read(buffer, sizeof(kBmpMagic)) == sizeof(kBmpMagic) && + !memcmp(buffer, kBmpMagic, sizeof(kBmpMagic)); +} + +static SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) { + if (is_bmp(stream)) { return SkNEW(SkBMPImageDecoder); } return NULL; @@ -49,6 +53,15 @@ static SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) { static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libbmp_dfactory); +static SkImageDecoder::Format get_format_bmp(SkStream* stream) { + if (is_bmp(stream)) { + return SkImageDecoder::kBMP_Format; + } + return SkImageDecoder::kUnknown_Format; +} + +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_bmp); + /////////////////////////////////////////////////////////////////////////////// class SkBmpDecoderCallback : public image_codec::BmpDecoderCallback { diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp index 3e4cda8a0b..f6c54c2dc0 100644 --- a/src/images/SkImageDecoder_libgif.cpp +++ b/src/images/SkImageDecoder_libgif.cpp @@ -91,9 +91,6 @@ private: /////////////////////////////////////////////////////////////////////////////// -//#define GIF_STAMP "GIF" /* First chars in file - GIF stamp. */ -//#define GIF_STAMP_LEN (sizeof(GIF_STAMP) - 1) - static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out, int size) { SkStream* stream = (SkStream*) fileType->UserData; @@ -365,18 +362,34 @@ DONE: DEFINE_DECODER_CREATOR(GIFImageDecoder); /////////////////////////////////////////////////////////////////////////////// -#include "SkTRegistry.h" - -static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) { +static bool is_gif(SkStream* stream) { char buf[GIF_STAMP_LEN]; if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 || memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 || memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) { - return SkNEW(SkGIFImageDecoder); + return true; } } + return false; +} + +#include "SkTRegistry.h" + +static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) { + if (is_gif(stream)) { + return SkNEW(SkGIFImageDecoder); + } return NULL; } static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libgif_dfactory); + +static SkImageDecoder::Format get_format_gif(SkStream* stream) { + if (is_gif(stream)) { + return SkImageDecoder::kGIF_Format; + } + return SkImageDecoder::kUnknown_Format; +} + +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_gif); diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp index ffc59e0003..195b6ff08b 100644 --- a/src/images/SkImageDecoder_libico.cpp +++ b/src/images/SkImageDecoder_libico.cpp @@ -373,9 +373,7 @@ static void editPixelBit32(const int pixelNo, const unsigned char* buf, DEFINE_DECODER_CREATOR(ICOImageDecoder); ///////////////////////////////////////////////////////////////////////////////////////// -#include "SkTRegistry.h" - -static SkImageDecoder* sk_libico_dfactory(SkStream* stream) { +static bool is_ico(SkStream* stream) { // Check to see if the first four bytes are 0,0,1,0 // FIXME: Is that required and sufficient? SkAutoMalloc autoMal(4); @@ -385,9 +383,27 @@ static SkImageDecoder* sk_libico_dfactory(SkStream* stream) { int type = read2Bytes(buf, 2); if (reserved != 0 || type != 1) { // This stream does not represent an ICO image. - return NULL; + return false; } - return SkNEW(SkICOImageDecoder); + return true; +} + +#include "SkTRegistry.h" + +static SkImageDecoder* sk_libico_dfactory(SkStream* stream) { + if (is_ico(stream)) { + return SkNEW(SkICOImageDecoder); + } + return NULL; } static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libico_dfactory); + +static SkImageDecoder::Format get_format_ico(SkStream* stream) { + if (is_ico(stream)) { + return SkImageDecoder::kICO_Format; + } + return SkImageDecoder::kUnknown_Format; +} + +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_ico); diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp index 9920bacc45..c55f4c4123 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -998,9 +998,7 @@ DEFINE_DECODER_CREATOR(JPEGImageDecoder); DEFINE_ENCODER_CREATOR(JPEGImageEncoder); /////////////////////////////////////////////////////////////////////////////// -#include "SkTRegistry.h" - -static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) { +static bool is_jpeg(SkStream* stream) { static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF }; static const size_t HEADER_SIZE = sizeof(gHeader); @@ -1008,12 +1006,28 @@ static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) { size_t len = stream->read(buffer, HEADER_SIZE); if (len != HEADER_SIZE) { - return NULL; // can't read enough + return false; // can't read enough } if (memcmp(buffer, gHeader, HEADER_SIZE)) { - return NULL; + return false; + } + return true; +} + +#include "SkTRegistry.h" + +static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) { + if (is_jpeg(stream)) { + return SkNEW(SkJPEGImageDecoder); + } + return NULL; +} + +static SkImageDecoder::Format get_format_jpeg(SkStream* stream) { + if (is_jpeg(stream)) { + return SkImageDecoder::kJPEG_Format; } - return SkNEW(SkJPEGImageDecoder); + return SkImageDecoder::kUnknown_Format; } static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { @@ -1022,4 +1036,5 @@ static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory); +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_jpeg); static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory); diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index efa4595545..aec8948945 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -47,6 +47,7 @@ public: virtual Format getFormat() const SK_OVERRIDE { return kPNG_Format; } + virtual ~SkPNGImageDecoder() { SkDELETE(fImageIndex); } @@ -1086,18 +1087,33 @@ DEFINE_ENCODER_CREATOR(PNGImageEncoder); #include "SkTRegistry.h" -SkImageDecoder* sk_libpng_dfactory(SkStream* stream) { +static bool is_png(SkStream* stream) { char buf[PNG_BYTES_TO_CHECK]; if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK && !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { + return true; + } + return false; +} + +SkImageDecoder* sk_libpng_dfactory(SkStream* stream) { + if (is_png(stream)) { return SkNEW(SkPNGImageDecoder); } return NULL; } +static SkImageDecoder::Format get_format_png(SkStream* stream) { + if (is_png(stream)) { + return SkImageDecoder::kPNG_Format; + } + return SkImageDecoder::kUnknown_Format; +} + SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; } static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efactory); +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_png); static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp index d9434c2813..a33d0f9b2f 100644 --- a/src/images/SkImageDecoder_libwebp.cpp +++ b/src/images/SkImageDecoder_libwebp.cpp @@ -587,9 +587,18 @@ static SkImageDecoder* sk_libwebp_dfactory(SkStream* stream) { return SkNEW(SkWEBPImageDecoder); } +static SkImageDecoder::Format get_format_webp(SkStream* stream) { + int width, height, hasAlpha; + if (webp_parse_header(stream, &width, &height, &hasAlpha)) { + return SkImageDecoder::kWEBP_Format; + } + return SkImageDecoder::kUnknown_Format; +} + static SkImageEncoder* sk_libwebp_efactory(SkImageEncoder::Type t) { return (SkImageEncoder::kWEBP_Type == t) ? SkNEW(SkWEBPImageEncoder) : NULL; } static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libwebp_dfactory); +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_webp); static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libwebp_efactory); diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp index 96677ccafc..db40f595fa 100644 --- a/src/images/SkImageDecoder_wbmp.cpp +++ b/src/images/SkImageDecoder_wbmp.cpp @@ -170,4 +170,13 @@ static SkImageDecoder* sk_wbmp_dfactory(SkStream* stream) { return NULL; } +static SkImageDecoder::Format get_format_wbmp(SkStream* stream) { + wbmp_head head; + if (head.init(stream)) { + return SkImageDecoder::kWBMP_Format; + } + return SkImageDecoder::kUnknown_Format; +} + static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_wbmp_dfactory); +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_wbmp); diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index 9fc49a445f..5fe6fddf90 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -245,3 +245,45 @@ static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) { } static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_imageencoder_cg_factory); + +struct FormatConversion { + CFStringRef fUTType; + SkImageDecoder::Format fFormat; +}; + +// Array of the types supported by the decoder. +static const FormatConversion gFormatConversions[] = { + { kUTTypeBMP, SkImageDecoder::kBMP_Format }, + { kUTTypeGIF, SkImageDecoder::kGIF_Format }, + { kUTTypeICO, SkImageDecoder::kICO_Format }, + { kUTTypeJPEG, SkImageDecoder::kJPEG_Format }, + // Also include JPEG2000 + { kUTTypeJPEG2000, SkImageDecoder::kJPEG_Format }, + { kUTTypePNG, SkImageDecoder::kPNG_Format }, +}; + +static SkImageDecoder::Format UTType_to_Format(const CFStringRef uttype) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) { + if (CFStringCompare(uttype, gFormatConversions[i].fUTType, 0) == kCFCompareEqualTo) { + return gFormatConversions[i].fFormat; + } + } + return SkImageDecoder::kUnknown_Format; +} + +static SkImageDecoder::Format get_format_cg(SkStream *stream) { + CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); + + if (NULL == imageSrc) { + return SkImageDecoder::kUnknown_Format; + } + + SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); + const CFStringRef name = CGImageSourceGetType(imageSrc); + if (NULL == name) { + return SkImageDecoder::kUnknown_Format; + } + return UTType_to_Format(name); +} + +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_cg); diff --git a/src/ports/SkImageDecoder_WIC.cpp b/src/ports/SkImageDecoder_WIC.cpp index 17d75ccaca..cd7f29fae4 100644 --- a/src/ports/SkImageDecoder_WIC.cpp +++ b/src/ports/SkImageDecoder_WIC.cpp @@ -29,11 +29,66 @@ #endif class SkImageDecoder_WIC : public SkImageDecoder { +public: + // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding + // only the format. + enum WICModes { + kDecodeFormat_WICMode, + kDecodeBounds_WICMode, + kDecodePixels_WICMode, + }; + + /** + * Helper function to decode an SkStream. + * @param stream SkStream to decode. Must be at the beginning. + * @param bm SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or + * kDecodePixels_WICMode, in which case it must not be NULL. + * @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if + * wicMode is kDecodeFormat_WICMode. + */ + bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const; + protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode); + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE; +}; + +struct FormatConversion { + GUID fGuidFormat; + SkImageDecoder::Format fFormat; }; +static const FormatConversion gFormatConversions[] = { + { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format }, + { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format }, + { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format }, + { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format }, + { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format }, +}; + +static SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) { + for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) { + if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) { + return gFormatConversions[i].fFormat; + } + } + return SkImageDecoder::kUnknown_Format; +} + bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { + WICModes wicMode; + switch (mode) { + case SkImageDecoder::kDecodeBounds_Mode: + wicMode = kDecodeBounds_WICMode; + break; + case SkImageDecoder::kDecodePixels_Mode: + wicMode = kDecodePixels_WICMode; + break; + } + return this->decodeStream(stream, bm, wicMode, NULL); +} + +bool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, + Format* format) const { //Initialize COM. SkAutoCoInitialize scopedCo; if (!scopedCo.succeeded()) { @@ -76,6 +131,20 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { ); } + if (kDecodeFormat_WICMode == wicMode) { + SkASSERT(format != NULL); + //Get the format + if (SUCCEEDED(hr)) { + GUID guidFormat; + hr = piBitmapDecoder->GetContainerFormat(&guidFormat); + if (SUCCEEDED(hr)) { + *format = GuidContainerFormat_to_Format(guidFormat); + return true; + } + } + return false; + } + //Get the first frame from the decoder. SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode; if (SUCCEEDED(hr)) { @@ -100,7 +169,7 @@ bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { //Exit early if we're only looking for the bitmap bounds. if (SUCCEEDED(hr)) { bm->setConfig(SkBitmap::kARGB_8888_Config, width, height); - if (SkImageDecoder::kDecodeBounds_Mode == mode) { + if (kDecodeBounds_WICMode == wicMode) { return true; } if (!this->allocPixelRef(bm, NULL)) { @@ -194,9 +263,6 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream case kBMP_Type: type = GUID_ContainerFormatBmp; break; - case kGIF_Type: - type = GUID_ContainerFormatGif; - break; case kICO_Type: type = GUID_ContainerFormatIco; break; @@ -348,7 +414,6 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) { switch (t) { case SkImageEncoder::kBMP_Type: - case SkImageEncoder::kGIF_Type: case SkImageEncoder::kICO_Type: case SkImageEncoder::kJPEG_Type: case SkImageEncoder::kPNG_Type: @@ -360,3 +425,14 @@ static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) { } static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_imageencoder_wic_factory); + +static SkImageDecoder::Format get_format_wic(SkStream* stream) { + SkImageDecoder::Format format; + SkImageDecoder_WIC codec; + if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) { + format = SkImageDecoder::kUnknown_Format; + } + return format; +} + +static SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_wic); |