OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkDecodingImageGenerator.h" | 8 #include "SkDecodingImageGenerator.h" |
9 #include "SkData.h" | 9 #include "SkData.h" |
10 #include "SkDiscardablePixelRef.h" | 10 #include "SkDiscardablePixelRef.h" |
11 #include "SkImageDecoder.h" | 11 #include "SkImageDecoder.h" |
12 #include "SkImagePriv.h" | |
13 #include "SkStream.h" | |
14 | |
15 | |
16 namespace { | |
17 /** | |
18 * Special allocator used by getPixels(). Uses preallocated memory | |
19 * provided. | |
20 */ | |
21 class TargetAllocator : public SkBitmap::Allocator { | |
22 public: | |
23 TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info) | |
24 : fTarget(target) | |
25 , fRowBytes(rowBytes) | |
26 , fInfo(info) { } | |
27 | |
28 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE { | |
29 if ((SkImageInfoToBitmapConfig(fInfo) != bm->config()) | |
30 || (bm->width() != fInfo.fWidth) | |
31 || (bm->height() != fInfo.fHeight)) { | |
32 return false; | |
33 } | |
34 bm->setConfig(bm->config(), bm->width(), bm->height(), | |
35 fRowBytes, bm->alphaType()); | |
36 bm->setPixels(fTarget, ct); | |
37 return true; | |
38 } | |
39 | |
40 private: | |
41 void* fTarget; | |
42 size_t fRowBytes; | |
43 SkImageInfo fInfo; | |
44 typedef SkBitmap::Allocator INHERITED; | |
45 }; | |
46 } // namespace | |
47 //////////////////////////////////////////////////////////////////////////////// | |
12 | 48 |
13 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data) | 49 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data) |
14 : fData(data) { | 50 : fData(data) |
51 , fHasInfo(false) | |
52 , fDoCopyTo(false) { | |
15 SkASSERT(fData != NULL); | 53 SkASSERT(fData != NULL); |
54 fStream = SkNEW_ARGS(SkMemoryStream, (fData)); | |
55 SkASSERT(fStream != NULL); | |
16 fData->ref(); | 56 fData->ref(); |
17 } | 57 } |
18 | 58 |
59 SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream) | |
60 : fData(NULL) | |
61 , fStream(stream) | |
62 , fHasInfo(false) | |
63 , fDoCopyTo(false) { | |
64 SkASSERT(fStream != NULL); | |
65 fHasInfo = false; | |
66 } | |
67 | |
19 SkDecodingImageGenerator::~SkDecodingImageGenerator() { | 68 SkDecodingImageGenerator::~SkDecodingImageGenerator() { |
20 fData->unref(); | 69 SkSafeUnref(fData); |
70 fStream->unref(); | |
21 } | 71 } |
22 | 72 |
23 SkData* SkDecodingImageGenerator::refEncodedData() { | 73 SkData* SkDecodingImageGenerator::refEncodedData() { |
24 // This functionality is used in `gm --serialize` | 74 // This functionality is used in `gm --serialize` |
25 fData->ref(); | 75 if (fData != NULL) { |
26 return fData; | 76 return SkSafeRef(fData); |
77 } | |
78 fData = fStream->getData(); | |
79 if (fData != NULL) { | |
80 return SkSafeRef(fData); | |
81 } | |
82 return SkData::NewWithCopyFromStream(fStream); | |
27 } | 83 } |
28 | 84 |
29 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) { | 85 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) { |
30 SkASSERT(info != NULL); | 86 // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo. |
31 return SkImageDecoder::DecodeMemoryToTarget(fData->data(), | 87 if (fHasInfo) { |
32 fData->size(), | 88 if (info != NULL) { |
33 info, NULL); | 89 *info = fInfo; |
90 } | |
91 return true; | |
92 } | |
93 SkAssertResult(fStream->rewind()); | |
94 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); | |
95 if (NULL == decoder.get()) { | |
96 return false; | |
97 } | |
98 SkBitmap bitmap; | |
99 if (!decoder->decode(fStream, &bitmap, | |
100 SkImageDecoder::kDecodeBounds_Mode)) { | |
101 return false; | |
102 } | |
103 if (bitmap.config() == SkBitmap::kNo_Config) { | |
104 return false; | |
105 } | |
106 if (!SkBitmapToImageInfo(bitmap, &fInfo)) { | |
scroggo
2013/12/05 21:07:18
Once https://codereview.chromium.org/68973005/ is
hal.canary
2013/12/05 22:29:29
That makes sense.
| |
107 // We can't use bitmap.config() as is. | |
108 // Must be kARGB_4444_Config. | |
109 if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) { | |
110 // kARGB_4444_Config can copy to kARGB_8888. | |
111 SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)"); | |
112 return false; | |
113 } | |
114 fDoCopyTo = true; | |
115 fInfo.fWidth = bitmap.width(); | |
116 fInfo.fHeight = bitmap.height(); | |
117 fInfo.fColorType = kPMColor_SkColorType; | |
118 fInfo.fAlphaType = bitmap.alphaType(); | |
119 } | |
120 if (info != NULL) { | |
121 *info = fInfo; | |
122 } | |
123 fHasInfo = true; | |
124 return true; | |
34 } | 125 } |
35 | 126 |
36 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info, | 127 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info, |
37 void* pixels, | 128 void* pixels, |
38 size_t rowBytes) { | 129 size_t rowBytes) { |
39 SkASSERT(pixels != NULL); | 130 if (NULL == pixels) { |
40 SkImageDecoder::Target target = {pixels, rowBytes}; | 131 return false; |
41 SkImageInfo tmpInfo = info; | 132 } |
42 return SkImageDecoder::DecodeMemoryToTarget(fData->data(), | 133 if (!this->getInfo(NULL)) { |
43 fData->size(), | 134 return false; |
44 &tmpInfo, &target); | 135 } |
136 SkAssertResult(fStream->rewind()); | |
137 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); | |
138 if (NULL == decoder.get()) { | |
139 return false; | |
140 } | |
141 if (fInfo != info) { | |
142 // if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) { | |
143 // return false; | |
144 // } | |
145 // The caller has specified a different info. for now, this | |
146 // is an error. In the future, we will check to see if we can | |
147 // convert. | |
148 return false; | |
149 } | |
150 int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info)); | |
151 if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) { | |
152 return false; | |
153 } | |
154 SkBitmap bitmap; | |
155 if (!bitmap.setConfig(info, rowBytes)) { | |
156 return false; | |
157 } | |
158 | |
159 TargetAllocator allocator(pixels, rowBytes, info); | |
160 if (!fDoCopyTo) { | |
161 decoder->setAllocator(&allocator); | |
162 } | |
163 bool success = decoder->decode(fStream, &bitmap, | |
164 SkImageDecoder::kDecodePixels_Mode); | |
165 decoder->setAllocator(NULL); | |
166 if (!success) { | |
167 return false; | |
168 } | |
169 if (fDoCopyTo) { | |
170 SkBitmap bm8888; | |
171 bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator); | |
172 } | |
173 return true; | |
45 } | 174 } |
46 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst, | 175 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst, |
47 SkDiscardableMemory::Factory* factory) { | 176 SkDiscardableMemory::Factory* factory) { |
48 SkASSERT(data != NULL); | 177 SkASSERT(data != NULL); |
49 SkASSERT(dst != NULL); | 178 SkASSERT(dst != NULL); |
50 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data))); | 179 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data))); |
51 return SkDiscardablePixelRef::Install(gen, dst, factory); | 180 return SkDiscardablePixelRef::Install(gen, dst, factory); |
52 } | 181 } |
182 | |
183 bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream, | |
184 SkBitmap* dst, | |
185 SkDiscardableMemory::Factory* factory) { | |
186 SkASSERT(stream != NULL); | |
187 SkASSERT(dst != NULL); | |
188 SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream))); | |
189 return SkDiscardablePixelRef::Install(gen, dst, factory); | |
190 } | |
191 | |
OLD | NEW |