~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/skia/src/ports/SkImageDecoder_CG.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 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 "SkImageEncoder.h"
 
19
#include "SkMovie.h"
 
20
#include "SkStream.h"
 
21
#include "SkTemplates.h"
 
22
 
 
23
static void malloc_release_proc(void* info, const void* data, size_t size) {
 
24
    sk_free(info);
 
25
}
 
26
 
 
27
static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) {
 
28
    // TODO: use callbacks, so we don't have to load all the data into RAM
 
29
    size_t len = stream->getLength();
 
30
    void* data = sk_malloc_throw(len);
 
31
    stream->read(data, len);
 
32
    
 
33
    return CGDataProviderCreateWithData(data, data, len, malloc_release_proc);
 
34
}
 
35
 
 
36
static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
 
37
    CGDataProviderRef data = SkStreamToDataProvider(stream);
 
38
    CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0);
 
39
    CGDataProviderRelease(data);
 
40
    return imageSrc;
 
41
}
 
42
 
 
43
class SkImageDecoder_CG : public SkImageDecoder {
 
44
protected:
 
45
    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
 
46
                          SkBitmap::Config pref, Mode);
 
47
};
 
48
 
 
49
#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
 
50
 
 
51
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm,
 
52
                                 SkBitmap::Config pref, Mode mode) {
 
53
    CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
 
54
 
 
55
    if (NULL == imageSrc) {
 
56
        return false;
 
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
    SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
 
65
    
 
66
    const int width = CGImageGetWidth(image);
 
67
    const int height = CGImageGetHeight(image);
 
68
    bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
 
69
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
 
70
        return true;
 
71
    }
 
72
    
 
73
    if (!this->allocPixelRef(bm, NULL)) {
 
74
        return false;
 
75
    }
 
76
    
 
77
    bm->lockPixels();
 
78
    bm->eraseColor(0);
 
79
 
 
80
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
 
81
    CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height,
 
82
                                            8, bm->rowBytes(), cs, BITMAP_INFO);
 
83
    CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
 
84
    CGContextRelease(cg);
 
85
    CGColorSpaceRelease(cs);
 
86
 
 
87
    bm->unlockPixels();
 
88
    return true;
 
89
}
 
90
 
 
91
///////////////////////////////////////////////////////////////////////////////
 
92
 
 
93
SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
 
94
    return SkNEW(SkImageDecoder_CG);
 
95
}
 
96
 
 
97
/////////////////////////////////////////////////////////////////////////
 
98
 
 
99
SkMovie* SkMovie::DecodeStream(SkStream* stream) {
 
100
    return NULL;
 
101
}
 
102
 
 
103
/////////////////////////////////////////////////////////////////////////
 
104
 
 
105
static size_t consumer_put(void* info, const void* buffer, size_t count) {
 
106
    SkWStream* stream = reinterpret_cast<SkWStream*>(info);
 
107
    return stream->write(buffer, count) ? count : 0;
 
108
}
 
109
 
 
110
static void consumer_release(void* info) {
 
111
    // we do nothing, since by design we don't "own" the stream (i.e. info)
 
112
}
 
113
 
 
114
static CGDataConsumerRef SkStreamToCGDataConsumer(SkWStream* stream) {
 
115
    CGDataConsumerCallbacks procs;
 
116
    procs.putBytes = consumer_put;
 
117
    procs.releaseConsumer = consumer_release;
 
118
    // we don't own/reference the stream, so it our consumer must not live
 
119
    // longer that our caller's ownership of the stream
 
120
    return CGDataConsumerCreate(stream, &procs);
 
121
}
 
122
 
 
123
static CGImageDestinationRef SkStreamToImageDestination(SkWStream* stream,
 
124
                                                        CFStringRef type) {
 
125
    CGDataConsumerRef consumer = SkStreamToCGDataConsumer(stream);
 
126
    if (NULL == consumer) {
 
127
        return NULL;
 
128
    }
 
129
    SkAutoTCallVProc<const void, CFRelease> arconsumer(consumer);
 
130
    
 
131
    return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, NULL);
 
132
}
 
133
 
 
134
class SkImageEncoder_CG : public SkImageEncoder {
 
135
public:
 
136
    SkImageEncoder_CG(Type t) : fType(t) {}
 
137
 
 
138
protected:
 
139
    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
 
140
    
 
141
private:
 
142
    Type fType;
 
143
};
 
144
 
 
145
extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
 
146
 
 
147
/*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
 
148
    to our SkWStream. Since we don't reference/own the SkWStream, our consumer
 
149
    must only live for the duration of the onEncode() method.
 
150
 */
 
151
bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
 
152
                                 int quality) {
 
153
    CFStringRef type;
 
154
    switch (fType) {
 
155
        case kJPEG_Type:
 
156
            type = kUTTypeJPEG;
 
157
            break;
 
158
        case kPNG_Type:
 
159
            type = kUTTypePNG;
 
160
            break;
 
161
        default:
 
162
            return false;
 
163
    }
 
164
    
 
165
    CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
 
166
    if (NULL == dst) {
 
167
        return false;
 
168
    }
 
169
    SkAutoTCallVProc<const void, CFRelease> ardst(dst);
 
170
 
 
171
    CGImageRef image = SkCreateCGImageRef(bm);
 
172
    if (NULL == image) {
 
173
        return false;
 
174
    }
 
175
    SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);
 
176
    
 
177
        CGImageDestinationAddImage(dst, image, NULL);
 
178
        CGImageDestinationFinalize(dst);
 
179
    return true;
 
180
}
 
181
 
 
182
SkImageEncoder* SkImageEncoder::Create(Type t) {
 
183
    switch (t) {
 
184
        case kJPEG_Type:
 
185
        case kPNG_Type:
 
186
            break;
 
187
        default:
 
188
            return NULL;
 
189
    }
 
190
    return SkNEW_ARGS(SkImageEncoder_CG, (t));
 
191
}
 
192