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 {
ColorColor23 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
getPaletteInfo(GLenum internalFormat,unsigned int & indexSizeBits,unsigned int & colorSizeBytes,GLenum & colorFrmt)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
paletteColor(const unsigned char * pallete,unsigned int index,GLenum format)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
uncompressTexture(GLenum internalformat,GLenum & formatOut,GLsizei width,GLsizei height,GLsizei imageSize,const GLvoid * data,GLint level)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