blob: da8bf15a11fa33058c5d801b86ed51d31607437c [file] [log] [blame]
reed@android.com0767e472008-12-23 16:06:51 +00001/* Copyright 2008, The Android Open Source Project
2**
3** Licensed under the Apache License, Version 2.0 (the "License");
4** you may not use this file except in compliance with the License.
5** You may obtain a copy of the License at
6**
7** http://www.apache.org/licenses/LICENSE-2.0
8**
9** Unless required by applicable law or agreed to in writing, software
10** distributed under the License is distributed on an "AS IS" BASIS,
11** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12** See the License for the specific language governing permissions and
13** limitations under the License.
14*/
15
16#include <Carbon/Carbon.h>
17#include "SkImageDecoder.h"
18#include "SkMovie.h"
19#include "SkStream.h"
20#include "SkTemplates.h"
21
22static void malloc_release_proc(void* info, const void* data, size_t size) {
23 sk_free(info);
24}
25
26static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) {
27 // TODO: use callbacks, so we don't have to load all the data into RAM
28 size_t len = stream->getLength();
29 void* data = sk_malloc_throw(len);
30 stream->read(data, len);
31
32 return CGDataProviderCreateWithData(data, data, len, malloc_release_proc);
33}
34
35static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
36 CGDataProviderRef data = SkStreamToDataProvider(stream);
37 CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0);
38 CGDataProviderRelease(data);
39 return imageSrc;
40}
41
42class SkImageDecoder_CG : public SkImageDecoder {
43protected:
44 virtual bool onDecode(SkStream* stream, SkBitmap* bm,
45 SkBitmap::Config pref, Mode);
46};
47
48#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
49
50bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm,
51 SkBitmap::Config pref, Mode mode) {
52 CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
53
54 if (NULL == imageSrc) {
55 return false;
56 }
57
58 SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
59
60 CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
61 if (NULL == image) {
62 return false;
63 }
64
65 SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
66
67 const int width = CGImageGetWidth(image);
68 const int height = CGImageGetHeight(image);
69 bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
70 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
71 return true;
72 }
73
74 if (!this->allocPixelRef(bm, NULL)) {
75 return false;
76 }
77
78 bm->lockPixels();
79 bm->eraseColor(0);
80
81 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
82 CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height,
83 8, bm->rowBytes(), cs, BITMAP_INFO);
84 CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
85 CGContextRelease(cg);
86 CGColorSpaceRelease(cs);
87
88 bm->unlockPixels();
89 return true;
90}
91
92///////////////////////////////////////////////////////////////////////////////
93
94SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
95 return SkNEW(SkImageDecoder_CG);
96}
97
98bool SkImageDecoder::SupportsFormat(Format format) {
99 return true;
100}
101
102/////////////////////////////////////////////////////////////////////////
103
104SkMovie* SkMovie::DecodeStream(SkStream* stream) {
105 return NULL;
106}
107
108/////////////////////////////////////////////////////////////////////////
109
110#ifdef SK_SUPPORT_IMAGE_ENCODE
111
112SkImageEncoder* SkImageEncoder::Create(Type t) {
113#if 0
114 switch (t) {
115 case kJPEG_Type:
116 return SkImageEncoder_JPEG_Factory();
117 case kPNG_Type:
118 return SkImageEncoder_PNG_Factory();
119 default:
120 return NULL;
121 }
122#else
123 return NULL;
124#endif
125}
126
127#endif