Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/images/SkImageDecoder_ktx.cpp

Issue 312353003: Initial KTX encoder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Code review changes Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkImageEncoder.h ('k') | tests/KtxTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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;
142 const SkString premulKey("KTXPremultipliedAlpha");
143 if (ktxFile.getValueForKey(premulKey) == SkString("True")) {
144 this->setRequireUnpremultipliedColors(true);
scroggo 2014/06/09 14:49:45 This is intended as a setting for the client. If t
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);
scroggo 2014/06/09 14:49:45 Again, if the client wanted unpremultiplied colors
166 }
167
153 return true; 168 return true;
154 } 169 }
155 170
156 return false; 171 return false;
157 } 172 }
158 173
174 ///////////////////////////////////////////////////////////////////////////////
175
176 // KTX Image Encoder
177 //
178 // This encoder takes a best guess at how to encode the bitmap passed to it. If
179 // there is an installed discardable pixel ref with existing PKM data, then we
180 // will repurpose the existing ETC1 data into a KTX file. If the data contains
181 // KTX data, then we simply return a copy of the same data. For all other files,
182 // the underlying KTX library tries to do its best to encode the appropriate
183 // data specified by the bitmap based on the config. (i.e. kAlpha8_Config will
184 // be represented as a full resolution 8-bit image dump with the appropriate
185 // OpenGL defines in the header).
186
187 class SkKTXImageEncoder : public SkImageEncoder {
188 protected:
189 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK _OVERRIDE;
190
191 private:
192 virtual bool encodePKM(SkWStream* stream, const SkData *data);
193 typedef SkImageEncoder INHERITED;
194 };
195
196 bool SkKTXImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) {
197 SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData());
198
199 // Is this even encoded data?
200 if (NULL != data) {
201 const uint8_t *bytes = data->bytes();
202 if (etc1_pkm_is_valid(bytes)) {
203 return this->encodePKM(stream, data);
204 }
205
206 // Is it a KTX file??
207 if (SkKTXFile::is_ktx(bytes)) {
208 return stream->write(bytes, data->size());
209 }
210
211 // If it's neither a KTX nor a PKM, then we need to
212 // get at the actual pixels, so fall through and decompress...
213 }
214
215 return SkKTXFile::WriteBitmapToKTX(stream, bitmap);
216 }
217
218 bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) {
219 const uint8_t* bytes = data->bytes();
220 SkASSERT(etc1_pkm_is_valid(bytes));
221
222 etc1_uint32 width = etc1_pkm_get_width(bytes);
223 etc1_uint32 height = etc1_pkm_get_height(bytes);
224
225 // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure
226 // that our dimensions are valid.
227 if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) {
228 return false;
229 }
230
231 // Advance pointer to etc1 data.
232 bytes += ETC_PKM_HEADER_SIZE;
233
234 return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height);
235 }
236
159 //////////////////////////////////////////////////////////////////////////////// ///////// 237 //////////////////////////////////////////////////////////////////////////////// /////////
160 DEFINE_DECODER_CREATOR(KTXImageDecoder); 238 DEFINE_DECODER_CREATOR(KTXImageDecoder);
239 DEFINE_ENCODER_CREATOR(KTXImageEncoder);
161 //////////////////////////////////////////////////////////////////////////////// ///////// 240 //////////////////////////////////////////////////////////////////////////////// /////////
162 241
163 static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) { 242 static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) {
164 if (SkKTXFile::is_ktx(stream)) { 243 if (SkKTXFile::is_ktx(stream)) {
165 return SkNEW(SkKTXImageDecoder); 244 return SkNEW(SkKTXImageDecoder);
166 } 245 }
167 return NULL; 246 return NULL;
168 } 247 }
169 248
170 static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory);
171
172 static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) { 249 static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) {
173 if (SkKTXFile::is_ktx(stream)) { 250 if (SkKTXFile::is_ktx(stream)) {
174 return SkImageDecoder::kKTX_Format; 251 return SkImageDecoder::kKTX_Format;
175 } 252 }
176 return SkImageDecoder::kUnknown_Format; 253 return SkImageDecoder::kUnknown_Format;
177 } 254 }
178 255
256 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) {
257 return (SkImageEncoder::kKTX_Type == t) ? SkNEW(SkKTXImageEncoder) : NULL;
258 }
259
260 static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory);
179 static SkImageDecoder_FormatReg gFormatReg(get_format_ktx); 261 static SkImageDecoder_FormatReg gFormatReg(get_format_ktx);
262 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory);
OLDNEW
« no previous file with comments | « include/core/SkImageEncoder.h ('k') | tests/KtxTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698