Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkDecodingImageGenerator.cpp
1 /*
2  * Copyright 2013 Google Inc.
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 "SkData.h"
9 #include "SkDecodingImageGenerator.h"
10 #include "SkImageDecoder.h"
11 #include "SkImageInfo.h"
12 #include "SkImageGenerator.h"
13 #include "SkImagePriv.h"
14 #include "SkStream.h"
15 #include "SkUtils.h"
16
17 namespace {
18 bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
19     return a.width() == b.width() && a.height() == b.height() &&
20            a.colorType() == b.colorType();
21 }
22
23 class DecodingImageGenerator : public SkImageGenerator {
24 public:
25     virtual ~DecodingImageGenerator();
26
27     SkData*                fData;
28     SkStreamRewindable*    fStream;
29     const SkImageInfo      fInfo;
30     const int              fSampleSize;
31     const bool             fDitherImage;
32
33     DecodingImageGenerator(SkData* data,
34                            SkStreamRewindable* stream,
35                            const SkImageInfo& info,
36                            int sampleSize,
37                            bool ditherImage);
38
39 protected:
40     virtual SkData* onRefEncodedData() SK_OVERRIDE;
41     virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
42         *info = fInfo;
43         return true;
44     }
45     virtual bool onGetPixels(const SkImageInfo& info,
46                              void* pixels, size_t rowBytes,
47                              SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
48     virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
49                                  SkYUVColorSpace* colorSpace) SK_OVERRIDE;
50
51 private:
52     typedef SkImageGenerator INHERITED;
53 };
54
55 /**
56  *  Special allocator used by getPixels(). Uses preallocated memory
57  *  provided if possible, else fall-back on the default allocator
58  */
59 class TargetAllocator : public SkBitmap::Allocator {
60 public:
61     TargetAllocator(const SkImageInfo& info,
62                     void* target,
63                     size_t rowBytes)
64         : fInfo(info)
65         , fTarget(target)
66         , fRowBytes(rowBytes)
67     {}
68
69     bool isReady() { return (fTarget != NULL); }
70
71     virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
72         if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
73             // Call default allocator.
74             return bm->tryAllocPixels(NULL, ct);
75         }
76
77         // TODO(halcanary): verify that all callers of this function
78         // will respect new RowBytes.  Will be moot once rowbytes belongs
79         // to PixelRef.
80         bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
81
82         fTarget = NULL;  // never alloc same pixels twice!
83         return true;
84     }
85
86 private:
87     const SkImageInfo fInfo;
88     void* fTarget;  // Block of memory to be supplied as pixel memory
89                     // in allocPixelRef.  Must be large enough to hold
90                     // a bitmap described by fInfo and fRowBytes
91     const size_t fRowBytes;  // rowbytes for the destination bitmap
92
93     typedef SkBitmap::Allocator INHERITED;
94 };
95
96 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
97 #ifdef SK_DEBUG
98     #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
99 #else
100     #define SkCheckResult(expr, value)  (void)(expr)
101 #endif
102
103 #ifdef SK_DEBUG
104 inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
105     return ((reported == actual)
106             || ((reported == kPremul_SkAlphaType)
107                 && (actual == kOpaque_SkAlphaType)));
108 }
109 #endif  // SK_DEBUG
110
111 ////////////////////////////////////////////////////////////////////////////////
112
113 DecodingImageGenerator::DecodingImageGenerator(
114         SkData* data,
115         SkStreamRewindable* stream,
116         const SkImageInfo& info,
117         int sampleSize,
118         bool ditherImage)
119     : fData(data)
120     , fStream(stream)
121     , fInfo(info)
122     , fSampleSize(sampleSize)
123     , fDitherImage(ditherImage)
124 {
125     SkASSERT(stream != NULL);
126     SkSafeRef(fData);  // may be NULL.
127 }
128
129 DecodingImageGenerator::~DecodingImageGenerator() {
130     SkSafeUnref(fData);
131     fStream->unref();
132 }
133
134 SkData* DecodingImageGenerator::onRefEncodedData() {
135     // This functionality is used in `gm --serialize`
136     // Does not encode options.
137     if (NULL == fData) {
138         // TODO(halcanary): SkStreamRewindable needs a refData() function
139         // which returns a cheap copy of the underlying data.
140         if (!fStream->rewind()) {
141             return NULL;
142         }
143         size_t length = fStream->getLength();
144         if (length) {
145             fData = SkData::NewFromStream(fStream, length);
146         }
147     }
148     return SkSafeRef(fData);
149 }
150
151 bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
152                                          void* pixels, size_t rowBytes,
153                                          SkPMColor ctableEntries[], int* ctableCount) {
154     if (fInfo != info) {
155         // The caller has specified a different info.  This is an
156         // error for this kind of SkImageGenerator.  Use the Options
157         // to change the settings.
158         return false;
159     }
160
161     SkAssertResult(fStream->rewind());
162     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
163     if (NULL == decoder.get()) {
164         return false;
165     }
166     decoder->setDitherImage(fDitherImage);
167     decoder->setSampleSize(fSampleSize);
168     decoder->setRequireUnpremultipliedColors(info.alphaType() == kUnpremul_SkAlphaType);
169
170     SkBitmap bitmap;
171     TargetAllocator allocator(fInfo, pixels, rowBytes);
172     decoder->setAllocator(&allocator);
173     bool success = decoder->decode(fStream, &bitmap, info.colorType(),
174                                    SkImageDecoder::kDecodePixels_Mode) != SkImageDecoder::kFailure;
175     decoder->setAllocator(NULL);
176     if (!success) {
177         return false;
178     }
179     if (allocator.isReady()) {  // Did not use pixels!
180         SkBitmap bm;
181         SkASSERT(bitmap.canCopyTo(info.colorType()));
182         bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
183         if (!copySuccess || allocator.isReady()) {
184             SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
185             // Earlier we checked canCopyto(); we expect consistency.
186             return false;
187         }
188         SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
189     } else {
190         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
191     }
192
193     if (kIndex_8_SkColorType == info.colorType()) {
194         if (kIndex_8_SkColorType != bitmap.colorType()) {
195             return false;   // they asked for Index8, but we didn't receive that from decoder
196         }
197         SkColorTable* ctable = bitmap.getColorTable();
198         if (NULL == ctable) {
199             return false;
200         }
201         const int count = ctable->count();
202         memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
203         ctable->unlockColors();
204         *ctableCount = count;
205     }
206     return true;
207 }
208
209 bool DecodingImageGenerator::onGetYUV8Planes(SkISize sizes[3], void* planes[3],
210                                              size_t rowBytes[3], SkYUVColorSpace* colorSpace) {
211     if (!fStream->rewind()) {
212         return false;
213     }
214
215     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
216     if (NULL == decoder.get()) {
217         return false;
218     }
219
220     return decoder->decodeYUV8Planes(fStream, sizes, planes, rowBytes, colorSpace);
221 }
222
223 // A contructor-type function that returns NULL on failure.  This
224 // prevents the returned SkImageGenerator from ever being in a bad
225 // state.  Called by both Create() functions
226 SkImageGenerator* CreateDecodingImageGenerator(
227         SkData* data,
228         SkStreamRewindable* stream,
229         const SkDecodingImageGenerator::Options& opts) {
230     SkASSERT(stream);
231     SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
232     SkAssertResult(autoStream->rewind());
233     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
234     if (NULL == decoder.get()) {
235         return NULL;
236     }
237     SkBitmap bitmap;
238     decoder->setSampleSize(opts.fSampleSize);
239     decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
240     if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
241         return NULL;
242     }
243     if (kUnknown_SkColorType == bitmap.colorType()) {
244         return NULL;
245     }
246
247     SkImageInfo info = bitmap.info();
248
249     if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
250         if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
251             SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
252             return NULL;  // Can not translate to needed config.
253         }
254         info = info.makeColorType(opts.fRequestedColorType);
255     }
256
257     if (opts.fRequireUnpremul && info.alphaType() != kOpaque_SkAlphaType) {
258         info = info.makeAlphaType(kUnpremul_SkAlphaType);
259     }
260
261     SkAlphaType newAlphaType = info.alphaType();
262     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)) {
263         return NULL;
264     }
265
266     return SkNEW_ARGS(DecodingImageGenerator,
267                       (data, autoStream.detach(), info.makeAlphaType(newAlphaType),
268                        opts.fSampleSize, opts.fDitherImage));
269 }
270
271 }  // namespace
272
273 ////////////////////////////////////////////////////////////////////////////////
274
275 SkImageGenerator* SkDecodingImageGenerator::Create(
276         SkData* data,
277         const SkDecodingImageGenerator::Options& opts) {
278     SkASSERT(data != NULL);
279     if (NULL == data) {
280         return NULL;
281     }
282     SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
283     SkASSERT(stream != NULL);
284     SkASSERT(stream->unique());
285     return CreateDecodingImageGenerator(data, stream, opts);
286 }
287
288 SkImageGenerator* SkDecodingImageGenerator::Create(
289         SkStreamRewindable* stream,
290         const SkDecodingImageGenerator::Options& opts) {
291     SkASSERT(stream != NULL);
292     SkASSERT(stream->unique());
293     if ((stream == NULL) || !stream->unique()) {
294         SkSafeUnref(stream);
295         return NULL;
296     }
297     return CreateDecodingImageGenerator(NULL, stream, opts);
298 }