// Modified by Henrik RydgÄrd: // // * Moved many I/O and similar functions to etctool.cpp, this file // should only concern itself with compression. // * got rid of readCompress.. // etcpack.cxx v1.06 // // NO WARRANTY // // BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO // REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER // EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE // PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME // THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON // MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR // IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR // OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE // RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS // NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS // AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES; // // IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY // GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF // THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO // LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY // YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY // OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED // OF THE POSSIBILITY OF SUCH DAMAGES. // // (C) Ericsson AB 2005. All Rights Reserved. // #include #include #include "etcpack.h" #include "etcdec.h" #define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x))) #define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1)) #define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1)) #define SQUARE(x) ((x)*(x)) #define JAS_ROUND(x) (((x) < 0.0 ) ? ((int)((x)-0.5)) : ((int)((x)+0.5))) #define RED(img,width,x,y) img[3*(y*width+x)+0] #define GREEN(img,width,x,y) img[3*(y*width+x)+1] #define BLUE(img,width,x,y) img[3*(y*width+x)+2] // SLOW SCAN RANGE IS -5 to 5 in all three colors #define SLOW_SCAN_MIN (-5) #define SLOW_SCAN_MAX (5) #define SLOW_SCAN_RANGE ((SLOW_SCAN_MAX-(SLOW_SCAN_MIN)+1)) #define SLOW_SCAN_OFFSET (-(SLOW_SCAN_MIN)) // We need this to guarrantee that at least one try is valid #define SLOW_TRY_MIN (-4 - SLOW_SCAN_MAX) #define SLOW_TRY_MAX (3 - (SLOW_SCAN_MIN)) // MEDIUM SCAN RANGE IS -3 to 3in all three colors #define MEDIUM_SCAN_MIN (-3) #define MEDIUM_SCAN_MAX (3) #define MEDIUM_SCAN_RANGE ((MEDIUM_SCAN_MAX-(MEDIUM_SCAN_MIN)+1)) #define MEDIUM_SCAN_OFFSET (-(MEDIUM_SCAN_MIN)) // We need this to guarrantee that at least one try is valid #define MEDIUM_TRY_MIN (-4 - MEDIUM_SCAN_MAX) #define MEDIUM_TRY_MAX (3 - (MEDIUM_SCAN_MIN)) #define PUTBITS( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << ((startpos)-(size)+1) #define PUTBITSHIGH( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << (((startpos)-32)-(size)+1) int scramble[4] = {3, 2, 0, 1}; static const int compressParamsEnc[16][4] = { { -8, -2, 2, 8 }, { -8, -2, 2, 8 }, { -17, -5, 5, 17 }, { -17, -5, 5, 17 }, { -29, -9, 9, 29 }, { -29, -9, 9, 29 }, { -42, -13, 13, 42 }, { -42, -13, 13, 42 }, { -60, -18, 18, 60 }, { -60, -18, 18, 60 }, { -80, -24, 24, 80 }, { -80, -24, 24, 80 }, {-106, -33, 33,106 }, {-106, -33, 33,106 }, {-183, -47, 47,183 }, {-183, -47, 47,183 }, }; void computeAverageColor2x4noQuantFloat(uint8 *img,int width,int height,int startx,int starty,float *avg_color) { int r=0,g=0,b=0; for(int y=starty; y> 1), 1, i); PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); i++; // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} // so that first bit is sign bit and the other bit is size bit (4 or 12). // This means that we have to scramble the bits before storing them. sum_error+=min_error; } } *pixel_indices_MSBp = pixel_indices_MSB; *pixel_indices_LSBp = pixel_indices_LSB; return sum_error; } float compressBlockWithTable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) { uint8 orig[3],approx[3]; unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; float sum_error=0; int q, i; double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED; double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED; double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED; i = 0; for(int x=startx; x> 1), 1, i); PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); i++; // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} // so that first bit is sign bit and the other bit is size bit (4 or 12). // This means that we have to scramble the bits before storing them. sum_error+=min_error; } } *pixel_indices_MSBp = pixel_indices_MSB; *pixel_indices_LSBp = pixel_indices_LSB; return sum_error; } int compressBlockWithTable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) { uint8 orig[3],approx[3]; unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; int sum_error=0; int q; int i; i = 0; for(int x=startx; x> 1), 1, i); PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); i++; // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} // so that first bit is sign bit and the other bit is size bit (4 or 12). // This means that we have to scramble the bits before storing them. sum_error+=min_error; } i+=2; } *pixel_indices_MSBp = pixel_indices_MSB; *pixel_indices_LSBp = pixel_indices_LSB; return sum_error; } float compressBlockWithTable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) { uint8 orig[3],approx[3]; unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; float sum_error=0; int q; int i; float wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; float wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; float wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; i = 0; for(int x=startx; x> 1), 1, i); PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); i++; // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} // so that first bit is sign bit and the other bit is size bit (4 or 12). // This means that we have to scramble the bits before storing them. sum_error+=min_error; } i+=2; } *pixel_indices_MSBp = pixel_indices_MSB; *pixel_indices_LSBp = pixel_indices_LSB; return sum_error; } int tryalltables_3bittable2x4(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) { int min_error = 3*255*255*16; int q; int err; unsigned int pixel_indices_MSB, pixel_indices_LSB; for(q=0;q<16;q+=2) // try all the 8 tables. { err=compressBlockWithTable2x4(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); if(err> 1; } } return min_error; } int tryalltables_3bittable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) { float min_error = 3*255*255*16; int q; float err; unsigned int pixel_indices_MSB, pixel_indices_LSB; for(q=0;q<16;q+=2) // try all the 8 tables. { err=compressBlockWithTable2x4percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); if(err> 1; } } return (int) min_error; } int tryalltables_3bittable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) { int min_error = 3*255*255*16; int q; int err; unsigned int pixel_indices_MSB, pixel_indices_LSB; for(q=0;q<16;q+=2) // try all the 8 tables. { err=compressBlockWithTable4x2(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); if(err> 1; } } return min_error; } int tryalltables_3bittable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) { float min_error = 3*255*255*16; int q; float err; unsigned int pixel_indices_MSB, pixel_indices_LSB; for(q=0;q<16;q+=2) // try all the 8 tables. { err=compressBlockWithTable4x2percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); if(err> 1; } } return (int) min_error; } // The below code quantizes a float RGB value to RGB555. // void quantize444ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) { // Detta ar nummer tva float dr, dg, db; float kr, kg, kb; float wR2, wG2, wB2; uint8 low_color[3]; uint8 high_color[3]; float lowhightable[8]; int q; float kval = (float) (255.0/15.0); // These are the values that we want to have: float red_average, green_average, blue_average; int red_4bit_low, green_4bit_low, blue_4bit_low; int red_4bit_high, green_4bit_high, blue_4bit_high; // These are the values that we approximate with: int red_low, green_low, blue_low; int red_high, green_high, blue_high; red_average = avg_col_in[0]; green_average = avg_col_in[1]; blue_average = avg_col_in[2]; // Find the 5-bit reconstruction levels red_low, red_high // so that red_average is in interval [red_low, red_high]. // (The same with green and blue.) red_4bit_low = (int) (red_average/kval); green_4bit_low = (int) (green_average/kval); blue_4bit_low = (int) (blue_average/kval); red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); kr = (float)red_high - (float)red_low; kg = (float)green_high - (float)green_low; kb = (float)blue_high - (float)blue_low; // Note that dr, dg, and db are all negative. dr = red_low - red_average; dg = green_low - green_average; db = blue_low - blue_average; // Use straight (nonperceptive) weights. wR2 = (float) 1.0; wG2 = (float) 1.0; wB2 = (float) 1.0; lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); float min_value = lowhightable[0]; int min_index = 0; for(q = 1; q<8; q++) { if(lowhightable[q] < min_value) { min_value = lowhightable[q]; min_index = q; } } low_color[0] = red_4bit_low; low_color[1] = green_4bit_low; low_color[2] = blue_4bit_low; high_color[0] = red_4bit_high; high_color[1] = green_4bit_high; high_color[2] = blue_4bit_high; switch(min_index) { case 0: // Since the step size is always 17 in RGB444 format (15*17=255), // kr = kg = kb = 17, which means that case 0 and case 7 will // always have equal projected error. Choose the one that is // closer to the desired color. if(dr*dr + dg*dg + db*db > 3*8*8) { enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; } else { enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; } break; case 1: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 2: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 3: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 4: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 5: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 6: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; case 7: if(dr*dr + dg*dg + db*db > 3*8*8) { enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; } else { enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; } break; } // Expand 5-bit encoded color to 8-bit color avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); } // The below code quantizes a float RGB value to RGB555. // void quantize555ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) { float dr, dg, db; float kr, kg, kb; float wR2, wG2, wB2; uint8 low_color[3]; uint8 high_color[3]; float lowhightable[8]; int q; float kval = (float) (255.0/31.0); // These are the values that we want to have: float red_average, green_average, blue_average; int red_5bit_low, green_5bit_low, blue_5bit_low; int red_5bit_high, green_5bit_high, blue_5bit_high; // These are the values that we approximate with: int red_low, green_low, blue_low; int red_high, green_high, blue_high; red_average = avg_col_in[0]; green_average = avg_col_in[1]; blue_average = avg_col_in[2]; // Find the 5-bit reconstruction levels red_low, red_high // so that red_average is in interval [red_low, red_high]. // (The same with green and blue.) red_5bit_low = (int) (red_average/kval); green_5bit_low = (int) (green_average/kval); blue_5bit_low = (int) (blue_average/kval); red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); kr = (float)red_high - (float)red_low; kg = (float)green_high - (float)green_low; kb = (float)blue_high - (float)blue_low; // Note that dr, dg, and db are all negative. dr = red_low - red_average; dg = green_low - green_average; db = blue_low - blue_average; // Use straight (nonperceptive) weights. wR2 = (float) 1.0; wG2 = (float) 1.0; wB2 = (float) 1.0; lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); float min_value = lowhightable[0]; int min_index = 0; for(q = 1; q<8; q++) { if(lowhightable[q] < min_value) { min_value = lowhightable[q]; min_index = q; } } low_color[0] = red_5bit_low; low_color[1] = green_5bit_low; low_color[2] = blue_5bit_low; high_color[0] = red_5bit_high; high_color[1] = green_5bit_high; high_color[2] = blue_5bit_high; switch(min_index) { case 0: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 1: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 2: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 3: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 4: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 5: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 6: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; case 7: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; } // Expand 5-bit encoded color to 8-bit color avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); } // The below code quantizes a float RGB value to RGB444. // It is thus the same as the above function quantize444ColorCombined(), but it uses a // weighted error metric instead. // void quantize444ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) { float dr, dg, db; float kr, kg, kb; float wR2, wG2, wB2; uint8 low_color[3]; uint8 high_color[3]; float lowhightable[8]; int q; float kval = (float) (255.0/15.0); // These are the values that we want to have: float red_average, green_average, blue_average; int red_4bit_low, green_4bit_low, blue_4bit_low; int red_4bit_high, green_4bit_high, blue_4bit_high; // These are the values that we approximate with: int red_low, green_low, blue_low; int red_high, green_high, blue_high; red_average = avg_col_in[0]; green_average = avg_col_in[1]; blue_average = avg_col_in[2]; // Find the 5-bit reconstruction levels red_low, red_high // so that red_average is in interval [red_low, red_high]. // (The same with green and blue.) red_4bit_low = (int) (red_average/kval); green_4bit_low = (int) (green_average/kval); blue_4bit_low = (int) (blue_average/kval); red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); low_color[0] = red_4bit_low; low_color[1] = green_4bit_low; low_color[2] = blue_4bit_low; high_color[0] = red_4bit_high; high_color[1] = green_4bit_high; high_color[2] = blue_4bit_high; kr = (float)red_high - (float)red_low; kg = (float)green_high - (float)green_low; kb = (float)blue_high- (float)blue_low; // Note that dr, dg, and db are all negative. dr = red_low - red_average; dg = green_low - green_average; db = blue_low - blue_average; // Perceptual weights to use wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); float min_value = lowhightable[0]; int min_index = 0; for(q = 1; q<8; q++) { if(lowhightable[q] < min_value) { min_value = lowhightable[q]; min_index = q; } } switch(min_index) { case 0: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 1: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 2: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 3: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 4: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 5: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 6: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; case 7: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; } // Expand encoded color to eight bits avg_color[0] = (enc_color[0] << 4) | enc_color[0]; avg_color[1] = (enc_color[1] << 4) | enc_color[1]; avg_color[2] = (enc_color[2] << 4) | enc_color[2]; } // The below code quantizes a float RGB value to RGB555. // It is thus the same as the above function quantize555ColorCombined(), but it uses a // weighted error metric instead. // void quantize555ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) { float dr, dg, db; float kr, kg, kb; float wR2, wG2, wB2; uint8 low_color[3]; uint8 high_color[3]; float lowhightable[8]; int q; float kval = (float) (255.0/31.0); // These are the values that we want to have: float red_average, green_average, blue_average; int red_5bit_low, green_5bit_low, blue_5bit_low; int red_5bit_high, green_5bit_high, blue_5bit_high; // These are the values that we approximate with: int red_low, green_low, blue_low; int red_high, green_high, blue_high; red_average = avg_col_in[0]; green_average = avg_col_in[1]; blue_average = avg_col_in[2]; // Find the 5-bit reconstruction levels red_low, red_high // so that red_average is in interval [red_low, red_high]. // (The same with green and blue.) red_5bit_low = (int) (red_average/kval); green_5bit_low = (int) (green_average/kval); blue_5bit_low = (int) (blue_average/kval); red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); low_color[0] = red_5bit_low; low_color[1] = green_5bit_low; low_color[2] = blue_5bit_low; high_color[0] = red_5bit_high; high_color[1] = green_5bit_high; high_color[2] = blue_5bit_high; kr = (float)red_high - (float)red_low; kg = (float)green_high - (float)green_low; kb = (float)blue_high - (float)blue_low; // Note that dr, dg, and db are all negative. dr = red_low - red_average; dg = green_low - green_average; db = blue_low - blue_average; // Perceptual weights to use wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); float min_value = lowhightable[0]; int min_index = 0; for(q = 1; q<8; q++) { if(lowhightable[q] < min_value) { min_value = lowhightable[q]; min_index = q; } } switch(min_index) { case 0: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 1: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = low_color[2]; break; case 2: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 3: enc_color[0] = low_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 4: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = low_color[2]; break; case 5: enc_color[0] = high_color[0]; enc_color[1] = low_color[1]; enc_color[2] = high_color[2]; break; case 6: enc_color[0] = low_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; case 7: enc_color[0] = high_color[0]; enc_color[1] = high_color[1]; enc_color[2] = high_color[2]; break; } // Expand 5-bit encoded color to 8-bit color avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); } void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) { unsigned int compressed1_norm_diff, compressed2_norm_diff; unsigned int compressed1_norm_444, compressed2_norm_444; unsigned int compressed1_flip_diff, compressed2_flip_diff; unsigned int compressed1_flip_444, compressed2_flip_444; unsigned int best_err_norm_diff = 255*255*8*3; unsigned int best_err_norm_444 = 255*255*8*3; unsigned int best_err_flip_diff = 255*255*8*3; unsigned int best_err_flip_444 = 255*255*8*3; uint8 avg_color_quant1[3], avg_color_quant2[3]; float avg_color_float1[3],avg_color_float2[3]; int enc_color1[3], enc_color2[3], diff[3]; int enc_base1[3], enc_base2[3]; int enc_try1[3], enc_try2[3]; int err; unsigned int best_pixel_indices1_MSB=0; unsigned int best_pixel_indices1_LSB=0; unsigned int best_pixel_indices2_MSB=0; unsigned int best_pixel_indices2_LSB=0; unsigned int best_table1=0, best_table2=0; int diffbit; int norm_err=0; int flip_err=0; int minerr; int dr1, dg1, db1, dr2, dg2, db2; // First try normal blocks 2x4: computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; // left part of block for(dr1 = SLOW_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // left part of block err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // right part of block for(dr2 = SLOW_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // left part of block err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } best_err_norm_diff = minerr; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm_diff = 0; PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); // left part of block tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); compressed2_norm_diff = 0; PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); } // We should do this in any case... { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for left block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // left part of block err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; // upper part of block for(dr1 = SLOW_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // upper part of block err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // lower part of block for(dr2 = SLOW_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // lower part of block err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } flip_err = minerr; best_err_flip_diff = flip_err; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip_diff = 0; PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); // upper part of block tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for upper block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // upper part of block err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; // left part of block for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // left part of block err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // right part of block for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // left part of block err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } best_err_norm_diff = minerr; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm_diff = 0; PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); // left part of block tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); compressed2_norm_diff = 0; PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for left block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // left part of block err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; // upper part of block for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // upper part of block err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // lower part of block for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // lower part of block err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } flip_err = minerr; best_err_flip_diff = flip_err; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip_diff = 0; PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); // upper part of block tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for upper block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // upper part of block err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; // left part of block for(dr1 = SLOW_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // left part of block err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // right part of block for(dr2 = SLOW_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // left part of block err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } best_err_norm_diff = minerr; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm_diff = 0; PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); // left part of block tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); compressed2_norm_diff = 0; PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); } // We should do this in any case... { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for left block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // left part of block err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; // upper part of block for(dr1 = SLOW_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // upper part of block err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // lower part of block for(dr2 = SLOW_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // lower part of block err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } flip_err = minerr; best_err_flip_diff = flip_err; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip_diff = 0; PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); // upper part of block tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for upper block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // upper part of block err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; // left part of block for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // left part of block err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // right part of block for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // left part of block err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } best_err_norm_diff = minerr; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm_diff = 0; PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); // left part of block tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); compressed2_norm_diff = 0; PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for left block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // left part of block err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) { diffbit = 1; enc_base1[0] = enc_color1[0]; enc_base1[1] = enc_color1[1]; enc_base1[2] = enc_color1[2]; enc_base2[0] = enc_color2[0]; enc_base2[1] = enc_color2[1]; enc_base2[2] = enc_color2[2]; int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; // upper part of block for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); // upper part of block err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); } } } // lower part of block for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); // lower part of block err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); } } } // Now see what combinations are both low in error and possible to // encode differentially. minerr = 255*255*3*8*2; for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { // The diff is OK, calculate total error: err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; if(err < minerr) { minerr = err; enc_color1[0] = enc_try1[0]; enc_color1[1] = enc_try1[1]; enc_color1[2] = enc_try1[2]; enc_color2[0] = enc_try2[0]; enc_color2[1] = enc_try2[1]; enc_color2[2] = enc_try2[2]; } } } } } } } } flip_err = minerr; best_err_flip_diff = flip_err; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip_diff = 0; PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); // upper part of block tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. // Color for upper block int besterr = 255*255*3*8; int bestri = 0, bestgi = 0, bestbi = 0; int ri, gi, bi; for(ri = 0; ri<15; ri++) { for(gi = 0; gi<15; gi++) { for(bi = 0; bi<15; bi++) { enc_color1[0] = ri; enc_color1[1] = gi; enc_color1[2] = bi; avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; // upper part of block err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); if(err= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; norm_err = 0; // left part of block norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // Pack bits into the first word. // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // left part of block norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } // Now try flipped blocks 4x2: computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } // Now lets see which is the best table to use. Only 8 tables are possible. if(norm_err <= flip_err) { compressed1 = compressed1_norm | 0; compressed2 = compressed2_norm; } else { compressed1 = compressed1_flip | 1; compressed2 = compressed2_flip; } } void compressBlockDiffFlipCombined(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) { unsigned int compressed1_norm, compressed2_norm; unsigned int compressed1_flip, compressed2_flip; uint8 avg_color_quant1[3], avg_color_quant2[3]; float avg_color_float1[3],avg_color_float2[3]; int enc_color1[3], enc_color2[3], diff[3]; unsigned int best_table1=0, best_table2=0; int diffbit; int norm_err=0; int flip_err=0; // First try normal blocks 2x4: computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. float eps; uint8 dummy[3]; quantize555ColorCombined(avg_color_float1, enc_color1, dummy); quantize555ColorCombined(avg_color_float2, enc_color2, dummy); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; norm_err = 0; // left part of block norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; uint8 dummy[3]; quantize444ColorCombined(avg_color_float1, enc_color1, dummy); quantize444ColorCombined(avg_color_float2, enc_color2, dummy); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // Pack bits into the first word. // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // left part of block norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } // Now try flipped blocks 4x2: computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. quantize555ColorCombined(avg_color_float1, enc_color1, dummy); quantize555ColorCombined(avg_color_float2, enc_color2, dummy); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; uint8 dummy[3]; quantize444ColorCombined(avg_color_float1, enc_color1, dummy); quantize444ColorCombined(avg_color_float2, enc_color2, dummy); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } // Now lets see which is the best table to use. Only 8 tables are possible. if(norm_err <= flip_err) { compressed1 = compressed1_norm | 0; compressed2 = compressed2_norm; } else { compressed1 = compressed1_flip | 1; compressed2 = compressed2_flip; } } void compressBlockDiffFlipAveragePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) { unsigned int compressed1_norm, compressed2_norm; unsigned int compressed1_flip, compressed2_flip; uint8 avg_color_quant1[3], avg_color_quant2[3]; float avg_color_float1[3],avg_color_float2[3]; int enc_color1[3], enc_color2[3], diff[3]; unsigned int best_table1=0, best_table2=0; int diffbit; int norm_err=0; int flip_err=0; // First try normal blocks 2x4: computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. float eps; enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; norm_err = 0; // left part of block norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // Pack bits into the first word. // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // left part of block norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } // Now try flipped blocks 4x2: computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } // Now lets see which is the best table to use. Only 8 tables are possible. if(norm_err <= flip_err) { compressed1 = compressed1_norm | 0; compressed2 = compressed2_norm; } else { compressed1 = compressed1_flip | 1; compressed2 = compressed2_flip; } } void compressBlockDiffFlipCombinedPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) { unsigned int compressed1_norm, compressed2_norm; unsigned int compressed1_flip, compressed2_flip; uint8 avg_color_quant1[3], avg_color_quant2[3]; float avg_color_float1[3],avg_color_float2[3]; int enc_color1[3], enc_color2[3], diff[3]; unsigned int best_table1=0, best_table2=0; int diffbit; int norm_err=0; int flip_err=0; // First try normal blocks 2x4: computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. float eps; uint8 dummy[3]; quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. // ETC1_RGB8_OES: // // a) bit layout in bits 63 through 32 if diffbit = 0 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // b) bit layout in bits 63 through 32 if diffbit = 1 // // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // // c) bit layout in bits 31 through 0 (in both cases) // // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // -------------------------------------------------------------------------------------------------- // | most significant pixel index bits | least significant pixel index bits | // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | // -------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; norm_err = 0; // left part of block norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // Pack bits into the first word. // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- compressed1_norm = 0; PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // left part of block norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // right part of block norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); PUTBITSHIGH( compressed1_norm, 0, 1, 32); compressed2_norm = 0; PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); } // Now try flipped blocks 4x2: computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); // First test if avg_color1 is similar enough to avg_color2 so that // we can use differential coding of colors. quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) { diffbit = 1; // The difference to be coded: diff[0] = enc_color2[0]-enc_color1[0]; diff[1] = enc_color2[1]-enc_color1[1]; diff[2] = enc_color2[2]-enc_color1[2]; avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } else { diffbit = 0; // The difference is bigger than what fits in 555 plus delta-333, so we will have // to deal with 444 444. eps = (float) 0.0001; quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 // --------------------------------------------------------------------------------------------------- // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | // --------------------------------------------------------------------------------------------------- // Pack bits into the first word. compressed1_flip = 0; PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); unsigned int best_pixel_indices1_MSB; unsigned int best_pixel_indices1_LSB; unsigned int best_pixel_indices2_MSB; unsigned int best_pixel_indices2_LSB; // upper part of block flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); // lower part of block flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); PUTBITSHIGH( compressed1_flip, 1, 1, 32); best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); } // Now lets see which is the best table to use. Only 8 tables are possible. if(norm_err <= flip_err) { compressed1 = compressed1_norm | 0; compressed2 = compressed2_norm; } else { compressed1 = compressed1_flip | 1; compressed2 = compressed2_flip; } } double calcBlockErrorRGB(uint8 *img, uint8 *imgdec, int width, int height, int startx, int starty) { int xx,yy; double err; err = 0; for(xx = startx; xx< startx+4; xx++) { for(yy = starty; yy> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24); } void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality) { uint8 rgb[4 * 4 * 3]; for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { rgb[(y * 4 + x) * 3 + 0] = in[(y * in_width + x) * 4 + 0]; rgb[(y * 4 + x) * 3 + 1] = in[(y * in_width + x) * 4 + 1]; rgb[(y * 4 + x) * 3 + 2] = in[(y * in_width + x) * 4 + 2]; } } uint8 imgdec[4 * 4 * 3]={0}; // temporary storage used by some of the functions. unsigned int compressed1 = 0, compressed2 = 0; switch (quality) { case 0: compressBlockDiffFlipFast(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); break; case 1: compressBlockDiffFlipFastPerceptual(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); break; case 2: compressBlockDiffFlipMedium(rgb, 4, 4, 0, 0, compressed1, compressed2); break; case 3: compressBlockDiffFlipMediumPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); break; case 4: compressBlockDiffFlipSlow(rgb, 4, 4, 0, 0, compressed1, compressed2); break; case 5: compressBlockDiffFlipSlowPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); break; default: fprintf(stderr, "ETC1: Compression level %i not defined", quality); return; } compressed1 = bswap(compressed1); compressed2 = bswap(compressed2); memcpy(output, &compressed1, 4); memcpy(output + 4, &compressed2, 4); memset(rgb, 0, 4 * 4 * 3); }