1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "GLcommon/PaletteTexture.h" 17 #include <stdio.h> 18 19 20 21 struct Color 22 { 23 Color(unsigned char r, unsigned char g,unsigned char b, unsigned char a):red(r),green(g),blue(b),alpha(a){}; 24 unsigned char red; 25 unsigned char green; 26 unsigned char blue; 27 unsigned char alpha; 28 }; 29 30 void getPaletteInfo(GLenum internalFormat,unsigned int& indexSizeBits,unsigned int& colorSizeBytes,GLenum& colorFrmt) { 31 32 colorFrmt = GL_RGB; 33 switch(internalFormat) 34 { 35 case GL_PALETTE4_RGB8_OES: 36 indexSizeBits = 4; 37 colorSizeBytes = 3; 38 break; 39 40 case GL_PALETTE4_RGBA8_OES: 41 indexSizeBits = 4; 42 colorSizeBytes = 4; 43 colorFrmt = GL_RGBA; 44 break; 45 46 case GL_PALETTE4_RGBA4_OES: 47 case GL_PALETTE4_RGB5_A1_OES: 48 colorFrmt = GL_RGBA; 49 /* fall-through */ 50 case GL_PALETTE4_R5_G6_B5_OES: 51 indexSizeBits = 4; 52 colorSizeBytes = 2; 53 break; 54 55 case GL_PALETTE8_RGB8_OES: 56 indexSizeBits = 8; 57 colorSizeBytes = 3; 58 break; 59 60 case GL_PALETTE8_RGBA8_OES: 61 indexSizeBits = 8; 62 colorSizeBytes = 4; 63 colorFrmt = GL_RGBA; 64 break; 65 66 case GL_PALETTE8_RGBA4_OES: 67 case GL_PALETTE8_RGB5_A1_OES: 68 colorFrmt = GL_RGBA; 69 /* fall-through */ 70 case GL_PALETTE8_R5_G6_B5_OES: 71 indexSizeBits = 8; 72 colorSizeBytes = 2; 73 break; 74 } 75 } 76 77 78 Color paletteColor(const unsigned char* pallete,unsigned int index,GLenum format) 79 { 80 short s; 81 switch(format) { 82 //RGB 83 case GL_PALETTE4_RGB8_OES: 84 case GL_PALETTE8_RGB8_OES: 85 return Color(pallete[index],pallete[index+1],pallete[index+2],0); 86 case GL_PALETTE8_R5_G6_B5_OES: 87 case GL_PALETTE4_R5_G6_B5_OES: 88 s = *((short *)(pallete+index)); 89 return Color((s >> 11)*255/31,((s >> 5) & 0x3f)*255/63 ,(s & 0x1f)*255/31,0); 90 91 //RGBA 92 case GL_PALETTE4_RGBA8_OES: 93 case GL_PALETTE8_RGBA8_OES: 94 return Color(pallete[index],pallete[index+1],pallete[index+2],pallete[index+3]); 95 case GL_PALETTE4_RGBA4_OES: 96 case GL_PALETTE8_RGBA4_OES: 97 s = *((short *)(pallete+index)); 98 return Color(((s >> 12) & 0xf)*255/15,((s >> 8) & 0xf)*255/15,((s >> 4) & 0xf)*255/15 ,(s & 0xf)*255/15); 99 case GL_PALETTE4_RGB5_A1_OES: 100 case GL_PALETTE8_RGB5_A1_OES: 101 s = *((short *)(pallete+index)); 102 return Color(((s >> 11) & 0x1f)*255/31,((s >> 6) & 0x1f)*255/31,((s >> 1) & 0x1f)*255/31 ,(s & 0x1) * 255); 103 default: 104 return Color(255,255,255,255); 105 } 106 } 107 108 unsigned char* uncompressTexture(GLenum internalformat,GLenum& formatOut,GLsizei width,GLsizei height,GLsizei imageSize, const GLvoid* data,GLint level) { 109 110 unsigned int indexSizeBits; //the size of the color index in the pallete 111 unsigned int colorSizeBytes; //the size of each color cell in the pallete 112 113 getPaletteInfo(internalformat,indexSizeBits,colorSizeBytes,formatOut); 114 if(!data) 115 { 116 return NULL; 117 } 118 119 const unsigned char* palette = static_cast<const unsigned char *>(data); 120 121 //the pallete positioned in the begininng of the data 122 // so we jump over it to get to the colos indices in the palette 123 124 int nColors = 2 << (indexSizeBits -1); //2^indexSizeBits 125 int paletteSizeBytes = nColors*colorSizeBytes; 126 const unsigned char* imageIndices = palette + paletteSizeBytes; 127 128 //jumping to the the correct mipmap level 129 for(int i=0;i<level;i++) { 130 imageIndices+= (width*height*indexSizeBits)/8; 131 width = width >> 1; 132 height = height >> 1; 133 } 134 135 int colorSizeOut = (formatOut == GL_RGB? 3:4); 136 int nPixels = width*height; 137 unsigned char* pixelsOut = new unsigned char[nPixels*colorSizeOut]; 138 if(!pixelsOut) return NULL; 139 140 int leftBytes = ((palette + imageSize) /* the end of data pointer*/ 141 - imageIndices); 142 int leftPixels = (leftBytes * 8 )/indexSizeBits; 143 144 int maxIndices = (leftPixels < nPixels) ? leftPixels:nPixels; 145 146 //filling the pixels array 147 for(int i =0 ; i < maxIndices ; i++) { 148 int paletteIndex = 0; 149 int indexOut = i*colorSizeOut; 150 if(indexSizeBits == 4) { 151 paletteIndex = (i%2) == 0 ? 152 imageIndices[i/2] >> 4: //upper bits 153 imageIndices[i/2] & 0xf; //lower bits 154 } else { 155 paletteIndex = imageIndices[i]; 156 } 157 158 paletteIndex*=colorSizeBytes; 159 Color c = paletteColor(palette,paletteIndex,internalformat); 160 161 pixelsOut[indexOut] = c.red; 162 pixelsOut[indexOut+1] = c.green; 163 pixelsOut[indexOut+2] = c.blue; 164 if(formatOut == GL_RGBA) { 165 pixelsOut[indexOut+3] = c.alpha; 166 } 167 } 168 return pixelsOut; 169 } 170 171