OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
10 #include "SkPixelRef.h" | |
10 #include "SkScaledBitmapSampler.h" | 11 #include "SkScaledBitmapSampler.h" |
11 #include "SkStream.h" | 12 #include "SkStream.h" |
12 #include "SkStreamHelpers.h" | 13 #include "SkStreamHelpers.h" |
13 #include "SkTypes.h" | 14 #include "SkTypes.h" |
14 | 15 |
15 #include "ktx.h" | 16 #include "ktx.h" |
16 #include "etc1.h" | 17 #include "etc1.h" |
17 | 18 |
18 //////////////////////////////////////////////////////////////////////////////// ///////// | 19 //////////////////////////////////////////////////////////////////////////////// ///////// |
19 | 20 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 return false; | 67 return false; |
67 } | 68 } |
68 | 69 |
69 // Setup the sampler... | 70 // Setup the sampler... |
70 SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); | 71 SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); |
71 | 72 |
72 // Set the config... | 73 // Set the config... |
73 bm->setConfig(SkBitmap::kARGB_8888_Config, | 74 bm->setConfig(SkBitmap::kARGB_8888_Config, |
74 sampler.scaledWidth(), sampler.scaledHeight(), | 75 sampler.scaledWidth(), sampler.scaledHeight(), |
75 0, | 76 0, |
76 ktxFile.isRGBA8()? kUnpremul_SkAlphaType : kOpaque_SkAlphaType ); | 77 ktxFile.isRGBA8()? kPremul_SkAlphaType : kOpaque_SkAlphaType); |
77 if (SkImageDecoder::kDecodeBounds_Mode == mode) { | 78 if (SkImageDecoder::kDecodeBounds_Mode == mode) { |
78 return true; | 79 return true; |
79 } | 80 } |
80 | 81 |
81 // If we've made it this far, then we know how to grok the data. | 82 // If we've made it this far, then we know how to grok the data. |
82 if (!this->allocPixelRef(bm, NULL)) { | 83 if (!this->allocPixelRef(bm, NULL)) { |
83 return false; | 84 return false; |
84 } | 85 } |
85 | 86 |
86 // Lock the pixels, since we're about to write to them... | 87 // Lock the pixels, since we're about to write to them... |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 srcRow += sampler.srcY0() * srcRowBytes; | 129 srcRow += sampler.srcY0() * srcRowBytes; |
129 for (int y = 0; y < dstHeight; ++y) { | 130 for (int y = 0; y < dstHeight; ++y) { |
130 sampler.next(srcRow); | 131 sampler.next(srcRow); |
131 srcRow += sampler.srcDY() * srcRowBytes; | 132 srcRow += sampler.srcDY() * srcRowBytes; |
132 } | 133 } |
133 | 134 |
134 return true; | 135 return true; |
135 | 136 |
136 } else if (ktxFile.isRGBA8()) { | 137 } else if (ktxFile.isRGBA8()) { |
137 | 138 |
139 // If we know that the image contains premultiplied alpha, then | |
140 // don't premultiply it upon decoding. | |
141 bool setRequireUnpremul = false; | |
robertphillips
2014/06/05 19:12:19
Can we just do "SkString premulKey("KTXPremultipli
krajcevski
2014/06/05 19:29:43
Done.
| |
142 SkString premulKey = SkString("KTXPremultipliedAlpha"); | |
143 if (ktxFile.getValueForKey(premulKey) == SkString("True")) { | |
144 this->setRequireUnpremultipliedColors(true); | |
145 setRequireUnpremul = true; | |
146 } | |
147 | |
138 // Uncompressed RGBA data | 148 // Uncompressed RGBA data |
139 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, *this)) { | 149 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, *this)) { |
140 return false; | 150 return false; |
141 } | 151 } |
142 | 152 |
143 // Just need to read RGBA pixels | 153 // Just need to read RGBA pixels |
144 const int srcRowBytes = width * 4; | 154 const int srcRowBytes = width * 4; |
145 const int dstHeight = sampler.scaledHeight(); | 155 const int dstHeight = sampler.scaledHeight(); |
146 const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelD ata()); | 156 const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelD ata()); |
147 srcRow += sampler.srcY0() * srcRowBytes; | 157 srcRow += sampler.srcY0() * srcRowBytes; |
148 for (int y = 0; y < dstHeight; ++y) { | 158 for (int y = 0; y < dstHeight; ++y) { |
149 sampler.next(srcRow); | 159 sampler.next(srcRow); |
150 srcRow += sampler.srcDY() * srcRowBytes; | 160 srcRow += sampler.srcDY() * srcRowBytes; |
151 } | 161 } |
152 | 162 |
163 // Reset this in case the decoder needs to be used again. | |
164 if (setRequireUnpremul) { | |
165 this->setRequireUnpremultipliedColors(false); | |
166 } | |
167 | |
153 return true; | 168 return true; |
154 } | 169 } |
155 | 170 |
156 return false; | 171 return false; |
157 } | 172 } |
158 | 173 |
174 /////////////////////////////////////////////////////////////////////////////// | |
175 | |
robertphillips
2014/06/05 19:12:19
// ??
krajcevski
2014/06/05 19:29:43
Done.
| |
176 class SkKTXImageEncoder : public SkImageEncoder { | |
177 protected: | |
178 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK _OVERRIDE; | |
179 | |
180 private: | |
181 virtual bool encodePKM(SkWStream* stream, const SkData *data); | |
182 typedef SkImageEncoder INHERITED; | |
183 }; | |
184 | |
robertphillips
2014/06/05 19:12:20
Can we put onEncode before encodePKM in the file?
krajcevski
2014/06/05 19:29:43
Done.
| |
185 bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) { | |
186 const uint8_t* bytes = data->bytes(); | |
187 SkASSERT(etc1_pkm_is_valid(bytes)); | |
188 | |
189 etc1_uint32 width = etc1_pkm_get_width(bytes); | |
190 etc1_uint32 height = etc1_pkm_get_height(bytes); | |
191 | |
192 // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure | |
193 // that our dimensions are valid. | |
194 if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) { | |
195 return false; | |
196 } | |
197 | |
198 // Advance pointer to etc1 data. | |
199 bytes += ETC_PKM_HEADER_SIZE; | |
200 | |
201 return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height); | |
202 } | |
203 | |
204 bool SkKTXImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) { | |
205 SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData()); | |
206 | |
207 // Is this even encoded data? | |
208 if (NULL != data) { | |
209 const uint8_t *bytes = data->bytes(); | |
210 if (etc1_pkm_is_valid(bytes)) { | |
robertphillips
2014/06/05 19:12:20
this-> ?
krajcevski
2014/06/05 19:29:43
Done.
| |
211 return encodePKM(stream, data); | |
212 } | |
213 | |
214 // Is it a KTX file?? | |
215 if (SkKTXFile::is_ktx(bytes)) { | |
216 return stream->write(bytes, data->size()); | |
217 } | |
218 | |
219 // If it's neither a KTX nor a PKM, then we need to | |
220 // get at the actual pixels, so fall through and decompress... | |
221 } | |
222 | |
223 return SkKTXFile::WriteBitmapToKTX(stream, bitmap); | |
224 } | |
225 | |
226 | |
159 //////////////////////////////////////////////////////////////////////////////// ///////// | 227 //////////////////////////////////////////////////////////////////////////////// ///////// |
160 DEFINE_DECODER_CREATOR(KTXImageDecoder); | 228 DEFINE_DECODER_CREATOR(KTXImageDecoder); |
229 DEFINE_ENCODER_CREATOR(KTXImageEncoder); | |
161 //////////////////////////////////////////////////////////////////////////////// ///////// | 230 //////////////////////////////////////////////////////////////////////////////// ///////// |
162 | 231 |
163 static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) { | 232 static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) { |
164 if (SkKTXFile::is_ktx(stream)) { | 233 if (SkKTXFile::is_ktx(stream)) { |
165 return SkNEW(SkKTXImageDecoder); | 234 return SkNEW(SkKTXImageDecoder); |
166 } | 235 } |
167 return NULL; | 236 return NULL; |
168 } | 237 } |
169 | 238 |
170 static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory); | |
171 | |
172 static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) { | 239 static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) { |
173 if (SkKTXFile::is_ktx(stream)) { | 240 if (SkKTXFile::is_ktx(stream)) { |
174 return SkImageDecoder::kKTX_Format; | 241 return SkImageDecoder::kKTX_Format; |
175 } | 242 } |
176 return SkImageDecoder::kUnknown_Format; | 243 return SkImageDecoder::kUnknown_Format; |
177 } | 244 } |
178 | 245 |
246 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) { | |
247 return (SkImageEncoder::kKTX_Type == t) ? SkNEW(SkKTXImageEncoder) : NULL; | |
248 } | |
249 | |
250 static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory); | |
179 static SkImageDecoder_FormatReg gFormatReg(get_format_ktx); | 251 static SkImageDecoder_FormatReg gFormatReg(get_format_ktx); |
252 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory); | |
OLD | NEW |