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 "SkStreamPriv.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
28static void malloc_release_proc(void* info, const void* data, size_t size) {
29    sk_free(info);
30}
31
32static 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 = SkCopyStreamToStorage(&storage, stream);
36    void* data = storage.detach();
37
38    return CGDataProviderCreateWithData(data, data, len, malloc_release_proc);
39}
40
41static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
42    CGDataProviderRef data = SkStreamToDataProvider(stream);
43    SkASSERT(data);
44    CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0);
45    CGDataProviderRelease(data);
46    return imageSrc;
47}
48
49class SkImageDecoder_CG : public SkImageDecoder {
50protected:
51    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
52};
53
54static void argb_4444_force_opaque(void* row, int count) {
55    uint16_t* row16 = (uint16_t*)row;
56    for (int i = 0; i < count; ++i) {
57        row16[i] |= 0xF000;
58    }
59}
60
61static void argb_8888_force_opaque(void* row, int count) {
62    // can use RGBA or BGRA, they have the same shift for alpha
63    const uint32_t alphaMask = 0xFF << SK_RGBA_A32_SHIFT;
64    uint32_t* row32 = (uint32_t*)row;
65    for (int i = 0; i < count; ++i) {
66        row32[i] |= alphaMask;
67    }
68}
69
70static void alpha_8_force_opaque(void* row, int count) {
71    memset(row, 0xFF, count);
72}
73
74static void force_opaque(SkBitmap* bm) {
75    SkAutoLockPixels alp(*bm);
76    if (!bm->getPixels()) {
77        return;
78    }
79
80    void (*proc)(void*, int);
81    switch (bm->colorType()) {
82        case kARGB_4444_SkColorType:
83            proc = argb_4444_force_opaque;
84            break;
85        case kRGBA_8888_SkColorType:
86        case kBGRA_8888_SkColorType:
87            proc = argb_8888_force_opaque;
88            break;
89        case kAlpha_8_SkColorType:
90            proc = alpha_8_force_opaque;
91            break;
92        default:
93            return;
94    }
95
96    char* row = (char*)bm->getPixels();
97    for (int y = 0; y < bm->height(); ++y) {
98        proc(row, bm->width());
99        row += bm->rowBytes();
100    }
101    bm->setAlphaType(kOpaque_SkAlphaType);
102}
103
104#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
105
106bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
107    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
108
109    if (NULL == imageSrc) {
110        return false;
111    }
112    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
113
114    CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
115    if (NULL == image) {
116        return false;
117    }
118    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
119
120    const int width = SkToInt(CGImageGetWidth(image));
121    const int height = SkToInt(CGImageGetHeight(image));
122
123    bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
124    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
125        return true;
126    }
127
128    if (!this->allocPixelRef(bm, NULL)) {
129        return false;
130    }
131
132    SkAutoLockPixels alp(*bm);
133
134    if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) {
135        return false;
136    }
137
138    CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
139    switch (info) {
140        case kCGImageAlphaNone:
141        case kCGImageAlphaNoneSkipLast:
142        case kCGImageAlphaNoneSkipFirst:
143            // We're opaque, but we can't rely on the data always having 0xFF
144            // in the alpha slot (which Skia wants), so we have to ram it in
145            // ourselves.
146            force_opaque(bm);
147            break;
148        default:
149            // we don't know if we're opaque or not, so compute it.
150            if (SkBitmap::ComputeIsOpaque(*bm)) {
151                bm->setAlphaType(kOpaque_SkAlphaType);
152            }
153    }
154    if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
155        // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
156        // Convert to unpremultiplied.
157        for (int i = 0; i < width; ++i) {
158            for (int j = 0; j < height; ++j) {
159                uint32_t* addr = bm->getAddr32(i, j);
160                *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
161            }
162        }
163        bm->setAlphaType(kUnpremul_SkAlphaType);
164    }
165    return true;
166}
167
168///////////////////////////////////////////////////////////////////////////////
169
170extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
171
172SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
173    SkImageDecoder* decoder = image_decoder_from_stream(stream);
174    if (NULL == decoder) {
175        // If no image decoder specific to the stream exists, use SkImageDecoder_CG.
176        return SkNEW(SkImageDecoder_CG);
177    } else {
178        return decoder;
179    }
180}
181
182/////////////////////////////////////////////////////////////////////////
183
184SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
185    return NULL;
186}
187
188/////////////////////////////////////////////////////////////////////////
189
190static size_t consumer_put(void* info, const void* buffer, size_t count) {
191    SkWStream* stream = reinterpret_cast<SkWStream*>(info);
192    return stream->write(buffer, count) ? count : 0;
193}
194
195static void consumer_release(void* info) {
196    // we do nothing, since by design we don't "own" the stream (i.e. info)
197}
198
199static CGDataConsumerRef SkStreamToCGDataConsumer(SkWStream* stream) {
200    CGDataConsumerCallbacks procs;
201    procs.putBytes = consumer_put;
202    procs.releaseConsumer = consumer_release;
203    // we don't own/reference the stream, so it our consumer must not live
204    // longer that our caller's ownership of the stream
205    return CGDataConsumerCreate(stream, &procs);
206}
207
208static CGImageDestinationRef SkStreamToImageDestination(SkWStream* stream,
209                                                        CFStringRef type) {
210    CGDataConsumerRef consumer = SkStreamToCGDataConsumer(stream);
211    if (NULL == consumer) {
212        return NULL;
213    }
214    SkAutoTCallVProc<const void, CFRelease> arconsumer(consumer);
215
216    return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, NULL);
217}
218
219class SkImageEncoder_CG : public SkImageEncoder {
220public:
221    SkImageEncoder_CG(Type t) : fType(t) {}
222
223protected:
224    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
225
226private:
227    Type fType;
228};
229
230/*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
231    to our SkWStream. Since we don't reference/own the SkWStream, our consumer
232    must only live for the duration of the onEncode() method.
233 */
234bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
235                                 int quality) {
236    // Used for converting a bitmap to 8888.
237    const SkBitmap* bmPtr = &bm;
238    SkBitmap bitmap8888;
239
240    CFStringRef type;
241    switch (fType) {
242        case kICO_Type:
243            type = kUTTypeICO;
244            break;
245        case kBMP_Type:
246            type = kUTTypeBMP;
247            break;
248        case kGIF_Type:
249            type = kUTTypeGIF;
250            break;
251        case kJPEG_Type:
252            type = kUTTypeJPEG;
253            break;
254        case kPNG_Type:
255            // PNG encoding an ARGB_4444 bitmap gives the following errors in GM:
256            // <Error>: CGImageDestinationAddImage image could not be converted to destination
257            // format.
258            // <Error>: CGImageDestinationFinalize image destination does not have enough images
259            // So instead we copy to 8888.
260            if (bm.colorType() == kARGB_4444_SkColorType) {
261                bm.copyTo(&bitmap8888, kN32_SkColorType);
262                bmPtr = &bitmap8888;
263            }
264            type = kUTTypePNG;
265            break;
266        default:
267            return false;
268    }
269
270    CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
271    if (NULL == dst) {
272        return false;
273    }
274    SkAutoTCallVProc<const void, CFRelease> ardst(dst);
275
276    CGImageRef image = SkCreateCGImageRef(*bmPtr);
277    if (NULL == image) {
278        return false;
279    }
280    SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);
281
282    CGImageDestinationAddImage(dst, image, NULL);
283    return CGImageDestinationFinalize(dst);
284}
285
286///////////////////////////////////////////////////////////////////////////////
287
288static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) {
289    switch (t) {
290        case SkImageEncoder::kICO_Type:
291        case SkImageEncoder::kBMP_Type:
292        case SkImageEncoder::kGIF_Type:
293        case SkImageEncoder::kJPEG_Type:
294        case SkImageEncoder::kPNG_Type:
295            break;
296        default:
297            return NULL;
298    }
299    return SkNEW_ARGS(SkImageEncoder_CG, (t));
300}
301
302static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory);
303
304#ifdef SK_BUILD_FOR_IOS
305class SkPNGImageEncoder_IOS : public SkImageEncoder_CG {
306public:
307    SkPNGImageEncoder_IOS()
308        : SkImageEncoder_CG(kPNG_Type) {
309    }
310};
311
312DEFINE_ENCODER_CREATOR(PNGImageEncoder_IOS);
313#endif
314
315struct FormatConversion {
316    CFStringRef             fUTType;
317    SkImageDecoder::Format  fFormat;
318};
319
320// Array of the types supported by the decoder.
321static const FormatConversion gFormatConversions[] = {
322    { kUTTypeBMP, SkImageDecoder::kBMP_Format },
323    { kUTTypeGIF, SkImageDecoder::kGIF_Format },
324    { kUTTypeICO, SkImageDecoder::kICO_Format },
325    { kUTTypeJPEG, SkImageDecoder::kJPEG_Format },
326    // Also include JPEG2000
327    { kUTTypeJPEG2000, SkImageDecoder::kJPEG_Format },
328    { kUTTypePNG, SkImageDecoder::kPNG_Format },
329};
330
331static SkImageDecoder::Format UTType_to_Format(const CFStringRef uttype) {
332    for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
333        if (CFStringCompare(uttype, gFormatConversions[i].fUTType, 0) == kCFCompareEqualTo) {
334            return gFormatConversions[i].fFormat;
335        }
336    }
337    return SkImageDecoder::kUnknown_Format;
338}
339
340static SkImageDecoder::Format get_format_cg(SkStreamRewindable* stream) {
341    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
342
343    if (NULL == imageSrc) {
344        return SkImageDecoder::kUnknown_Format;
345    }
346
347    SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
348    const CFStringRef name = CGImageSourceGetType(imageSrc);
349    if (NULL == name) {
350        return SkImageDecoder::kUnknown_Format;
351    }
352    return UTType_to_Format(name);
353}
354
355static SkImageDecoder_FormatReg gFormatReg(get_format_cg);
356