101e04c3fSmrg/*
201e04c3fSmrg * Copyright (C) 2011 Red Hat Inc.
301e04c3fSmrg *
401e04c3fSmrg * block compression parts are:
501e04c3fSmrg * Copyright (C) 2004  Roland Scheidegger   All Rights Reserved.
601e04c3fSmrg *
701e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
801e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
901e04c3fSmrg * to deal in the Software without restriction, including without limitation
1001e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1101e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
1201e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1301e04c3fSmrg *
1401e04c3fSmrg * The above copyright notice and this permission notice (including the next
1501e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1601e04c3fSmrg * Software.
1701e04c3fSmrg *
1801e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1901e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2001e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2101e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2201e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2301e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2401e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2501e04c3fSmrg *
2601e04c3fSmrg * Author:
2701e04c3fSmrg *    Dave Airlie
2801e04c3fSmrg */
2901e04c3fSmrg
3001e04c3fSmrg/* included by texcompress_rgtc to define byte/ubyte compressors */
3101e04c3fSmrg
3201e04c3fSmrgvoid TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata,
3301e04c3fSmrg	                   unsigned i, unsigned j, TYPE *value, unsigned comps)
3401e04c3fSmrg{
3501e04c3fSmrg   TYPE decode;
3601e04c3fSmrg   const TYPE *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8 * comps);
3701e04c3fSmrg   const TYPE alpha0 = blksrc[0];
3801e04c3fSmrg   const TYPE alpha1 = blksrc[1];
3901e04c3fSmrg   const char bit_pos = ((j&3) * 4 + (i&3)) * 3;
4001e04c3fSmrg   const unsigned char acodelow = blksrc[2 + bit_pos / 8];
4101e04c3fSmrg   const unsigned char acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0;
4201e04c3fSmrg   const unsigned char code = (acodelow >> (bit_pos & 0x7) |
4301e04c3fSmrg      (acodehigh  << (8 - (bit_pos & 0x7)))) & 0x7;
4401e04c3fSmrg
4501e04c3fSmrg   if (code == 0)
4601e04c3fSmrg      decode = alpha0;
4701e04c3fSmrg   else if (code == 1)
4801e04c3fSmrg      decode = alpha1;
4901e04c3fSmrg   else if (alpha0 > alpha1)
5001e04c3fSmrg      decode = ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7);
5101e04c3fSmrg   else if (code < 6)
5201e04c3fSmrg      decode = ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5);
5301e04c3fSmrg   else if (code == 6)
5401e04c3fSmrg      decode = T_MIN;
5501e04c3fSmrg   else
5601e04c3fSmrg      decode = T_MAX;
5701e04c3fSmrg
5801e04c3fSmrg   *value = decode;
5901e04c3fSmrg}
6001e04c3fSmrg
6101e04c3fSmrgstatic void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
6201e04c3fSmrg                                            TYPE alphabase1,
6301e04c3fSmrg                                            TYPE alphabase2,
6401e04c3fSmrg                                            TYPE alphaenc[16])
6501e04c3fSmrg{
6601e04c3fSmrg   *blkaddr++ = alphabase1;
6701e04c3fSmrg   *blkaddr++ = alphabase2;
6801e04c3fSmrg   *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
6901e04c3fSmrg   *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
7001e04c3fSmrg   *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
7101e04c3fSmrg   *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
7201e04c3fSmrg   *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
7301e04c3fSmrg   *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
7401e04c3fSmrg}
7501e04c3fSmrg
7601e04c3fSmrgvoid TAG(encode_rgtc_ubyte)(TYPE *blkaddr, TYPE srccolors[4][4],
7701e04c3fSmrg                            int numxpixels, int numypixels)
7801e04c3fSmrg{
7901e04c3fSmrg   TYPE alphabase[2], alphause[2];
8001e04c3fSmrg   short alphatest[2] = { 0 };
8101e04c3fSmrg   unsigned int alphablockerror1, alphablockerror2, alphablockerror3;
8201e04c3fSmrg   TYPE i, j, aindex, acutValues[7];
8301e04c3fSmrg   TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
8401e04c3fSmrg   int alphaabsmin = 0, alphaabsmax = 0;
8501e04c3fSmrg   short alphadist;
8601e04c3fSmrg
8701e04c3fSmrg   /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
8801e04c3fSmrg   alphabase[0] = T_MAX; alphabase[1] = T_MIN;
8901e04c3fSmrg   for (j = 0; j < numypixels; j++) {
9001e04c3fSmrg      for (i = 0; i < numxpixels; i++) {
9101e04c3fSmrg	 if (srccolors[j][i] == T_MIN)
9201e04c3fSmrg            alphaabsmin = 1;
9301e04c3fSmrg         else if (srccolors[j][i] == T_MAX)
9401e04c3fSmrg            alphaabsmax = 1;
9501e04c3fSmrg         else {
9601e04c3fSmrg            if (srccolors[j][i] > alphabase[1])
9701e04c3fSmrg               alphabase[1] = srccolors[j][i];
9801e04c3fSmrg            if (srccolors[j][i] < alphabase[0])
9901e04c3fSmrg               alphabase[0] = srccolors[j][i];
10001e04c3fSmrg         }
10101e04c3fSmrg      }
10201e04c3fSmrg   }
10301e04c3fSmrg
10401e04c3fSmrg
10501e04c3fSmrg   if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
10601e04c3fSmrg       || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */
10701e04c3fSmrg      /* shortcut here since it is a very common case (and also avoids later problems) */
10801e04c3fSmrg      /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
10901e04c3fSmrg
11001e04c3fSmrg      *blkaddr++ = srccolors[0][0];
11101e04c3fSmrg      blkaddr++;
11201e04c3fSmrg      *blkaddr++ = 0;
11301e04c3fSmrg      *blkaddr++ = 0;
11401e04c3fSmrg      *blkaddr++ = 0;
11501e04c3fSmrg      *blkaddr++ = 0;
11601e04c3fSmrg      *blkaddr++ = 0;
11701e04c3fSmrg      *blkaddr++ = 0;
11801e04c3fSmrg#if RGTC_DEBUG
11901e04c3fSmrg      fprintf(stderr, "enc0 used\n");
12001e04c3fSmrg#endif
12101e04c3fSmrg      return;
12201e04c3fSmrg   }
12301e04c3fSmrg
12401e04c3fSmrg   /* find best encoding for alpha0 > alpha1 */
12501e04c3fSmrg   /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
12601e04c3fSmrg   alphablockerror1 = 0x0;
12701e04c3fSmrg   alphablockerror2 = 0xffffffff;
12801e04c3fSmrg   alphablockerror3 = 0xffffffff;
12901e04c3fSmrg   if (alphaabsmin) alphause[0] = T_MIN;
13001e04c3fSmrg   else alphause[0] = alphabase[0];
13101e04c3fSmrg   if (alphaabsmax) alphause[1] = T_MAX;
13201e04c3fSmrg   else alphause[1] = alphabase[1];
13301e04c3fSmrg   /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
13401e04c3fSmrg   for (aindex = 0; aindex < 7; aindex++) {
13501e04c3fSmrg      /* don't forget here is always rounded down */
13601e04c3fSmrg      acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
13701e04c3fSmrg   }
13801e04c3fSmrg
13901e04c3fSmrg   for (j = 0; j < numypixels; j++) {
14001e04c3fSmrg      for (i = 0; i < numxpixels; i++) {
14101e04c3fSmrg         /* maybe it's overkill to have the most complicated calculation just for the error
14201e04c3fSmrg            calculation which we only need to figure out if encoding1 or encoding2 is better... */
14301e04c3fSmrg         if (srccolors[j][i] > acutValues[0]) {
14401e04c3fSmrg            alphaenc1[4*j + i] = 0;
14501e04c3fSmrg            alphadist = srccolors[j][i] - alphause[1];
14601e04c3fSmrg         }
14701e04c3fSmrg         else if (srccolors[j][i] > acutValues[1]) {
14801e04c3fSmrg            alphaenc1[4*j + i] = 2;
14901e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
15001e04c3fSmrg         }
15101e04c3fSmrg         else if (srccolors[j][i] > acutValues[2]) {
15201e04c3fSmrg            alphaenc1[4*j + i] = 3;
15301e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
15401e04c3fSmrg         }
15501e04c3fSmrg         else if (srccolors[j][i] > acutValues[3]) {
15601e04c3fSmrg            alphaenc1[4*j + i] = 4;
15701e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
15801e04c3fSmrg         }
15901e04c3fSmrg         else if (srccolors[j][i] > acutValues[4]) {
16001e04c3fSmrg            alphaenc1[4*j + i] = 5;
16101e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
16201e04c3fSmrg         }
16301e04c3fSmrg         else if (srccolors[j][i] > acutValues[5]) {
16401e04c3fSmrg            alphaenc1[4*j + i] = 6;
16501e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
16601e04c3fSmrg         }
16701e04c3fSmrg         else if (srccolors[j][i] > acutValues[6]) {
16801e04c3fSmrg            alphaenc1[4*j + i] = 7;
16901e04c3fSmrg            alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
17001e04c3fSmrg         }
17101e04c3fSmrg         else {
17201e04c3fSmrg            alphaenc1[4*j + i] = 1;
17301e04c3fSmrg            alphadist = srccolors[j][i] - alphause[0];
17401e04c3fSmrg         }
17501e04c3fSmrg         alphablockerror1 += alphadist * alphadist;
17601e04c3fSmrg      }
17701e04c3fSmrg   }
17801e04c3fSmrg
17901e04c3fSmrg#if RGTC_DEBUG
18001e04c3fSmrg   for (i = 0; i < 16; i++) {
18101e04c3fSmrg      fprintf(stderr, "%d ", alphaenc1[i]);
18201e04c3fSmrg   }
18301e04c3fSmrg   fprintf(stderr, "cutVals ");
18401e04c3fSmrg   for (i = 0; i < 7; i++) {
18501e04c3fSmrg      fprintf(stderr, "%d ", acutValues[i]);
18601e04c3fSmrg   }
18701e04c3fSmrg   fprintf(stderr, "srcVals ");
18801e04c3fSmrg   for (j = 0; j < numypixels; j++) {
18901e04c3fSmrg      for (i = 0; i < numxpixels; i++) {
19001e04c3fSmrg	 fprintf(stderr, "%d ", srccolors[j][i]);
19101e04c3fSmrg      }
19201e04c3fSmrg   }
19301e04c3fSmrg   fprintf(stderr, "\n");
19401e04c3fSmrg#endif
19501e04c3fSmrg
19601e04c3fSmrg   /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
19701e04c3fSmrg      are false but try it anyway */
19801e04c3fSmrg   if (alphablockerror1 >= 32) {
19901e04c3fSmrg
20001e04c3fSmrg      /* don't bother if encoding is already very good, this condition should also imply
20101e04c3fSmrg      we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
20201e04c3fSmrg      alphablockerror2 = 0;
20301e04c3fSmrg      for (aindex = 0; aindex < 5; aindex++) {
20401e04c3fSmrg         /* don't forget here is always rounded down */
20501e04c3fSmrg         acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
20601e04c3fSmrg      }
20701e04c3fSmrg      for (j = 0; j < numypixels; j++) {
20801e04c3fSmrg         for (i = 0; i < numxpixels; i++) {
20901e04c3fSmrg             /* maybe it's overkill to have the most complicated calculation just for the error
21001e04c3fSmrg               calculation which we only need to figure out if encoding1 or encoding2 is better... */
21101e04c3fSmrg            if (srccolors[j][i] == T_MIN) {
21201e04c3fSmrg               alphaenc2[4*j + i] = 6;
21301e04c3fSmrg               alphadist = 0;
21401e04c3fSmrg            }
21501e04c3fSmrg            else if (srccolors[j][i] == T_MAX) {
21601e04c3fSmrg               alphaenc2[4*j + i] = 7;
21701e04c3fSmrg               alphadist = 0;
21801e04c3fSmrg            }
21901e04c3fSmrg            else if (srccolors[j][i] <= acutValues[0]) {
22001e04c3fSmrg               alphaenc2[4*j + i] = 0;
22101e04c3fSmrg               alphadist = srccolors[j][i] - alphabase[0];
22201e04c3fSmrg            }
22301e04c3fSmrg            else if (srccolors[j][i] <= acutValues[1]) {
22401e04c3fSmrg               alphaenc2[4*j + i] = 2;
22501e04c3fSmrg               alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
22601e04c3fSmrg            }
22701e04c3fSmrg            else if (srccolors[j][i] <= acutValues[2]) {
22801e04c3fSmrg               alphaenc2[4*j + i] = 3;
22901e04c3fSmrg               alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
23001e04c3fSmrg            }
23101e04c3fSmrg            else if (srccolors[j][i] <= acutValues[3]) {
23201e04c3fSmrg               alphaenc2[4*j + i] = 4;
23301e04c3fSmrg               alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
23401e04c3fSmrg            }
23501e04c3fSmrg            else if (srccolors[j][i] <= acutValues[4]) {
23601e04c3fSmrg               alphaenc2[4*j + i] = 5;
23701e04c3fSmrg               alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
23801e04c3fSmrg            }
23901e04c3fSmrg            else {
24001e04c3fSmrg               alphaenc2[4*j + i] = 1;
24101e04c3fSmrg               alphadist = srccolors[j][i] - alphabase[1];
24201e04c3fSmrg            }
24301e04c3fSmrg            alphablockerror2 += alphadist * alphadist;
24401e04c3fSmrg         }
24501e04c3fSmrg      }
24601e04c3fSmrg
24701e04c3fSmrg
24801e04c3fSmrg      /* skip this if the error is already very small
24901e04c3fSmrg         this encoding is MUCH better on average than #2 though, but expensive! */
25001e04c3fSmrg      if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
25101e04c3fSmrg         short blockerrlin1 = 0;
25201e04c3fSmrg         short blockerrlin2 = 0;
25301e04c3fSmrg         TYPE nralphainrangelow = 0;
25401e04c3fSmrg         TYPE nralphainrangehigh = 0;
25501e04c3fSmrg         alphatest[0] = T_MAX;
25601e04c3fSmrg         alphatest[1] = T_MIN;
25701e04c3fSmrg         /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
25801e04c3fSmrg         for (j = 0; j < numypixels; j++) {
25901e04c3fSmrg            for (i = 0; i < numxpixels; i++) {
26001e04c3fSmrg               if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
26101e04c3fSmrg                  alphatest[1] = srccolors[j][i];
26201e04c3fSmrg               if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
26301e04c3fSmrg                  alphatest[0] = srccolors[j][i];
26401e04c3fSmrg            }
26501e04c3fSmrg         }
26601e04c3fSmrg          /* shouldn't happen too often, don't really care about those degenerated cases */
26701e04c3fSmrg          if (alphatest[1] <= alphatest[0]) {
26801e04c3fSmrg             alphatest[0] = T_MIN+1;
26901e04c3fSmrg             alphatest[1] = T_MAX-1;
27001e04c3fSmrg         }
27101e04c3fSmrg         for (aindex = 0; aindex < 5; aindex++) {
27201e04c3fSmrg         /* don't forget here is always rounded down */
27301e04c3fSmrg            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
27401e04c3fSmrg         }
27501e04c3fSmrg
27601e04c3fSmrg         /* find the "average" difference between the alpha values and the next encoded value.
27701e04c3fSmrg            This is then used to calculate new base values.
27801e04c3fSmrg            Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
27901e04c3fSmrg            since they will see more improvement, and also because the values in the middle are somewhat
28001e04c3fSmrg            likely to get no improvement at all (because the base values might move in different directions)?
28101e04c3fSmrg            OTOH it would mean the values in the middle are even less likely to get an improvement
28201e04c3fSmrg         */
28301e04c3fSmrg         for (j = 0; j < numypixels; j++) {
28401e04c3fSmrg            for (i = 0; i < numxpixels; i++) {
28501e04c3fSmrg               if (srccolors[j][i] <= alphatest[0] / 2) {
28601e04c3fSmrg               }
28701e04c3fSmrg               else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
28801e04c3fSmrg               }
28901e04c3fSmrg               else if (srccolors[j][i] <= acutValues[0]) {
29001e04c3fSmrg                  blockerrlin1 += (srccolors[j][i] - alphatest[0]);
29101e04c3fSmrg                  nralphainrangelow += 1;
29201e04c3fSmrg               }
29301e04c3fSmrg               else if (srccolors[j][i] <= acutValues[1]) {
29401e04c3fSmrg                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
29501e04c3fSmrg                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
29601e04c3fSmrg                  nralphainrangelow += 1;
29701e04c3fSmrg                  nralphainrangehigh += 1;
29801e04c3fSmrg               }
29901e04c3fSmrg               else if (srccolors[j][i] <= acutValues[2]) {
30001e04c3fSmrg                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
30101e04c3fSmrg                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
30201e04c3fSmrg                  nralphainrangelow += 1;
30301e04c3fSmrg                  nralphainrangehigh += 1;
30401e04c3fSmrg               }
30501e04c3fSmrg               else if (srccolors[j][i] <= acutValues[3]) {
30601e04c3fSmrg                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
30701e04c3fSmrg                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
30801e04c3fSmrg                  nralphainrangelow += 1;
30901e04c3fSmrg                  nralphainrangehigh += 1;
31001e04c3fSmrg               }
31101e04c3fSmrg               else if (srccolors[j][i] <= acutValues[4]) {
31201e04c3fSmrg                  blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
31301e04c3fSmrg                  blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
31401e04c3fSmrg                  nralphainrangelow += 1;
31501e04c3fSmrg                  nralphainrangehigh += 1;
31601e04c3fSmrg                  }
31701e04c3fSmrg               else {
31801e04c3fSmrg                  blockerrlin2 += (srccolors[j][i] - alphatest[1]);
31901e04c3fSmrg                  nralphainrangehigh += 1;
32001e04c3fSmrg               }
32101e04c3fSmrg            }
32201e04c3fSmrg         }
32301e04c3fSmrg         /* shouldn't happen often, needed to avoid div by zero */
32401e04c3fSmrg         if (nralphainrangelow == 0) nralphainrangelow = 1;
32501e04c3fSmrg         if (nralphainrangehigh == 0) nralphainrangehigh = 1;
32601e04c3fSmrg         alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
32701e04c3fSmrg#if RGTC_DEBUG
32801e04c3fSmrg         fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
32901e04c3fSmrg         fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
33001e04c3fSmrg#endif
33101e04c3fSmrg         /* again shouldn't really happen often... */
33201e04c3fSmrg         if (alphatest[0] < T_MIN) {
33301e04c3fSmrg            alphatest[0] = T_MIN;
33401e04c3fSmrg         }
33501e04c3fSmrg         alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
33601e04c3fSmrg         if (alphatest[1] > T_MAX) {
33701e04c3fSmrg            alphatest[1] = T_MAX;
33801e04c3fSmrg         }
33901e04c3fSmrg
34001e04c3fSmrg         alphablockerror3 = 0;
34101e04c3fSmrg         for (aindex = 0; aindex < 5; aindex++) {
34201e04c3fSmrg         /* don't forget here is always rounded down */
34301e04c3fSmrg            acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
34401e04c3fSmrg         }
34501e04c3fSmrg         for (j = 0; j < numypixels; j++) {
34601e04c3fSmrg            for (i = 0; i < numxpixels; i++) {
34701e04c3fSmrg                /* maybe it's overkill to have the most complicated calculation just for the error
34801e04c3fSmrg                  calculation which we only need to figure out if encoding1 or encoding2 is better... */
34901e04c3fSmrg               if (srccolors[j][i] <= alphatest[0] / 2) {
35001e04c3fSmrg                  alphaenc3[4*j + i] = 6;
35101e04c3fSmrg                  alphadist = srccolors[j][i];
35201e04c3fSmrg               }
35301e04c3fSmrg               else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
35401e04c3fSmrg                  alphaenc3[4*j + i] = 7;
35501e04c3fSmrg                  alphadist = T_MAX - srccolors[j][i];
35601e04c3fSmrg               }
35701e04c3fSmrg               else if (srccolors[j][i] <= acutValues[0]) {
35801e04c3fSmrg                  alphaenc3[4*j + i] = 0;
35901e04c3fSmrg                  alphadist = srccolors[j][i] - alphatest[0];
36001e04c3fSmrg               }
36101e04c3fSmrg               else if (srccolors[j][i] <= acutValues[1]) {
36201e04c3fSmrg                 alphaenc3[4*j + i] = 2;
36301e04c3fSmrg                 alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
36401e04c3fSmrg               }
36501e04c3fSmrg               else if (srccolors[j][i] <= acutValues[2]) {
36601e04c3fSmrg                  alphaenc3[4*j + i] = 3;
36701e04c3fSmrg                  alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
36801e04c3fSmrg               }
36901e04c3fSmrg               else if (srccolors[j][i] <= acutValues[3]) {
37001e04c3fSmrg                  alphaenc3[4*j + i] = 4;
37101e04c3fSmrg                  alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
37201e04c3fSmrg               }
37301e04c3fSmrg               else if (srccolors[j][i] <= acutValues[4]) {
37401e04c3fSmrg                  alphaenc3[4*j + i] = 5;
37501e04c3fSmrg                  alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
37601e04c3fSmrg               }
37701e04c3fSmrg               else {
37801e04c3fSmrg                  alphaenc3[4*j + i] = 1;
37901e04c3fSmrg                  alphadist = srccolors[j][i] - alphatest[1];
38001e04c3fSmrg               }
38101e04c3fSmrg               alphablockerror3 += alphadist * alphadist;
38201e04c3fSmrg            }
38301e04c3fSmrg         }
38401e04c3fSmrg      }
38501e04c3fSmrg   }
38601e04c3fSmrg
38701e04c3fSmrg  /* write the alpha values and encoding back. */
38801e04c3fSmrg   if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
38901e04c3fSmrg#if RGTC_DEBUG
39001e04c3fSmrg      if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
39101e04c3fSmrg      fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n",
39201e04c3fSmrg	      T_MIN, T_MAX,
39301e04c3fSmrg	      alphause[1], alphause[0]);
39401e04c3fSmrg#endif
39501e04c3fSmrg
39601e04c3fSmrg      TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
39701e04c3fSmrg   }
39801e04c3fSmrg   else if (alphablockerror2 <= alphablockerror3) {
39901e04c3fSmrg#if RGTC_DEBUG
40001e04c3fSmrg      if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
40101e04c3fSmrg      fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n",
40201e04c3fSmrg	      T_MIN, T_MAX,
40301e04c3fSmrg	      alphabase[0], alphabase[1]);
40401e04c3fSmrg#endif
40501e04c3fSmrg
40601e04c3fSmrg      TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
40701e04c3fSmrg   }
40801e04c3fSmrg   else {
40901e04c3fSmrg#if RGTC_DEBUG
41001e04c3fSmrg      fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
41101e04c3fSmrg      fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n",
41201e04c3fSmrg	      T_MIN, T_MAX,
41301e04c3fSmrg	      alphatest[0], alphatest[1]);
41401e04c3fSmrg#endif
41501e04c3fSmrg
41601e04c3fSmrg      TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
41701e04c3fSmrg   }
41801e04c3fSmrg}
419