Chromium Code Reviews| 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 |