OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2014 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 "SkColorPriv.h" | |
9 #include "SkImageEncoder.h" | |
10 #include "SkImageGenerator.h" | |
11 #include "SkPixelRef.h" | |
12 #include "SkStream.h" | |
13 #include "SkStreamPriv.h" | |
14 #include "SkTypes.h" | |
15 | |
16 #include "ktx.h" | |
17 #include "etc1.h" | |
18 | |
19 /////////////////////////////////////////////////////////////////////////////// | |
20 | |
21 // KTX Image Encoder | |
22 // | |
23 // 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 | |
25 // texture in an OpenGL application, including the use of compressed data. | |
26 // | |
27 // 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 | |
29 // 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, | |
31 // 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 | |
33 // be represented as a full resolution 8-bit image dump with the appropriate | |
34 // OpenGL defines in the header). | |
35 | |
36 class SkKTXImageEncoder : public SkImageEncoder { | |
37 protected: | |
38 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; | |
39 | |
40 private: | |
41 virtual bool encodePKM(SkWStream* stream, const SkData *data); | |
42 typedef SkImageEncoder INHERITED; | |
43 }; | |
44 | |
45 bool SkKTXImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int)
{ | |
46 if (!bitmap.pixelRef()) { | |
47 return false; | |
48 } | |
49 SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData()); | |
50 | |
51 // Is this even encoded data? | |
52 if (data) { | |
53 const uint8_t *bytes = data->bytes(); | |
54 if (etc1_pkm_is_valid(bytes)) { | |
55 return this->encodePKM(stream, data); | |
56 } | |
57 | |
58 // Is it a KTX file?? | |
59 if (SkKTXFile::is_ktx(bytes)) { | |
60 return stream->write(bytes, data->size()); | |
61 } | |
62 | |
63 // If it's neither a KTX nor a PKM, then we need to | |
64 // get at the actual pixels, so fall through and decompress... | |
65 } | |
66 | |
67 return SkKTXFile::WriteBitmapToKTX(stream, bitmap); | |
68 } | |
69 | |
70 bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) { | |
71 const uint8_t* bytes = data->bytes(); | |
72 SkASSERT(etc1_pkm_is_valid(bytes)); | |
73 | |
74 etc1_uint32 width = etc1_pkm_get_width(bytes); | |
75 etc1_uint32 height = etc1_pkm_get_height(bytes); | |
76 | |
77 // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure | |
78 // that our dimensions are valid. | |
79 if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) { | |
80 return false; | |
81 } | |
82 | |
83 // Advance pointer to etc1 data. | |
84 bytes += ETC_PKM_HEADER_SIZE; | |
85 | |
86 return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height); | |
87 } | |
88 | |
89 ////////////////////////////////////////////////////////////////////////////////
///////// | |
90 DEFINE_ENCODER_CREATOR(KTXImageEncoder); | |
91 ////////////////////////////////////////////////////////////////////////////////
///////// | |
92 | |
93 SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) { | |
94 return (SkImageEncoder::kKTX_Type == t) ? new SkKTXImageEncoder : nullptr; | |
95 } | |
96 | |
97 static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory); | |
OLD | NEW |