loadimage_paletted.cpp (4506B)
1 // 2 // Copyright 2022 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // loadimage_paletted.cpp: Decodes GL_PALETTE_* textures. 8 9 #include "image_util/loadimage.h" 10 11 #include <type_traits> 12 #include "common/mathutil.h" 13 14 #include "image_util/imageformats.h" 15 16 namespace angle 17 { 18 19 namespace 20 { 21 22 template <typename T> 23 R8G8B8A8 ReadColor(const T *src) 24 { 25 gl::ColorF tmp; 26 T::readColor(&tmp, src); 27 R8G8B8A8 rgba; 28 R8G8B8A8::writeColor(&rgba, &tmp); 29 return rgba; 30 } 31 32 size_t DecodeIndexIntoPalette(const uint8_t *row, size_t i, uint32_t indexBits) 33 { 34 switch (indexBits) 35 { 36 case 4: 37 { 38 // From OES_compressed_paletted_texture, section Additions to 39 // Chapter 3 of the OpenGL 1.3 Specification (Rasterization): 40 // 41 // Texel Data Formats for compressed paletted textures 42 // 43 // PALETTE4_xxx: 44 // 45 // 7 6 5 4 3 2 1 0 46 // --------------- 47 // | 1st | 2nd | 48 // | texel | texel | 49 // --------------- 50 51 bool even = i % 2 == 0; 52 return (row[i / 2] >> (even ? 4 : 0)) & 0x0f; 53 } 54 55 case 8: 56 return row[i]; 57 58 default: 59 UNREACHABLE(); 60 return 0; 61 } 62 } 63 64 R8G8B8A8 DecodeColor(const uint8_t *src, 65 uint32_t redBlueBits, 66 uint32_t greenBits, 67 uint32_t alphaBits) 68 { 69 switch (redBlueBits) 70 { 71 case 8: 72 ASSERT(greenBits == 8); 73 switch (alphaBits) 74 { 75 case 0: 76 return ReadColor<>(reinterpret_cast<const R8G8B8 *>(src)); 77 case 8: 78 return ReadColor<>(reinterpret_cast<const R8G8B8A8 *>(src)); 79 default: 80 UNREACHABLE(); 81 break; 82 } 83 break; 84 85 case 5: 86 switch (greenBits) 87 { 88 case 6: 89 ASSERT(alphaBits == 0); 90 return ReadColor<>(reinterpret_cast<const R5G6B5 *>(src)); 91 case 5: 92 ASSERT(alphaBits == 1); 93 return ReadColor<>(reinterpret_cast<const R5G5B5A1 *>(src)); 94 default: 95 UNREACHABLE(); 96 break; 97 } 98 break; 99 100 case 4: 101 ASSERT(greenBits == 4 && alphaBits == 4); 102 return ReadColor<>(reinterpret_cast<const R4G4B4A4 *>(src)); 103 104 default: 105 UNREACHABLE(); 106 break; 107 } 108 109 UNREACHABLE(); 110 return R8G8B8A8{0, 0, 0, 255}; 111 } 112 113 } // namespace 114 115 // See LoadPalettedToRGBA8. 116 void LoadPalettedToRGBA8Impl(size_t width, 117 size_t height, 118 size_t depth, 119 uint32_t indexBits, 120 uint32_t redBlueBits, 121 uint32_t greenBits, 122 uint32_t alphaBits, 123 const uint8_t *input, 124 size_t inputRowPitch, 125 size_t inputDepthPitch, 126 uint8_t *output, 127 size_t outputRowPitch, 128 size_t outputDepthPitch) 129 { 130 size_t colorBytes = (redBlueBits + greenBits + redBlueBits + alphaBits) / 8; 131 size_t paletteSize = 1 << indexBits; 132 size_t paletteBytes = paletteSize * colorBytes; 133 134 const uint8_t *palette = input; 135 136 const uint8_t *texels = input + paletteBytes; // + TODO(http://anglebug.com/7688): mip levels 137 138 for (size_t z = 0; z < depth; z++) 139 { 140 for (size_t y = 0; y < height; y++) 141 { 142 const uint8_t *srcRow = 143 priv::OffsetDataPointer<uint8_t>(texels, y, z, inputRowPitch, inputDepthPitch); 144 R8G8B8A8 *dstRow = 145 priv::OffsetDataPointer<R8G8B8A8>(output, y, z, outputRowPitch, outputDepthPitch); 146 147 for (size_t x = 0; x < width; x++) 148 { 149 size_t indexIntoPalette = DecodeIndexIntoPalette(srcRow, x, indexBits); 150 151 dstRow[x] = DecodeColor(palette + indexIntoPalette * colorBytes, redBlueBits, 152 greenBits, alphaBits); 153 } 154 } 155 } 156 } 157 158 } // namespace angle