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

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

Issue 1830723002: Revert of Delete SkImageDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fix-animator
Patch Set: Created 4 years, 9 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 | « src/images/SkImageDecoder_astc.cpp ('k') | src/images/SkImageDecoder_libbmp.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 "SkImageEncoder.h" 9 #include "SkImageDecoder.h"
10 #include "SkImageGenerator.h" 10 #include "SkImageGenerator.h"
11 #include "SkPixelRef.h" 11 #include "SkPixelRef.h"
12 #include "SkScaledBitmapSampler.h"
12 #include "SkStream.h" 13 #include "SkStream.h"
13 #include "SkStreamPriv.h" 14 #include "SkStreamPriv.h"
14 #include "SkTypes.h" 15 #include "SkTypes.h"
15 16
16 #include "ktx.h" 17 #include "ktx.h"
17 #include "etc1.h" 18 #include "etc1.h"
18 19
19 /////////////////////////////////////////////////////////////////////////////// 20 //////////////////////////////////////////////////////////////////////////////// /////////
20 21
21 // KTX Image Encoder 22
22 // 23 //////////////////////////////////////////////////////////////////////////////// /////////
24
25 // KTX Image decoder
26 // ---
23 // KTX is a general texture data storage file format ratified by the Khronos Gro up. As an 27 // KTX is a general texture data storage file format ratified by the Khronos Gro up. As an
24 // overview, a KTX file contains all of the appropriate values needed to fully s pecify a 28 // overview, a KTX file contains all of the appropriate values needed to fully s pecify a
25 // texture in an OpenGL application, including the use of compressed data. 29 // texture in an OpenGL application, including the use of compressed data.
26 // 30 //
31 // This decoder is meant to be used with an SkDiscardablePixelRef so that GPU ba ckends
32 // can sniff the data before creating a texture. If they encounter a compressed format
33 // that they understand, they can then upload the data directly to the GPU. Othe rwise,
34 // they will decode the data into a format that Skia supports.
35
36 class SkKTXImageDecoder : public SkImageDecoder {
37 public:
38 SkKTXImageDecoder() { }
39
40 Format getFormat() const override {
41 return kKTX_Format;
42 }
43
44 protected:
45 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) override;
46
47 private:
48 typedef SkImageDecoder INHERITED;
49 };
50
51 SkImageDecoder::Result SkKTXImageDecoder::onDecode(SkStream* stream, SkBitmap* b m, Mode mode) {
52 // TODO: Implement SkStream::copyToData() that's cheap for memory and file s treams
53 auto data = SkCopyStreamToData(stream);
54 if (nullptr == data) {
55 return kFailure;
56 }
57
58 SkKTXFile ktxFile(data.get());
59 if (!ktxFile.valid()) {
60 return kFailure;
61 }
62
63 const unsigned short width = ktxFile.width();
64 const unsigned short height = ktxFile.height();
65
66 // Set a flag if our source is premultiplied alpha
67 const SkString premulKey("KTXPremultipliedAlpha");
68 const bool bSrcIsPremul = ktxFile.getValueForKey(premulKey) == SkString("Tru e");
69
70 // Setup the sampler...
71 SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
72
73 // Determine the alpha of the bitmap...
74 SkAlphaType alphaType = kOpaque_SkAlphaType;
75 if (ktxFile.isRGBA8()) {
76 if (this->getRequireUnpremultipliedColors()) {
77 alphaType = kUnpremul_SkAlphaType;
78 // If the client wants unpremul colors and we only have
79 // premul, then we cannot honor their wish.
80 if (bSrcIsPremul) {
81 return kFailure;
82 }
83 } else {
84 alphaType = kPremul_SkAlphaType;
85 }
86 }
87
88 // Search through the compressed formats to see if the KTX file is holding
89 // compressed data
90 bool ktxIsCompressed = false;
91 SkTextureCompressor::Format ktxCompressedFormat;
92 for (int i = 0; i < SkTextureCompressor::kFormatCnt; ++i) {
93 SkTextureCompressor::Format fmt = static_cast<SkTextureCompressor::Forma t>(i);
94 if (ktxFile.isCompressedFormat(fmt)) {
95 ktxIsCompressed = true;
96 ktxCompressedFormat = fmt;
97 break;
98 }
99 }
100
101 // If the compressed format is a grayscale image, then setup the bitmap prop erly...
102 bool isCompressedAlpha = ktxIsCompressed &&
103 ((SkTextureCompressor::kLATC_Format == ktxCompressedFormat) ||
104 (SkTextureCompressor::kR11_EAC_Format == ktxCompressedFormat));
105
106 // Set the image dimensions and underlying pixel type.
107 if (isCompressedAlpha) {
108 const int w = sampler.scaledWidth();
109 const int h = sampler.scaledHeight();
110 bm->setInfo(SkImageInfo::MakeA8(w, h));
111 } else {
112 const int w = sampler.scaledWidth();
113 const int h = sampler.scaledHeight();
114 bm->setInfo(SkImageInfo::MakeN32(w, h, alphaType));
115 }
116
117 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
118 return kSuccess;
119 }
120
121 // If we've made it this far, then we know how to grok the data.
122 if (!this->allocPixelRef(bm, nullptr)) {
123 return kFailure;
124 }
125
126 // Lock the pixels, since we're about to write to them...
127 SkAutoLockPixels alp(*bm);
128
129 if (isCompressedAlpha) {
130 if (!sampler.begin(bm, SkScaledBitmapSampler::kGray, *this)) {
131 return kFailure;
132 }
133
134 // Alpha data is only a single byte per pixel.
135 int nPixels = width * height;
136 SkAutoMalloc outRGBData(nPixels);
137 uint8_t *outRGBDataPtr = reinterpret_cast<uint8_t *>(outRGBData.get());
138
139 // Decode the compressed format
140 const uint8_t *buf = reinterpret_cast<const uint8_t *>(ktxFile.pixelData ());
141 if (!SkTextureCompressor::DecompressBufferFromFormat(
142 outRGBDataPtr, width, buf, width, height, ktxCompressedFormat)) {
143 return kFailure;
144 }
145
146 // Set each of the pixels...
147 const int srcRowBytes = width;
148 const int dstHeight = sampler.scaledHeight();
149 const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr);
150 srcRow += sampler.srcY0() * srcRowBytes;
151 for (int y = 0; y < dstHeight; ++y) {
152 sampler.next(srcRow);
153 srcRow += sampler.srcDY() * srcRowBytes;
154 }
155
156 return kSuccess;
157
158 } else if (ktxFile.isCompressedFormat(SkTextureCompressor::kETC1_Format)) {
159 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
160 return kFailure;
161 }
162
163 // ETC1 Data is encoded as RGB pixels, so we should extract it as such
164 int nPixels = width * height;
165 SkAutoMalloc outRGBData(nPixels * 3);
166 uint8_t *outRGBDataPtr = reinterpret_cast<uint8_t *>(outRGBData.get());
167
168 // Decode ETC1
169 const uint8_t *buf = reinterpret_cast<const uint8_t *>(ktxFile.pixelData ());
170 if (!SkTextureCompressor::DecompressBufferFromFormat(
171 outRGBDataPtr, width*3, buf, width, height, SkTextureCompressor: :kETC1_Format)) {
172 return kFailure;
173 }
174
175 // Set each of the pixels...
176 const int srcRowBytes = width * 3;
177 const int dstHeight = sampler.scaledHeight();
178 const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr);
179 srcRow += sampler.srcY0() * srcRowBytes;
180 for (int y = 0; y < dstHeight; ++y) {
181 sampler.next(srcRow);
182 srcRow += sampler.srcDY() * srcRowBytes;
183 }
184
185 return kSuccess;
186
187 } else if (ktxFile.isRGB8()) {
188
189 // Uncompressed RGB data (without alpha)
190 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
191 return kFailure;
192 }
193
194 // Just need to read RGB pixels
195 const int srcRowBytes = width * 3;
196 const int dstHeight = sampler.scaledHeight();
197 const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelD ata());
198 srcRow += sampler.srcY0() * srcRowBytes;
199 for (int y = 0; y < dstHeight; ++y) {
200 sampler.next(srcRow);
201 srcRow += sampler.srcDY() * srcRowBytes;
202 }
203
204 return kSuccess;
205
206 } else if (ktxFile.isRGBA8()) {
207
208 // Uncompressed RGBA data
209
210 // If we know that the image contains premultiplied alpha, then
211 // we need to turn off the premultiplier
212 SkScaledBitmapSampler::Options opts (*this);
213 if (bSrcIsPremul) {
214 SkASSERT(bm->alphaType() == kPremul_SkAlphaType);
215 SkASSERT(!this->getRequireUnpremultipliedColors());
216
217 opts.fPremultiplyAlpha = false;
218 }
219
220 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, opts)) {
221 return kFailure;
222 }
223
224 // Just need to read RGBA pixels
225 const int srcRowBytes = width * 4;
226 const int dstHeight = sampler.scaledHeight();
227 const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelD ata());
228 srcRow += sampler.srcY0() * srcRowBytes;
229 for (int y = 0; y < dstHeight; ++y) {
230 sampler.next(srcRow);
231 srcRow += sampler.srcDY() * srcRowBytes;
232 }
233
234 return kSuccess;
235 }
236
237 return kFailure;
238 }
239
240 ///////////////////////////////////////////////////////////////////////////////
241
242 // KTX Image Encoder
243 //
27 // This encoder takes a best guess at how to encode the bitmap passed to it. If 244 // This encoder takes a best guess at how to encode the bitmap passed to it. If
28 // there is an installed discardable pixel ref with existing PKM data, then we 245 // there is an installed discardable pixel ref with existing PKM data, then we
29 // will repurpose the existing ETC1 data into a KTX file. If the data contains 246 // will repurpose the existing ETC1 data into a KTX file. If the data contains
30 // KTX data, then we simply return a copy of the same data. For all other files, 247 // KTX data, then we simply return a copy of the same data. For all other files,
31 // the underlying KTX library tries to do its best to encode the appropriate 248 // the underlying KTX library tries to do its best to encode the appropriate
32 // data specified by the bitmap based on the config. (i.e. kAlpha8_Config will 249 // data specified by the bitmap based on the config. (i.e. kAlpha8_Config will
33 // be represented as a full resolution 8-bit image dump with the appropriate 250 // be represented as a full resolution 8-bit image dump with the appropriate
34 // OpenGL defines in the header). 251 // OpenGL defines in the header).
35 252
36 class SkKTXImageEncoder : public SkImageEncoder { 253 class SkKTXImageEncoder : public SkImageEncoder {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 return false; 297 return false;
81 } 298 }
82 299
83 // Advance pointer to etc1 data. 300 // Advance pointer to etc1 data.
84 bytes += ETC_PKM_HEADER_SIZE; 301 bytes += ETC_PKM_HEADER_SIZE;
85 302
86 return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height); 303 return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height);
87 } 304 }
88 305
89 //////////////////////////////////////////////////////////////////////////////// ///////// 306 //////////////////////////////////////////////////////////////////////////////// /////////
307 DEFINE_DECODER_CREATOR(KTXImageDecoder);
90 DEFINE_ENCODER_CREATOR(KTXImageEncoder); 308 DEFINE_ENCODER_CREATOR(KTXImageEncoder);
91 //////////////////////////////////////////////////////////////////////////////// ///////// 309 //////////////////////////////////////////////////////////////////////////////// /////////
92 310
311 static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) {
312 if (SkKTXFile::is_ktx(stream)) {
313 return new SkKTXImageDecoder;
314 }
315 return nullptr;
316 }
317
318 static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) {
319 if (SkKTXFile::is_ktx(stream)) {
320 return SkImageDecoder::kKTX_Format;
321 }
322 return SkImageDecoder::kUnknown_Format;
323 }
324
93 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) { 325 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) {
94 return (SkImageEncoder::kKTX_Type == t) ? new SkKTXImageEncoder : nullptr; 326 return (SkImageEncoder::kKTX_Type == t) ? new SkKTXImageEncoder : nullptr;
95 } 327 }
96 328
329 static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory);
330 static SkImageDecoder_FormatReg gFormatReg(get_format_ktx);
97 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory); 331 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory);
OLDNEW
« no previous file with comments | « src/images/SkImageDecoder_astc.cpp ('k') | src/images/SkImageDecoder_libbmp.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698