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