diff options
Diffstat (limited to 'src/ports/SkImageDecoder_CG.cpp')
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 247 |
1 files changed, 0 insertions, 247 deletions
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index c4446ae16d..6673c240ef 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -11,7 +11,6 @@ #include "SkCGUtils.h" #include "SkColorPriv.h" #include "SkData.h" -#include "SkImageDecoder.h" #include "SkImageEncoder.h" #include "SkMovie.h" #include "SkStream.h" @@ -29,210 +28,6 @@ #include <MobileCoreServices/MobileCoreServices.h> #endif -static void data_unref_proc(void* skdata, const void*, size_t) { - SkASSERT(skdata); - static_cast<SkData*>(skdata)->unref(); -} - -static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) { - // TODO: use callbacks, so we don't have to load all the data into RAM - SkData* skdata = SkCopyStreamToData(stream).release(); - if (!skdata) { - return nullptr; - } - - return CGDataProviderCreateWithData(skdata, skdata->data(), skdata->size(), data_unref_proc); -} - -static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) { - CGDataProviderRef data = SkStreamToDataProvider(stream); - if (!data) { - return nullptr; - } - CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0); - CGDataProviderRelease(data); - return imageSrc; -} - -class SkImageDecoder_CG : public SkImageDecoder { -protected: - virtual Result onDecode(SkStream* stream, SkBitmap* bm, Mode); -}; - -static void argb_4444_force_opaque(void* row, int count) { - uint16_t* row16 = (uint16_t*)row; - for (int i = 0; i < count; ++i) { - row16[i] |= 0xF000; - } -} - -static void argb_8888_force_opaque(void* row, int count) { - // can use RGBA or BGRA, they have the same shift for alpha - const uint32_t alphaMask = 0xFF << SK_RGBA_A32_SHIFT; - uint32_t* row32 = (uint32_t*)row; - for (int i = 0; i < count; ++i) { - row32[i] |= alphaMask; - } -} - -static void alpha_8_force_opaque(void* row, int count) { - memset(row, 0xFF, count); -} - -static void force_opaque(SkBitmap* bm) { - SkAutoLockPixels alp(*bm); - if (!bm->getPixels()) { - return; - } - - void (*proc)(void*, int); - switch (bm->colorType()) { - case kARGB_4444_SkColorType: - proc = argb_4444_force_opaque; - break; - case kRGBA_8888_SkColorType: - case kBGRA_8888_SkColorType: - proc = argb_8888_force_opaque; - break; - case kAlpha_8_SkColorType: - proc = alpha_8_force_opaque; - break; - default: - return; - } - - char* row = (char*)bm->getPixels(); - for (int y = 0; y < bm->height(); ++y) { - proc(row, bm->width()); - row += bm->rowBytes(); - } - bm->setAlphaType(kOpaque_SkAlphaType); -} - -#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast) - -class AutoCFDataRelease { - CFDataRef fDR; -public: - AutoCFDataRelease(CFDataRef dr) : fDR(dr) {} - ~AutoCFDataRelease() { if (fDR) { CFRelease(fDR); } } - - operator CFDataRef () { return fDR; } -}; - -static bool colorspace_is_sRGB(CGColorSpaceRef cs) { -#ifdef SK_BUILD_FOR_IOS - return true; // iOS seems to define itself to always return sRGB <reed> -#else - AutoCFDataRelease data(CGColorSpaceCopyICCProfile(cs)); - if (data) { - // found by inspection -- need a cleaner way to sniff a profile - const CFIndex ICC_PROFILE_OFFSET_TO_SRGB_TAG = 52; - - if (CFDataGetLength(data) >= ICC_PROFILE_OFFSET_TO_SRGB_TAG + 4) { - return !memcmp(CFDataGetBytePtr(data) + ICC_PROFILE_OFFSET_TO_SRGB_TAG, "sRGB", 4); - } - } - return false; -#endif -} - -SkImageDecoder::Result SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { - CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); - - if (nullptr == imageSrc) { - return kFailure; - } - SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); - - CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, nullptr); - if (nullptr == image) { - return kFailure; - } - SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); - - const int width = SkToInt(CGImageGetWidth(image)); - const int height = SkToInt(CGImageGetHeight(image)); - SkColorProfileType cpType = kLinear_SkColorProfileType; - - CGColorSpaceRef cs = CGImageGetColorSpace(image); - if (cs) { - CGColorSpaceModel m = CGColorSpaceGetModel(cs); - if (kCGColorSpaceModelRGB == m && colorspace_is_sRGB(cs)) { - cpType = kSRGB_SkColorProfileType; - } - } - - SkAlphaType at = kPremul_SkAlphaType; - switch (CGImageGetAlphaInfo(image)) { - case kCGImageAlphaNone: - case kCGImageAlphaNoneSkipLast: - case kCGImageAlphaNoneSkipFirst: - at = kOpaque_SkAlphaType; - break; - default: - break; - } - - bm->setInfo(SkImageInfo::Make(width, height, kN32_SkColorType, at, cpType)); - if (SkImageDecoder::kDecodeBounds_Mode == mode) { - return kSuccess; - } - - if (!this->allocPixelRef(bm, nullptr)) { - return kFailure; - } - - SkAutoLockPixels alp(*bm); - - if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) { - return kFailure; - } - - CGImageAlphaInfo info = CGImageGetAlphaInfo(image); - switch (info) { - case kCGImageAlphaNone: - case kCGImageAlphaNoneSkipLast: - case kCGImageAlphaNoneSkipFirst: - // We're opaque, but we can't rely on the data always having 0xFF - // in the alpha slot (which Skia wants), so we have to ram it in - // ourselves. - force_opaque(bm); - break; - default: - // we don't know if we're opaque or not, so compute it. - if (SkBitmap::ComputeIsOpaque(*bm)) { - bm->setAlphaType(kOpaque_SkAlphaType); - } - } - if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) { - // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied. - // Convert to unpremultiplied. - for (int i = 0; i < width; ++i) { - for (int j = 0; j < height; ++j) { - uint32_t* addr = bm->getAddr32(i, j); - *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr); - } - } - bm->setAlphaType(kUnpremul_SkAlphaType); - } - return kSuccess; -} - -/////////////////////////////////////////////////////////////////////////////// - -extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*); - -SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) { - SkImageDecoder* decoder = image_decoder_from_stream(stream); - if (nullptr == decoder) { - // If no image decoder specific to the stream exists, use SkImageDecoder_CG. - return new SkImageDecoder_CG; - } else { - return decoder; - } -} - ///////////////////////////////////////////////////////////////////////// SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { @@ -366,46 +161,4 @@ public: DEFINE_ENCODER_CREATOR(PNGImageEncoder_IOS); #endif -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(SkStreamRewindable* stream) { - CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); - - if (nullptr == imageSrc) { - return SkImageDecoder::kUnknown_Format; - } - - SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); - const CFStringRef name = CGImageSourceGetType(imageSrc); - if (nullptr == name) { - return SkImageDecoder::kUnknown_Format; - } - return UTType_to_Format(name); -} - -static SkImageDecoder_FormatReg gFormatReg(get_format_cg); - #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |