1 /* 2 * Copyright 2008 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCGUtils.h" 9 #include "SkColorPriv.h" 10 #include "SkImageDecoder.h" 11 #include "SkImageEncoder.h" 12 #include "SkMovie.h" 13 #include "SkStream.h" 14 #include "SkStreamHelpers.h" 15 #include "SkTemplates.h" 16 #include "SkUnPreMultiply.h" 17 18 #ifdef SK_BUILD_FOR_MAC 19 #include <ApplicationServices/ApplicationServices.h> 20 #endif 21 22 #ifdef SK_BUILD_FOR_IOS 23 #include <CoreGraphics/CoreGraphics.h> 24 #include <ImageIO/ImageIO.h> 25 #include <MobileCoreServices/MobileCoreServices.h> 26 #endif 27 28 static void malloc_release_proc(void* info, const void* data, size_t size) { 29 sk_free(info); 30 } 31 32 static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) { 33 // TODO: use callbacks, so we don't have to load all the data into RAM 34 SkAutoMalloc storage; 35 const size_t len = CopyStreamToStorage(&storage, stream); 36 void* data = storage.detach(); 37 38 return CGDataProviderCreateWithData(data, data, len, malloc_release_proc); 39 } 40 41 static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) { 42 CGDataProviderRef data = SkStreamToDataProvider(stream); 43 CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0); 44 CGDataProviderRelease(data); 45 return imageSrc; 46 } 47 48 class SkImageDecoder_CG : public SkImageDecoder { 49 protected: 50 virtual Result onDecode(SkStream* stream, SkBitmap* bm, Mode); 51 }; 52 53 #define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast) 54 55 SkImageDecoder::Result SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 56 CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); 57 58 if (NULL == imageSrc) { 59 return kFailure; 60 } 61 SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); 62 63 CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL); 64 if (NULL == image) { 65 return kFailure; 66 } 67 SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image); 68 69 const int width = SkToInt(CGImageGetWidth(image)); 70 const int height = SkToInt(CGImageGetHeight(image)); 71 72 bm->setInfo(SkImageInfo::MakeN32Premul(width, height)); 73 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 74 return kSuccess; 75 } 76 77 if (!this->allocPixelRef(bm, NULL)) { 78 return kFailure; 79 } 80 81 SkAutoLockPixels alp(*bm); 82 83 if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) { 84 return kFailure; 85 } 86 87 CGImageAlphaInfo info = CGImageGetAlphaInfo(image); 88 switch (info) { 89 case kCGImageAlphaNone: 90 case kCGImageAlphaNoneSkipLast: 91 case kCGImageAlphaNoneSkipFirst: 92 SkASSERT(SkBitmap::ComputeIsOpaque(*bm)); 93 bm->setAlphaType(kOpaque_SkAlphaType); 94 break; 95 default: 96 // we don't know if we're opaque or not, so compute it. 97 if (SkBitmap::ComputeIsOpaque(*bm)) { 98 bm->setAlphaType(kOpaque_SkAlphaType); 99 } 100 } 101 if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) { 102 // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied. 103 // Convert to unpremultiplied. 104 for (int i = 0; i < width; ++i) { 105 for (int j = 0; j < height; ++j) { 106 uint32_t* addr = bm->getAddr32(i, j); 107 *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr); 108 } 109 } 110 bm->setAlphaType(kUnpremul_SkAlphaType); 111 } 112 return kSuccess; 113 } 114 115 /////////////////////////////////////////////////////////////////////////////// 116 117 extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*); 118 119 SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) { 120 SkImageDecoder* decoder = image_decoder_from_stream(stream); 121 if (NULL == decoder) { 122 // If no image decoder specific to the stream exists, use SkImageDecoder_CG. 123 return SkNEW(SkImageDecoder_CG); 124 } else { 125 return decoder; 126 } 127 } 128 129 ///////////////////////////////////////////////////////////////////////// 130 131 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { 132 return NULL; 133 } 134 135 ///////////////////////////////////////////////////////////////////////// 136 137 static size_t consumer_put(void* info, const void* buffer, size_t count) { 138 SkWStream* stream = reinterpret_cast<SkWStream*>(info); 139 return stream->write(buffer, count) ? count : 0; 140 } 141 142 static void consumer_release(void* info) { 143 // we do nothing, since by design we don't "own" the stream (i.e. info) 144 } 145 146 static CGDataConsumerRef SkStreamToCGDataConsumer(SkWStream* stream) { 147 CGDataConsumerCallbacks procs; 148 procs.putBytes = consumer_put; 149 procs.releaseConsumer = consumer_release; 150 // we don't own/reference the stream, so it our consumer must not live 151 // longer that our caller's ownership of the stream 152 return CGDataConsumerCreate(stream, &procs); 153 } 154 155 static CGImageDestinationRef SkStreamToImageDestination(SkWStream* stream, 156 CFStringRef type) { 157 CGDataConsumerRef consumer = SkStreamToCGDataConsumer(stream); 158 if (NULL == consumer) { 159 return NULL; 160 } 161 SkAutoTCallVProc<const void, CFRelease> arconsumer(consumer); 162 163 return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, NULL); 164 } 165 166 class SkImageEncoder_CG : public SkImageEncoder { 167 public: 168 SkImageEncoder_CG(Type t) : fType(t) {} 169 170 protected: 171 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); 172 173 private: 174 Type fType; 175 }; 176 177 /* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes 178 to our SkWStream. Since we don't reference/own the SkWStream, our consumer 179 must only live for the duration of the onEncode() method. 180 */ 181 bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm, 182 int quality) { 183 // Used for converting a bitmap to 8888. 184 const SkBitmap* bmPtr = &bm; 185 SkBitmap bitmap8888; 186 187 CFStringRef type; 188 switch (fType) { 189 case kICO_Type: 190 type = kUTTypeICO; 191 break; 192 case kBMP_Type: 193 type = kUTTypeBMP; 194 break; 195 case kGIF_Type: 196 type = kUTTypeGIF; 197 break; 198 case kJPEG_Type: 199 type = kUTTypeJPEG; 200 break; 201 case kPNG_Type: 202 // PNG encoding an ARGB_4444 bitmap gives the following errors in GM: 203 // <Error>: CGImageDestinationAddImage image could not be converted to destination 204 // format. 205 // <Error>: CGImageDestinationFinalize image destination does not have enough images 206 // So instead we copy to 8888. 207 if (bm.colorType() == kARGB_4444_SkColorType) { 208 bm.copyTo(&bitmap8888, kN32_SkColorType); 209 bmPtr = &bitmap8888; 210 } 211 type = kUTTypePNG; 212 break; 213 default: 214 return false; 215 } 216 217 CGImageDestinationRef dst = SkStreamToImageDestination(stream, type); 218 if (NULL == dst) { 219 return false; 220 } 221 SkAutoTCallVProc<const void, CFRelease> ardst(dst); 222 223 CGImageRef image = SkCreateCGImageRef(*bmPtr); 224 if (NULL == image) { 225 return false; 226 } 227 SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image); 228 229 CGImageDestinationAddImage(dst, image, NULL); 230 return CGImageDestinationFinalize(dst); 231 } 232 233 /////////////////////////////////////////////////////////////////////////////// 234 235 static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) { 236 switch (t) { 237 case SkImageEncoder::kICO_Type: 238 case SkImageEncoder::kBMP_Type: 239 case SkImageEncoder::kGIF_Type: 240 case SkImageEncoder::kJPEG_Type: 241 case SkImageEncoder::kPNG_Type: 242 break; 243 default: 244 return NULL; 245 } 246 return SkNEW_ARGS(SkImageEncoder_CG, (t)); 247 } 248 249 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory); 250 251 struct FormatConversion { 252 CFStringRef fUTType; 253 SkImageDecoder::Format fFormat; 254 }; 255 256 // Array of the types supported by the decoder. 257 static const FormatConversion gFormatConversions[] = { 258 { kUTTypeBMP, SkImageDecoder::kBMP_Format }, 259 { kUTTypeGIF, SkImageDecoder::kGIF_Format }, 260 { kUTTypeICO, SkImageDecoder::kICO_Format }, 261 { kUTTypeJPEG, SkImageDecoder::kJPEG_Format }, 262 // Also include JPEG2000 263 { kUTTypeJPEG2000, SkImageDecoder::kJPEG_Format }, 264 { kUTTypePNG, SkImageDecoder::kPNG_Format }, 265 }; 266 267 static SkImageDecoder::Format UTType_to_Format(const CFStringRef uttype) { 268 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) { 269 if (CFStringCompare(uttype, gFormatConversions[i].fUTType, 0) == kCFCompareEqualTo) { 270 return gFormatConversions[i].fFormat; 271 } 272 } 273 return SkImageDecoder::kUnknown_Format; 274 } 275 276 static SkImageDecoder::Format get_format_cg(SkStreamRewindable* stream) { 277 CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); 278 279 if (NULL == imageSrc) { 280 return SkImageDecoder::kUnknown_Format; 281 } 282 283 SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc); 284 const CFStringRef name = CGImageSourceGetType(imageSrc); 285 if (NULL == name) { 286 return SkImageDecoder::kUnknown_Format; 287 } 288 return UTType_to_Format(name); 289 } 290 291 static SkImageDecoder_FormatReg gFormatReg(get_format_cg); 292