Home | History | Annotate | Download | only in GLcommon
      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