xref: /aosp_15_r20/external/mesa3d/src/util/texcompress_rgtc_tmp.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2011 Red Hat Inc.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * block compression parts are:
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2004  Roland Scheidegger   All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
15*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
16*61046927SAndroid Build Coastguard Worker  * Software.
17*61046927SAndroid Build Coastguard Worker  *
18*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  * Author:
27*61046927SAndroid Build Coastguard Worker  *    Dave Airlie
28*61046927SAndroid Build Coastguard Worker  */
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker /* included by texcompress_rgtc to define byte/ubyte compressors */
31*61046927SAndroid Build Coastguard Worker 
TAG(fetch_texel_rgtc)32*61046927SAndroid Build Coastguard Worker void TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata,
33*61046927SAndroid Build Coastguard Worker 	                   unsigned i, unsigned j, TYPE *value, unsigned comps)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker    TYPE decode;
36*61046927SAndroid Build Coastguard Worker    const TYPE *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8 * comps);
37*61046927SAndroid Build Coastguard Worker    const TYPE alpha0 = blksrc[0];
38*61046927SAndroid Build Coastguard Worker    const TYPE alpha1 = blksrc[1];
39*61046927SAndroid Build Coastguard Worker    const char bit_pos = ((j&3) * 4 + (i&3)) * 3;
40*61046927SAndroid Build Coastguard Worker    const unsigned char acodelow = blksrc[2 + bit_pos / 8];
41*61046927SAndroid Build Coastguard Worker    const unsigned char acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0;
42*61046927SAndroid Build Coastguard Worker    const unsigned char code = (acodelow >> (bit_pos & 0x7) |
43*61046927SAndroid Build Coastguard Worker       (acodehigh  << (8 - (bit_pos & 0x7)))) & 0x7;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    if (code == 0)
46*61046927SAndroid Build Coastguard Worker       decode = alpha0;
47*61046927SAndroid Build Coastguard Worker    else if (code == 1)
48*61046927SAndroid Build Coastguard Worker       decode = alpha1;
49*61046927SAndroid Build Coastguard Worker    else if (alpha0 > alpha1)
50*61046927SAndroid Build Coastguard Worker       decode = ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7);
51*61046927SAndroid Build Coastguard Worker    else if (code < 6)
52*61046927SAndroid Build Coastguard Worker       decode = ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5);
53*61046927SAndroid Build Coastguard Worker    else if (code == 6)
54*61046927SAndroid Build Coastguard Worker       decode = T_MIN;
55*61046927SAndroid Build Coastguard Worker    else
56*61046927SAndroid Build Coastguard Worker       decode = T_MAX;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    *value = decode;
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker 
TAG(write_rgtc_encoded_channel)61*61046927SAndroid Build Coastguard Worker static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
62*61046927SAndroid Build Coastguard Worker                                             TYPE alphabase1,
63*61046927SAndroid Build Coastguard Worker                                             TYPE alphabase2,
64*61046927SAndroid Build Coastguard Worker                                             TYPE alphaenc[16])
65*61046927SAndroid Build Coastguard Worker {
66*61046927SAndroid Build Coastguard Worker    *blkaddr++ = alphabase1;
67*61046927SAndroid Build Coastguard Worker    *blkaddr++ = alphabase2;
68*61046927SAndroid Build Coastguard Worker    *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
69*61046927SAndroid Build Coastguard Worker    *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
70*61046927SAndroid Build Coastguard Worker    *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
71*61046927SAndroid Build Coastguard Worker    *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
72*61046927SAndroid Build Coastguard Worker    *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
73*61046927SAndroid Build Coastguard Worker    *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
74*61046927SAndroid Build Coastguard Worker }
75*61046927SAndroid Build Coastguard Worker 
TAG(encode_rgtc_ubyte)76*61046927SAndroid Build Coastguard Worker void TAG(encode_rgtc_ubyte)(TYPE *blkaddr, TYPE srccolors[4][4],
77*61046927SAndroid Build Coastguard Worker                             int numxpixels, int numypixels)
78*61046927SAndroid Build Coastguard Worker {
79*61046927SAndroid Build Coastguard Worker    TYPE alphabase[2], alphause[2];
80*61046927SAndroid Build Coastguard Worker    short alphatest[2] = { 0 };
81*61046927SAndroid Build Coastguard Worker    unsigned int alphablockerror1, alphablockerror2, alphablockerror3;
82*61046927SAndroid Build Coastguard Worker    TYPE i, j, aindex, acutValues[7];
83*61046927SAndroid Build Coastguard Worker    TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
84*61046927SAndroid Build Coastguard Worker    int alphaabsmin = 0, alphaabsmax = 0;
85*61046927SAndroid Build Coastguard Worker    short alphadist;
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
88*61046927SAndroid Build Coastguard Worker    alphabase[0] = T_MAX; alphabase[1] = T_MIN;
89*61046927SAndroid Build Coastguard Worker    for (j = 0; j < numypixels; j++) {
90*61046927SAndroid Build Coastguard Worker       for (i = 0; i < numxpixels; i++) {
91*61046927SAndroid Build Coastguard Worker 	 if (srccolors[j][i] == T_MIN)
92*61046927SAndroid Build Coastguard Worker             alphaabsmin = 1;
93*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] == T_MAX)
94*61046927SAndroid Build Coastguard Worker             alphaabsmax = 1;
95*61046927SAndroid Build Coastguard Worker          else {
96*61046927SAndroid Build Coastguard Worker             if (srccolors[j][i] > alphabase[1])
97*61046927SAndroid Build Coastguard Worker                alphabase[1] = srccolors[j][i];
98*61046927SAndroid Build Coastguard Worker             if (srccolors[j][i] < alphabase[0])
99*61046927SAndroid Build Coastguard Worker                alphabase[0] = srccolors[j][i];
100*61046927SAndroid Build Coastguard Worker          }
101*61046927SAndroid Build Coastguard Worker       }
102*61046927SAndroid Build Coastguard Worker    }
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker    if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
106*61046927SAndroid Build Coastguard Worker        || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */
107*61046927SAndroid Build Coastguard Worker       /* shortcut here since it is a very common case (and also avoids later problems) */
108*61046927SAndroid Build Coastguard Worker       /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker       *blkaddr++ = srccolors[0][0];
111*61046927SAndroid Build Coastguard Worker       blkaddr++;
112*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
113*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
114*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
115*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
116*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
117*61046927SAndroid Build Coastguard Worker       *blkaddr++ = 0;
118*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
119*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "enc0 used\n");
120*61046927SAndroid Build Coastguard Worker #endif
121*61046927SAndroid Build Coastguard Worker       return;
122*61046927SAndroid Build Coastguard Worker    }
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    /* find best encoding for alpha0 > alpha1 */
125*61046927SAndroid Build Coastguard Worker    /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
126*61046927SAndroid Build Coastguard Worker    alphablockerror1 = 0x0;
127*61046927SAndroid Build Coastguard Worker    alphablockerror2 = 0xffffffff;
128*61046927SAndroid Build Coastguard Worker    alphablockerror3 = 0xffffffff;
129*61046927SAndroid Build Coastguard Worker    if (alphaabsmin) alphause[0] = T_MIN;
130*61046927SAndroid Build Coastguard Worker    else alphause[0] = alphabase[0];
131*61046927SAndroid Build Coastguard Worker    if (alphaabsmax) alphause[1] = T_MAX;
132*61046927SAndroid Build Coastguard Worker    else alphause[1] = alphabase[1];
133*61046927SAndroid Build Coastguard Worker    /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
134*61046927SAndroid Build Coastguard Worker    for (aindex = 0; aindex < 7; aindex++) {
135*61046927SAndroid Build Coastguard Worker       /* don't forget here is always rounded down */
136*61046927SAndroid Build Coastguard Worker       acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
137*61046927SAndroid Build Coastguard Worker    }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    for (j = 0; j < numypixels; j++) {
140*61046927SAndroid Build Coastguard Worker       for (i = 0; i < numxpixels; i++) {
141*61046927SAndroid Build Coastguard Worker          /* maybe it's overkill to have the most complicated calculation just for the error
142*61046927SAndroid Build Coastguard Worker             calculation which we only need to figure out if encoding1 or encoding2 is better... */
143*61046927SAndroid Build Coastguard Worker          if (srccolors[j][i] > acutValues[0]) {
144*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 0;
145*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - alphause[1];
146*61046927SAndroid Build Coastguard Worker          }
147*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[1]) {
148*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 2;
149*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
150*61046927SAndroid Build Coastguard Worker          }
151*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[2]) {
152*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 3;
153*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
154*61046927SAndroid Build Coastguard Worker          }
155*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[3]) {
156*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 4;
157*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
158*61046927SAndroid Build Coastguard Worker          }
159*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[4]) {
160*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 5;
161*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
162*61046927SAndroid Build Coastguard Worker          }
163*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[5]) {
164*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 6;
165*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
166*61046927SAndroid Build Coastguard Worker          }
167*61046927SAndroid Build Coastguard Worker          else if (srccolors[j][i] > acutValues[6]) {
168*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 7;
169*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
170*61046927SAndroid Build Coastguard Worker          }
171*61046927SAndroid Build Coastguard Worker          else {
172*61046927SAndroid Build Coastguard Worker             alphaenc1[4*j + i] = 1;
173*61046927SAndroid Build Coastguard Worker             alphadist = srccolors[j][i] - alphause[0];
174*61046927SAndroid Build Coastguard Worker          }
175*61046927SAndroid Build Coastguard Worker          alphablockerror1 += alphadist * alphadist;
176*61046927SAndroid Build Coastguard Worker       }
177*61046927SAndroid Build Coastguard Worker    }
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
180*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 16; i++) {
181*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%d ", alphaenc1[i]);
182*61046927SAndroid Build Coastguard Worker    }
183*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "cutVals ");
184*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 7; i++) {
185*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%d ", acutValues[i]);
186*61046927SAndroid Build Coastguard Worker    }
187*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "srcVals ");
188*61046927SAndroid Build Coastguard Worker    for (j = 0; j < numypixels; j++) {
189*61046927SAndroid Build Coastguard Worker       for (i = 0; i < numxpixels; i++) {
190*61046927SAndroid Build Coastguard Worker 	 fprintf(stderr, "%d ", srccolors[j][i]);
191*61046927SAndroid Build Coastguard Worker       }
192*61046927SAndroid Build Coastguard Worker    }
193*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "\n");
194*61046927SAndroid Build Coastguard Worker #endif
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
197*61046927SAndroid Build Coastguard Worker       are false but try it anyway */
198*61046927SAndroid Build Coastguard Worker    if (alphablockerror1 >= 32) {
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker       /* don't bother if encoding is already very good, this condition should also imply
201*61046927SAndroid Build Coastguard Worker       we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
202*61046927SAndroid Build Coastguard Worker       alphablockerror2 = 0;
203*61046927SAndroid Build Coastguard Worker       for (aindex = 0; aindex < 5; aindex++) {
204*61046927SAndroid Build Coastguard Worker          /* don't forget here is always rounded down */
205*61046927SAndroid Build Coastguard Worker          acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
206*61046927SAndroid Build Coastguard Worker       }
207*61046927SAndroid Build Coastguard Worker       for (j = 0; j < numypixels; j++) {
208*61046927SAndroid Build Coastguard Worker          for (i = 0; i < numxpixels; i++) {
209*61046927SAndroid Build Coastguard Worker              /* maybe it's overkill to have the most complicated calculation just for the error
210*61046927SAndroid Build Coastguard Worker                calculation which we only need to figure out if encoding1 or encoding2 is better... */
211*61046927SAndroid Build Coastguard Worker             if (srccolors[j][i] == T_MIN) {
212*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 6;
213*61046927SAndroid Build Coastguard Worker                alphadist = 0;
214*61046927SAndroid Build Coastguard Worker             }
215*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] == T_MAX) {
216*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 7;
217*61046927SAndroid Build Coastguard Worker                alphadist = 0;
218*61046927SAndroid Build Coastguard Worker             }
219*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] <= acutValues[0]) {
220*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 0;
221*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - alphabase[0];
222*61046927SAndroid Build Coastguard Worker             }
223*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] <= acutValues[1]) {
224*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 2;
225*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
226*61046927SAndroid Build Coastguard Worker             }
227*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] <= acutValues[2]) {
228*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 3;
229*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
230*61046927SAndroid Build Coastguard Worker             }
231*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] <= acutValues[3]) {
232*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 4;
233*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
234*61046927SAndroid Build Coastguard Worker             }
235*61046927SAndroid Build Coastguard Worker             else if (srccolors[j][i] <= acutValues[4]) {
236*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 5;
237*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
238*61046927SAndroid Build Coastguard Worker             }
239*61046927SAndroid Build Coastguard Worker             else {
240*61046927SAndroid Build Coastguard Worker                alphaenc2[4*j + i] = 1;
241*61046927SAndroid Build Coastguard Worker                alphadist = srccolors[j][i] - alphabase[1];
242*61046927SAndroid Build Coastguard Worker             }
243*61046927SAndroid Build Coastguard Worker             alphablockerror2 += alphadist * alphadist;
244*61046927SAndroid Build Coastguard Worker          }
245*61046927SAndroid Build Coastguard Worker       }
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker       /* skip this if the error is already very small
249*61046927SAndroid Build Coastguard Worker          this encoding is MUCH better on average than #2 though, but expensive! */
250*61046927SAndroid Build Coastguard Worker       if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
251*61046927SAndroid Build Coastguard Worker          short blockerrlin1 = 0;
252*61046927SAndroid Build Coastguard Worker          short blockerrlin2 = 0;
253*61046927SAndroid Build Coastguard Worker          TYPE nralphainrangelow = 0;
254*61046927SAndroid Build Coastguard Worker          TYPE nralphainrangehigh = 0;
255*61046927SAndroid Build Coastguard Worker          alphatest[0] = T_MAX;
256*61046927SAndroid Build Coastguard Worker          alphatest[1] = T_MIN;
257*61046927SAndroid Build Coastguard Worker          /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
258*61046927SAndroid Build Coastguard Worker          for (j = 0; j < numypixels; j++) {
259*61046927SAndroid Build Coastguard Worker             for (i = 0; i < numxpixels; i++) {
260*61046927SAndroid Build Coastguard Worker                if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
261*61046927SAndroid Build Coastguard Worker                   alphatest[1] = srccolors[j][i];
262*61046927SAndroid Build Coastguard Worker                if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
263*61046927SAndroid Build Coastguard Worker                   alphatest[0] = srccolors[j][i];
264*61046927SAndroid Build Coastguard Worker             }
265*61046927SAndroid Build Coastguard Worker          }
266*61046927SAndroid Build Coastguard Worker           /* shouldn't happen too often, don't really care about those degenerated cases */
267*61046927SAndroid Build Coastguard Worker           if (alphatest[1] <= alphatest[0]) {
268*61046927SAndroid Build Coastguard Worker              alphatest[0] = T_MIN+1;
269*61046927SAndroid Build Coastguard Worker              alphatest[1] = T_MAX-1;
270*61046927SAndroid Build Coastguard Worker          }
271*61046927SAndroid Build Coastguard Worker          for (aindex = 0; aindex < 5; aindex++) {
272*61046927SAndroid Build Coastguard Worker          /* don't forget here is always rounded down */
273*61046927SAndroid Build Coastguard Worker             acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
274*61046927SAndroid Build Coastguard Worker          }
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker          /* find the "average" difference between the alpha values and the next encoded value.
277*61046927SAndroid Build Coastguard Worker             This is then used to calculate new base values.
278*61046927SAndroid Build Coastguard Worker             Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
279*61046927SAndroid Build Coastguard Worker             since they will see more improvement, and also because the values in the middle are somewhat
280*61046927SAndroid Build Coastguard Worker             likely to get no improvement at all (because the base values might move in different directions)?
281*61046927SAndroid Build Coastguard Worker             OTOH it would mean the values in the middle are even less likely to get an improvement
282*61046927SAndroid Build Coastguard Worker          */
283*61046927SAndroid Build Coastguard Worker          for (j = 0; j < numypixels; j++) {
284*61046927SAndroid Build Coastguard Worker             for (i = 0; i < numxpixels; i++) {
285*61046927SAndroid Build Coastguard Worker                if (srccolors[j][i] <= alphatest[0] / 2) {
286*61046927SAndroid Build Coastguard Worker                }
287*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
288*61046927SAndroid Build Coastguard Worker                }
289*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[0]) {
290*61046927SAndroid Build Coastguard Worker                   blockerrlin1 += (srccolors[j][i] - alphatest[0]);
291*61046927SAndroid Build Coastguard Worker                   nralphainrangelow += 1;
292*61046927SAndroid Build Coastguard Worker                }
293*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[1]) {
294*61046927SAndroid Build Coastguard Worker                   blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
295*61046927SAndroid Build Coastguard Worker                   blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
296*61046927SAndroid Build Coastguard Worker                   nralphainrangelow += 1;
297*61046927SAndroid Build Coastguard Worker                   nralphainrangehigh += 1;
298*61046927SAndroid Build Coastguard Worker                }
299*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[2]) {
300*61046927SAndroid Build Coastguard Worker                   blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
301*61046927SAndroid Build Coastguard Worker                   blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
302*61046927SAndroid Build Coastguard Worker                   nralphainrangelow += 1;
303*61046927SAndroid Build Coastguard Worker                   nralphainrangehigh += 1;
304*61046927SAndroid Build Coastguard Worker                }
305*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[3]) {
306*61046927SAndroid Build Coastguard Worker                   blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
307*61046927SAndroid Build Coastguard Worker                   blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
308*61046927SAndroid Build Coastguard Worker                   nralphainrangelow += 1;
309*61046927SAndroid Build Coastguard Worker                   nralphainrangehigh += 1;
310*61046927SAndroid Build Coastguard Worker                }
311*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[4]) {
312*61046927SAndroid Build Coastguard Worker                   blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
313*61046927SAndroid Build Coastguard Worker                   blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
314*61046927SAndroid Build Coastguard Worker                   nralphainrangelow += 1;
315*61046927SAndroid Build Coastguard Worker                   nralphainrangehigh += 1;
316*61046927SAndroid Build Coastguard Worker                   }
317*61046927SAndroid Build Coastguard Worker                else {
318*61046927SAndroid Build Coastguard Worker                   blockerrlin2 += (srccolors[j][i] - alphatest[1]);
319*61046927SAndroid Build Coastguard Worker                   nralphainrangehigh += 1;
320*61046927SAndroid Build Coastguard Worker                }
321*61046927SAndroid Build Coastguard Worker             }
322*61046927SAndroid Build Coastguard Worker          }
323*61046927SAndroid Build Coastguard Worker          /* shouldn't happen often, needed to avoid div by zero */
324*61046927SAndroid Build Coastguard Worker          if (nralphainrangelow == 0) nralphainrangelow = 1;
325*61046927SAndroid Build Coastguard Worker          if (nralphainrangehigh == 0) nralphainrangehigh = 1;
326*61046927SAndroid Build Coastguard Worker          alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
327*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
328*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
329*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
330*61046927SAndroid Build Coastguard Worker #endif
331*61046927SAndroid Build Coastguard Worker          /* again shouldn't really happen often... */
332*61046927SAndroid Build Coastguard Worker          if (alphatest[0] < T_MIN) {
333*61046927SAndroid Build Coastguard Worker             alphatest[0] = T_MIN;
334*61046927SAndroid Build Coastguard Worker          }
335*61046927SAndroid Build Coastguard Worker          alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
336*61046927SAndroid Build Coastguard Worker          if (alphatest[1] > T_MAX) {
337*61046927SAndroid Build Coastguard Worker             alphatest[1] = T_MAX;
338*61046927SAndroid Build Coastguard Worker          }
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker          alphablockerror3 = 0;
341*61046927SAndroid Build Coastguard Worker          for (aindex = 0; aindex < 5; aindex++) {
342*61046927SAndroid Build Coastguard Worker          /* don't forget here is always rounded down */
343*61046927SAndroid Build Coastguard Worker             acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
344*61046927SAndroid Build Coastguard Worker          }
345*61046927SAndroid Build Coastguard Worker          for (j = 0; j < numypixels; j++) {
346*61046927SAndroid Build Coastguard Worker             for (i = 0; i < numxpixels; i++) {
347*61046927SAndroid Build Coastguard Worker                 /* maybe it's overkill to have the most complicated calculation just for the error
348*61046927SAndroid Build Coastguard Worker                   calculation which we only need to figure out if encoding1 or encoding2 is better... */
349*61046927SAndroid Build Coastguard Worker                if (srccolors[j][i] <= alphatest[0] / 2) {
350*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 6;
351*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i];
352*61046927SAndroid Build Coastguard Worker                }
353*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
354*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 7;
355*61046927SAndroid Build Coastguard Worker                   alphadist = T_MAX - srccolors[j][i];
356*61046927SAndroid Build Coastguard Worker                }
357*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[0]) {
358*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 0;
359*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i] - alphatest[0];
360*61046927SAndroid Build Coastguard Worker                }
361*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[1]) {
362*61046927SAndroid Build Coastguard Worker                  alphaenc3[4*j + i] = 2;
363*61046927SAndroid Build Coastguard Worker                  alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
364*61046927SAndroid Build Coastguard Worker                }
365*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[2]) {
366*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 3;
367*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
368*61046927SAndroid Build Coastguard Worker                }
369*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[3]) {
370*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 4;
371*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
372*61046927SAndroid Build Coastguard Worker                }
373*61046927SAndroid Build Coastguard Worker                else if (srccolors[j][i] <= acutValues[4]) {
374*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 5;
375*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
376*61046927SAndroid Build Coastguard Worker                }
377*61046927SAndroid Build Coastguard Worker                else {
378*61046927SAndroid Build Coastguard Worker                   alphaenc3[4*j + i] = 1;
379*61046927SAndroid Build Coastguard Worker                   alphadist = srccolors[j][i] - alphatest[1];
380*61046927SAndroid Build Coastguard Worker                }
381*61046927SAndroid Build Coastguard Worker                alphablockerror3 += alphadist * alphadist;
382*61046927SAndroid Build Coastguard Worker             }
383*61046927SAndroid Build Coastguard Worker          }
384*61046927SAndroid Build Coastguard Worker       }
385*61046927SAndroid Build Coastguard Worker    }
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker   /* write the alpha values and encoding back. */
388*61046927SAndroid Build Coastguard Worker    if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
389*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
390*61046927SAndroid Build Coastguard Worker       if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
391*61046927SAndroid Build Coastguard Worker       fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n",
392*61046927SAndroid Build Coastguard Worker 	      T_MIN, T_MAX,
393*61046927SAndroid Build Coastguard Worker 	      alphause[1], alphause[0]);
394*61046927SAndroid Build Coastguard Worker #endif
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker       TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
397*61046927SAndroid Build Coastguard Worker    }
398*61046927SAndroid Build Coastguard Worker    else if (alphablockerror2 <= alphablockerror3) {
399*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
400*61046927SAndroid Build Coastguard Worker       if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
401*61046927SAndroid Build Coastguard Worker       fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n",
402*61046927SAndroid Build Coastguard Worker 	      T_MIN, T_MAX,
403*61046927SAndroid Build Coastguard Worker 	      alphabase[0], alphabase[1]);
404*61046927SAndroid Build Coastguard Worker #endif
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker       TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
407*61046927SAndroid Build Coastguard Worker    }
408*61046927SAndroid Build Coastguard Worker    else {
409*61046927SAndroid Build Coastguard Worker #if RGTC_DEBUG
410*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
411*61046927SAndroid Build Coastguard Worker       fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n",
412*61046927SAndroid Build Coastguard Worker 	      T_MIN, T_MAX,
413*61046927SAndroid Build Coastguard Worker 	      alphatest[0], alphatest[1]);
414*61046927SAndroid Build Coastguard Worker #endif
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker       TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
417*61046927SAndroid Build Coastguard Worker    }
418*61046927SAndroid Build Coastguard Worker }
419