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 "SkEndian.h" 9 #include "SkColorPriv.h" 10 #include "SkImageDecoder.h" 11 #include "SkScaledBitmapSampler.h" 12 #include "SkStream.h" 13 #include "SkStreamPriv.h" 14 #include "SkTypes.h" 15 16 #include "SkTextureCompressor.h" 17 18 class SkASTCImageDecoder : public SkImageDecoder { 19 public: 20 SkASTCImageDecoder() { } 21 22 virtual Format getFormat() const SK_OVERRIDE { 23 return kASTC_Format; 24 } 25 26 protected: 27 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; 28 29 private: 30 typedef SkImageDecoder INHERITED; 31 }; 32 33 ///////////////////////////////////////////////////////////////////////////////////////// 34 35 static const uint32_t kASTCMagicNumber = 0x5CA1AB13; 36 37 static inline int read_24bit(const uint8_t* buf) { 38 // Assume everything is little endian... 39 return 40 static_cast<int>(buf[0]) | 41 (static_cast<int>(buf[1]) << 8) | 42 (static_cast<int>(buf[2]) << 16); 43 } 44 45 bool SkASTCImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { 46 SkAutoMalloc autoMal; 47 const size_t length = SkCopyStreamToStorage(&autoMal, stream); 48 if (0 == length) { 49 return false; 50 } 51 52 unsigned char* buf = (unsigned char*)autoMal.get(); 53 54 // Make sure that the magic header is there... 55 SkASSERT(SkEndian_SwapLE32(*(reinterpret_cast<uint32_t*>(buf))) == kASTCMagicNumber); 56 57 // Advance past the magic header 58 buf += 4; 59 60 const int blockDimX = buf[0]; 61 const int blockDimY = buf[1]; 62 const int blockDimZ = buf[2]; 63 64 if (1 != blockDimZ) { 65 // We don't support decoding 3D 66 return false; 67 } 68 69 // Choose the proper ASTC format 70 SkTextureCompressor::Format astcFormat; 71 if (4 == blockDimX && 4 == blockDimY) { 72 astcFormat = SkTextureCompressor::kASTC_4x4_Format; 73 } else if (5 == blockDimX && 4 == blockDimY) { 74 astcFormat = SkTextureCompressor::kASTC_5x4_Format; 75 } else if (5 == blockDimX && 5 == blockDimY) { 76 astcFormat = SkTextureCompressor::kASTC_5x5_Format; 77 } else if (6 == blockDimX && 5 == blockDimY) { 78 astcFormat = SkTextureCompressor::kASTC_6x5_Format; 79 } else if (6 == blockDimX && 6 == blockDimY) { 80 astcFormat = SkTextureCompressor::kASTC_6x6_Format; 81 } else if (8 == blockDimX && 5 == blockDimY) { 82 astcFormat = SkTextureCompressor::kASTC_8x5_Format; 83 } else if (8 == blockDimX && 6 == blockDimY) { 84 astcFormat = SkTextureCompressor::kASTC_8x6_Format; 85 } else if (8 == blockDimX && 8 == blockDimY) { 86 astcFormat = SkTextureCompressor::kASTC_8x8_Format; 87 } else if (10 == blockDimX && 5 == blockDimY) { 88 astcFormat = SkTextureCompressor::kASTC_10x5_Format; 89 } else if (10 == blockDimX && 6 == blockDimY) { 90 astcFormat = SkTextureCompressor::kASTC_10x6_Format; 91 } else if (10 == blockDimX && 8 == blockDimY) { 92 astcFormat = SkTextureCompressor::kASTC_10x8_Format; 93 } else if (10 == blockDimX && 10 == blockDimY) { 94 astcFormat = SkTextureCompressor::kASTC_10x10_Format; 95 } else if (12 == blockDimX && 10 == blockDimY) { 96 astcFormat = SkTextureCompressor::kASTC_12x10_Format; 97 } else if (12 == blockDimX && 12 == blockDimY) { 98 astcFormat = SkTextureCompressor::kASTC_12x12_Format; 99 } else { 100 // We don't support any other block dimensions.. 101 return false; 102 } 103 104 // Advance buf past the block dimensions 105 buf += 3; 106 107 // Read the width/height/depth from the buffer... 108 const int width = read_24bit(buf); 109 const int height = read_24bit(buf + 3); 110 const int depth = read_24bit(buf + 6); 111 112 if (1 != depth) { 113 // We don't support decoding 3D. 114 return false; 115 } 116 117 // Advance the buffer past the image dimensions 118 buf += 9; 119 120 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 121 // should we allow the Chooser (if present) to pick a config for us??? 122 if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) { 123 return false; 124 } 125 #endif 126 127 // Setup the sampler... 128 SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); 129 130 // Determine the alpha of the bitmap... 131 SkAlphaType alphaType = kOpaque_SkAlphaType; 132 if (this->getRequireUnpremultipliedColors()) { 133 alphaType = kUnpremul_SkAlphaType; 134 } else { 135 alphaType = kPremul_SkAlphaType; 136 } 137 138 // Set the config... 139 bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), alphaType)); 140 141 if (SkImageDecoder::kDecodeBounds_Mode == mode) { 142 return true; 143 } 144 145 if (!this->allocPixelRef(bm, NULL)) { 146 return false; 147 } 148 149 // Lock the pixels, since we're about to write to them... 150 SkAutoLockPixels alp(*bm); 151 152 if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, *this)) { 153 return false; 154 } 155 156 // ASTC Data is encoded as RGBA pixels, so we should extract it as such 157 int nPixels = width * height; 158 SkAutoMalloc outRGBAData(nPixels * 4); 159 uint8_t *outRGBADataPtr = reinterpret_cast<uint8_t *>(outRGBAData.get()); 160 161 // Decode ASTC 162 if (!SkTextureCompressor::DecompressBufferFromFormat( 163 outRGBADataPtr, width*4, buf, width, height, astcFormat)) { 164 } 165 166 // Set each of the pixels... 167 const int srcRowBytes = width * 4; 168 const int dstHeight = sampler.scaledHeight(); 169 const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBADataPtr); 170 srcRow += sampler.srcY0() * srcRowBytes; 171 for (int y = 0; y < dstHeight; ++y) { 172 sampler.next(srcRow); 173 srcRow += sampler.srcDY() * srcRowBytes; 174 } 175 176 return true; 177 } 178 179 ///////////////////////////////////////////////////////////////////////////////////////// 180 DEFINE_DECODER_CREATOR(ASTCImageDecoder); 181 ///////////////////////////////////////////////////////////////////////////////////////// 182 183 static bool is_astc(SkStreamRewindable* stream) { 184 // Read the ASTC header and make sure it's valid. 185 uint32_t magic; 186 if (stream->read((void*)&magic, 4) != 4) { 187 return false; 188 } 189 190 return kASTCMagicNumber == SkEndian_SwapLE32(magic); 191 } 192 193 static SkImageDecoder* sk_libastc_dfactory(SkStreamRewindable* stream) { 194 if (is_astc(stream)) { 195 return SkNEW(SkASTCImageDecoder); 196 } 197 return NULL; 198 } 199 200 static SkImageDecoder_DecodeReg gReg(sk_libastc_dfactory); 201 202 static SkImageDecoder::Format get_format_astc(SkStreamRewindable* stream) { 203 if (is_astc(stream)) { 204 return SkImageDecoder::kASTC_Format; 205 } 206 return SkImageDecoder::kUnknown_Format; 207 } 208 209 static SkImageDecoder_FormatReg gFormatReg(get_format_astc); 210