[gimp-dds] / trunk / dxt.c Repository:
ViewVC logotype

View of /trunk/dxt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 120 - (download) (as text) (annotate)
Tue Nov 11 19:05:16 2008 UTC (12 months, 1 week ago) by cocidius
File size: 35722 byte(s)
* Fix some gcc 4.3 warnings
* Corrected mipmap image generation for DXT compressed images when mipmap
image has a dimension smaller than 4 pixels
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004-2008 Shawn Kirst <skirst@insightbb.com>,
    5    with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
    6 
    7    This program is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU General Public
    9    License as published by the Free Software Foundation; either
   10    version 2 of the License, or (at your option) any later version.
   11 
   12    This program is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    General Public License for more details.
   16 
   17    You should have received a copy of the GNU General Public License
   18    along with this program; see the file COPYING.  If not, write to
   19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20    Boston, MA 02111-1307, USA.
   21 */
   22 
   23 /*
   24  * Parts of this code have been generously released in the public domain
   25  * by Fabian 'ryg' Giesen.  The original code can be found (at the time
   26  * of writing) here:  http://mollyrocket.com/forums/viewtopic.php?t=392
   27  *
   28  * For more information about this code, see the README.dxt file that
   29  * came with the source.
   30  */
   31 
   32 #include <stdlib.h>
   33 #include <string.h>
   34 #include <math.h>
   35 #include <glib.h>
   36 
   37 #include "dds.h"
   38 #include "endian.h"
   39 #include "mipmap.h"
   40 #include "imath.h"
   41 
   42 #include "dxt_tables.h"
   43 
   44 /* extract 4x4 BGRA block */
   45 static void extract_block(const unsigned char *src, int x, int y,
   46                           int w, int h, unsigned char *block)
   47 {
   48    int i, j;
   49    int bw = MIN(w - x, 4);
   50    int bh = MIN(h - y, 4);
   51    int bx, by;
   52    const int rem[] =
   53    {
   54       0, 0, 0, 0,
   55       0, 1, 0, 1,
   56       0, 1, 2, 0,
   57       0, 1, 2, 3
   58    };
   59 
   60    for(i = 0; i < 4; ++i)
   61    {
   62       by = rem[(bh - 1) * 4 + i] + y;
   63       for(j = 0; j < 4; ++j)
   64       {
   65          bx = rem[(bw - 1) * 4 + j] + x;
   66          block[(i * 4 * 4) + (j * 4) + 0] =
   67             src[(by * (w * 4)) + (bx * 4) + 0];
   68          block[(i * 4 * 4) + (j * 4) + 1] =
   69             src[(by * (w * 4)) + (bx * 4) + 1];
   70          block[(i * 4 * 4) + (j * 4) + 2] =
   71             src[(by * (w * 4)) + (bx * 4) + 2];
   72          block[(i * 4 * 4) + (j * 4) + 3] =
   73             src[(by * (w * 4)) + (bx * 4) + 3];
   74       }
   75    }
   76 }
   77 
   78 /* pack BGR8 to RGB565 */
   79 static inline unsigned short pack_rgb565(const unsigned char *c)
   80 {
   81    return(((c[2] >> 3) << 11) | ((c[1] >> 2) << 5) | (c[0] >> 3));
   82 }
   83 
   84 /* unpack RGB565 to BGR */
   85 static void unpack_rgb565(unsigned char *dst, unsigned short v)
   86 {
   87    int r = (v >> 11) & 0x1f;
   88    int g = (v >>  5) & 0x3f;
   89    int b = (v      ) & 0x1f;
   90 
   91    dst[0] = (b << 3) | (b >> 2);
   92    dst[1] = (g << 2) | (g >> 4);
   93    dst[2] = (r << 3) | (r >> 2);
   94 }
   95 
   96 static void lerp_rgb(unsigned char *dst, unsigned char *a, unsigned char *b, int f)
   97 {
   98    dst[0] = blerp(a[0], b[0], f);
   99    dst[1] = blerp(a[1], b[1], f);
  100    dst[2] = blerp(a[2], b[2], f);
  101 }
  102 
  103 static int color_distance(const unsigned char *c0,
  104                           const unsigned char *c1)
  105 {
  106    return(((c0[0] - c1[0]) * (c0[0] - c1[0])) +
  107           ((c0[1] - c1[1]) * (c0[1] - c1[1])) +
  108           ((c0[2] - c1[2]) * (c0[2] - c1[2])));
  109 }
  110 
  111 static int luminance(const unsigned char *c)
  112 {
  113    return((c[2] * 54 + c[1] * 182 + c[0] * 20) >> 8);
  114 }
  115 
  116 /* Block dithering function.  Simply dithers a block to 565 RGB.
  117  * (Floyd-Steinberg)
  118  */
  119 static void dither_block(unsigned char *dst, const unsigned char *block)
  120 {
  121    int err[8], *ep1 = err, *ep2 = err + 4, *tmp;
  122    int c, y;
  123    unsigned char *bp, *dp;
  124    const unsigned char *quant;
  125 
  126    /* process channels seperately */
  127    for(c = 0; c < 3; ++c)
  128    {
  129       bp = (unsigned char *)block;
  130       dp = dst;
  131       quant = (c == 1) ? quantG + 8 : quantRB + 8;
  132 
  133       bp += c;
  134       dp += c;
  135 
  136       memset(err, 0, sizeof(err));
  137 
  138       for(y = 0; y < 4; ++y)
  139       {
  140          /* pixel 0 */
  141          dp[ 0] = quant[bp[ 0] + ((3 * ep2[1] + 5 * ep2[0]) >> 4)];
  142          ep1[0] = bp[ 0] - dp[ 0];
  143 
  144          /* pixel 1 */
  145          dp[ 4] = quant[bp[ 4] + ((7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]) >> 4)];
  146          ep1[1] = bp[ 4] - dp[ 4];
  147 
  148          /* pixel 2 */
  149          dp[ 8] = quant[bp[ 8] + ((7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]) >> 4)];
  150          ep1[2] = bp[ 8] - dp[ 8];
  151 
  152          /* pixel 3 */
  153          dp[12] = quant[bp[12] + ((7 * ep1[2] + 5 * ep2[3] + ep2[2]) >> 4)];
  154          ep1[3] = bp[12] - dp[12];
  155 
  156          /* advance to next line */
  157          tmp = ep1;
  158          ep1 = ep2;
  159          ep2 = tmp;
  160 
  161          bp += 16;
  162          dp += 16;
  163       }
  164    }
  165 }
  166 
  167 /* Color matching function */
  168 static unsigned int match_colors_block(const unsigned char *block,
  169                                        unsigned char color[4][3],
  170                                        int dither)
  171 {
  172    unsigned int mask = 0;
  173    int dirb = color[0][0] - color[1][0];
  174    int dirg = color[0][1] - color[1][1];
  175    int dirr = color[0][2] - color[1][2];
  176    int dots[16], stops[4];
  177    int c0pt, halfpt, c3pt, dot;
  178    int i;
  179 
  180    for(i = 0; i < 16; ++i)
  181       dots[i] = block[4 * i] * dirb + block[4 * i + 1] * dirg + block[4 * i + 2] * dirr;
  182 
  183    for(i = 0; i < 4; ++i)
  184       stops[i] = color[i][0] * dirb + color[i][1] * dirg + color[i][2] * dirr;
  185 
  186    c0pt = (stops[1] + stops[3]) >> 1;
  187    halfpt = (stops[3] + stops[2]) >> 1;
  188    c3pt = (stops[2] + stops[0]) >> 1;
  189 
  190    if(!dither)
  191    {
  192       /* the version without dithering is straight-forward */
  193       for(i = 15; i >= 0; --i)
  194       {
  195          mask <<= 2;
  196          dot = dots[i];
  197 
  198          if(dot < halfpt)
  199             mask |= (dot < c0pt) ? 1 : 3;
  200          else
  201             mask |= (dot < c3pt) ? 2 : 0;
  202       }
  203    }
  204    else
  205    {
  206       /* with floyd-steinberg dithering (see above) */
  207       int err[8], *ep1 = err, *ep2 = err + 4, *tmp;
  208       int *dp = dots, y, lmask, step;
  209 
  210       c0pt <<= 4;
  211       halfpt <<= 4;
  212       c3pt <<= 4;
  213 
  214       memset(err, 0, sizeof(err));
  215 
  216       for(y = 0; y < 4; ++y)
  217       {
  218          /* pixel 0 */
  219          dot = (dp[0] << 4) + (3 * ep2[1] + 5 * ep2[0]);
  220          if(dot < halfpt)
  221             step = (dot < c0pt) ? 1 : 3;
  222          else
  223             step = (dot < c3pt) ? 2 : 0;
  224 
  225          ep1[0] = dp[0] - stops[step];
  226          lmask = step;
  227 
  228          /* pixel 1 */
  229          dot = (dp[1] << 4) + (7 * ep1[0] + 3 * ep2[2] + 5 * ep2[1] + ep2[0]);
  230          if(dot < halfpt)
  231             step = (dot < c0pt) ? 1 : 3;
  232          else
  233             step = (dot < c3pt) ? 2 : 0;
  234 
  235          ep1[1] = dp[1] - stops[step];
  236          lmask |= step << 2;
  237 
  238          /* pixel 2 */
  239          dot = (dp[2] << 4) + (7 * ep1[1] + 3 * ep2[3] + 5 * ep2[2] + ep2[1]);
  240          if(dot < halfpt)
  241             step = (dot < c0pt) ? 1 : 3;
  242          else
  243             step = (dot < c3pt) ? 2 : 0;
  244 
  245          ep1[2] = dp[2] - stops[step];
  246          lmask |= step << 4;
  247 
  248          /* pixel 3 */
  249          dot = (dp[3] << 4) + (7 * ep1[2] + 5 * ep2[3] + ep2[2]);
  250          if(dot < halfpt)
  251             step = (dot < c0pt) ? 1 : 3;
  252          else
  253             step = (dot < c3pt) ? 2 : 0;
  254 
  255          ep1[3] = dp[3] - stops[step];
  256          lmask |= step << 6;
  257 
  258          /* advance to next line */
  259          tmp = ep1;
  260          ep1 = ep2;
  261          ep2 = tmp;
  262 
  263          dp += 4;
  264          mask |= lmask << (y * 8);
  265       }
  266    }
  267 
  268    return(mask);
  269 }
  270 
  271 /* Special case color matching for DXT1 color blocks with non-opaque
  272  * alpha values.  Simple distance based color matching.  This is my
  273  * little hack, Fabian had no need for DXT1-alpha :)
  274  */
  275 static unsigned int match_colors_block_DXT1alpha(const unsigned char *block,
  276                                                  unsigned char color[4][3])
  277 {
  278    int i, d0, d1, d2, idx;
  279    unsigned int mask = 0;
  280 
  281    for(i = 15; i >= 0; --i)
  282    {
  283       mask <<= 2;
  284       d0 = color_distance(&block[4 * i], color[0]);
  285       d1 = color_distance(&block[4 * i], color[1]);
  286       d2 = color_distance(&block[4 * i], color[2]);
  287       if(block[4 * i + 3] < 128)
  288          idx = 3;
  289       else if(d0 < d1 && d0 < d2)
  290          idx = 0;
  291       else if(d1 < d2)
  292          idx = 1;
  293       else
  294          idx = 2;
  295       mask |= idx;
  296    }
  297 
  298    return(mask);
  299 }
  300 
  301 /* The color optimization function. (Clever code, part 1) */
  302 static void optimize_colors_block(const unsigned char *block,
  303                                   unsigned short *max16, unsigned short *min16)
  304 {
  305    static const int niterpow = 4;
  306 
  307    int mu[3], mn[3], mx[3];
  308    int i, c, r, g, b, dot, iter;
  309    int muv, mnv, mxv, mnd, mxd;
  310    int cov[6];
  311    unsigned char *bp, mnc[3], mxc[3];
  312    float covf[6], vfr, vfg, vfb, magn;
  313    float fr, fg, fb;
  314 
  315    /* determine color distribution */
  316    for(c = 0; c < 3; ++c)
  317    {
  318       bp = (unsigned char *)block + c;
  319 
  320       muv = mnv = mxv = bp[0];
  321       for(i = 4; i < 64; i += 4)
  322       {
  323          muv += bp[i];
  324          if(mnv > bp[i]) mnv = bp[i];
  325          if(mxv < bp[i]) mxv = bp[i];
  326       }
  327 
  328       mu[c] = (muv + 8) >> 4;
  329       mn[c] = mnv;
  330       mx[c] = mxv;
  331    }
  332 
  333    memset(cov, 0, sizeof(cov));
  334 
  335    /* determine covariance matrix */
  336    for(i = 0; i < 16; ++i)
  337    {
  338       b = block[4 * i + 0] - mu[0];
  339       g = block[4 * i + 1] - mu[1];
  340       r = block[4 * i + 2] - mu[2];
  341 
  342       cov[0] += r * r;
  343       cov[1] += r * g;
  344       cov[2] += r * b;
  345       cov[3] += g * g;
  346       cov[4] += g * b;
  347       cov[5] += b * b;
  348    }
  349 
  350    /* convert covariance matrix to float, find principal axis via power iter */
  351    for(i = 0; i < 6; ++i)
  352       covf[i] = cov[i] / 255.0f;
  353 
  354    vfb = mx[0] - mn[0];
  355    vfg = mx[1] - mn[1];
  356    vfr = mx[2] - mn[2];
  357 
  358    for(iter = 0; iter < niterpow; ++iter)
  359    {
  360       fr = vfr * covf[0] + vfg * covf[1] + vfb * covf[2];
  361       fg = vfr * covf[1] + vfg * covf[3] + vfb * covf[4];
  362       fb = vfr * covf[2] + vfg * covf[4] + vfb * covf[5];
  363 
  364       vfr = fr;
  365       vfg = fg;
  366       vfb = fb;
  367    }
  368 
  369    vfr = fabsf(vfr);
  370    vfg = fabsf(vfg);
  371    vfb = fabsf(vfb);
  372 
  373    magn = MAX(MAX(vfr, vfg), vfb);
  374 
  375    if(magn < 4.0) /* too small, default to luminance */
  376    {
  377       r = 148;
  378       g = 300;
  379       b = 58;
  380    }
  381    else
  382    {
  383       magn = 512.0f / magn;
  384       r = (int)(vfr * magn);
  385       g = (int)(vfg * magn);
  386       b = (int)(vfb * magn);
  387    }
  388 
  389    /* pick colors at extreme points */
  390    mnd =  0x7fffffff;
  391    mxd = -0x7fffffff;
  392 
  393    for(i = 0; i < 16; ++i)
  394    {
  395       dot = block[4 * i] * b + block[4 * i + 1] * g + block[4 * i + 2] * r;
  396 
  397       if(dot < mnd)
  398       {
  399          mnd = dot;
  400          memcpy(mnc, &block[4 * i], 3);
  401       }
  402       if(dot > mxd)
  403       {
  404          mxd = dot;
  405          memcpy(mxc, &block[4 * i], 3);
  406       }
  407    }
  408 
  409    /* reduce to 16-bit colors */
  410    *max16 = pack_rgb565(mxc);
  411    *min16 = pack_rgb565(mnc);
  412 }
  413 
  414 /* The refinement function (Clever code, part 2)
  415  * Tries to optimize colors to suit block contents better.
  416  * (By solving a least squares system via normal equations + Cramer's rule)
  417  */
  418 static int refine_block(const unsigned char *block,
  419                         unsigned short *max16, unsigned short *min16,
  420                         unsigned int mask)
  421 {
  422    static const int w1tab[4] = {3, 0, 2, 1};
  423    static const int prods[4] = {0x090000, 0x000900, 0x040102, 0x010402};
  424    /* ^ Some magic to save a lot of multiplies in the accumulating loop... */
  425 
  426    int akku = 0;
  427    int At1_r, At1_g, At1_b;
  428    int At2_r, At2_g, At2_b;
  429    unsigned int cm = mask;
  430    int i, step, w1, r, g, b;
  431    int xx, yy, xy;
  432    float frb, fg;
  433    unsigned short v, oldmin, oldmax;
  434    int s;
  435 
  436    oldmin = *min16;
  437    oldmax = *max16;
  438    if((mask ^ (mask << 2)) < 4) /* all pixels have the same index */
  439    {
  440       /* degenerate system, use optimal single-color match for average color */
  441       r = g = b = 8;
  442       for(i = 0; i < 16; ++i)
  443       {
  444          r += block[4 * i + 2];
  445          g += block[4 * i + 1];
  446          b += block[4 * i + 0];
  447       }
  448 
  449       r >>= 4;
  450       g >>= 4;
  451       b >>= 4;
  452 
  453       *max16 = (omatch5[r][0] << 11) | (omatch6[g][0] << 5) | omatch5[b][0];
  454       *min16 = (omatch5[r][1] << 11) | (omatch6[g][1] << 5) | omatch5[b][1];
  455       return(*min16 != oldmin || *max16 != oldmax);
  456    }
  457 
  458    At1_r = At1_g = At1_b = 0;
  459    At2_r = At2_g = At2_b = 0;
  460 
  461    for(i = 0; i < 16; ++i, cm >>= 2)
  462    {
  463       step = cm & 3;
  464       w1 = w1tab[step];
  465       r = block[4 * i + 2];
  466       g = block[4 * i + 1];
  467       b = block[4 * i + 0];
  468 
  469       akku  += prods[step];
  470       At1_r += w1 * r;
  471       At1_g += w1 * g;
  472       At1_b += w1 * b;
  473       At2_r += r;
  474       At2_g += g;
  475       At2_b += b;
  476    }
  477 
  478    At2_r = 3 * At2_r - At1_r;
  479    At2_g = 3 * At2_g - At1_g;
  480    At2_b = 3 * At2_b - At1_b;
  481 
  482    /* extract solutions and decide solvability */
  483    xx = akku >> 16;
  484    yy = (akku >> 8) & 0xff;
  485    xy = (akku >> 0) & 0xff;
  486 
  487    frb = 3.0f * 31.0f / 255.0f / (xx * yy - xy * xy);
  488    fg = frb * 63.0f / 31.0f;
  489 
  490    /* solve */
  491    s = (int)((At1_r * yy - At2_r * xy) * frb + 0.5f);
  492    if(s < 0) s = 0;
  493    if(s > 31) s = 31;
  494    v = s << 11;
  495    s = (int)((At1_g * yy - At2_g * xy) * fg + 0.5f);
  496    if(s < 0) s = 0;
  497    if(s > 63) s = 63;
  498    v |= s << 5;
  499    s = (int)((At1_b * yy - At2_b * xy) * frb + 0.5f);
  500    if(s < 0) s = 0;
  501    if(s > 31) s = 31;
  502    v |= s;
  503    *max16 = v;
  504 
  505    s = (int)((At2_r * xx - At1_r * xy) * frb + 0.5f);
  506    if(s < 0) s = 0;
  507    if(s > 31) s = 31;
  508    v = s << 11;
  509    s = (int)((At2_g * xx - At1_g * xy) * fg + 0.5f);
  510    if(s < 0) s = 0;
  511    if(s > 63) s = 63;
  512    v |= s << 5;
  513    s = (int)((At2_b * xx - At1_b * xy) * frb + 0.5f);
  514    if(s < 0) s = 0;
  515    if(s > 31) s = 31;
  516    v |= s;
  517    *min16 = v;
  518 
  519    return(oldmin != *min16 || oldmax != *max16);
  520 }
  521 
  522 /* Find min/max colors by distance */
  523 static void get_min_max_colors_distance(const unsigned char *block,
  524                                         unsigned short *max16,
  525                                         unsigned short *min16)
  526 {
  527    int i, j, dist, maxdist = -1;
  528    unsigned short c0 = 0, c1 = 0;
  529 
  530    for(i = 0; i < 64 - 4; i += 4)
  531    {
  532       for(j = i + 4; j < 64; j += 4)
  533       {
  534          dist = color_distance(&block[i], &block[j]);
  535          if(dist > maxdist)
  536          {
  537             maxdist = dist;
  538             c0 = pack_rgb565(block + i);
  539             c1 = pack_rgb565(block + j);
  540          }
  541       }
  542    }
  543 
  544    *max16 = MAX(c0, c1);
  545    *min16 = MIN(c0, c1);
  546 }
  547 
  548 /* Find min-max colors by luminance */
  549 static void get_min_max_colors_luminance(const unsigned char *block,
  550                                          unsigned short *max16,
  551                                          unsigned short *min16)
  552 {
  553    int i, lum, minlum = 0x7fffffff, maxlum = -0x7fffffff;
  554    unsigned char mn[3], mx[3];
  555 
  556    for(i = 0; i < 16; ++i)
  557    {
  558       lum = luminance(&block[4 * i]);
  559       if(lum > maxlum)
  560       {
  561          maxlum = lum;
  562          memcpy(mx, &block[4 * i], 3);
  563       }
  564       if(lum < minlum)
  565       {
  566          minlum = lum;
  567          memcpy(mn, &block[4 * i], 3);
  568       }
  569    }
  570 
  571    *max16 = pack_rgb565(mx);
  572    *min16 = pack_rgb565(mn);
  573 }
  574 
  575 #define INSET_SHIFT  4
  576 
  577 /* Find min-max colors using the inset bounding box method */
  578 static void get_min_max_colors_inset_bbox(const unsigned char *block,
  579                                           unsigned short *max16,
  580                                           unsigned short *min16)
  581 {
  582    int i;
  583    unsigned char inset[3], mx[3], mn[3];
  584 
  585    mn[0] = mn[1] = mn[2] = 255;
  586    mx[0] = mx[1] = mx[2] = 0;
  587 
  588    for(i = 0; i < 16; ++i)
  589    {
  590       if(block[4 * i + 0] < mn[0]) mn[0] = block[4 * i + 0];
  591       if(block[4 * i + 1] < mn[1]) mn[1] = block[4 * i + 1];
  592       if(block[4 * i + 2] < mn[2]) mn[2] = block[4 * i + 2];
  593       if(block[4 * i + 0] > mx[0]) mx[0] = block[4 * i + 0];
  594       if(block[4 * i + 1] > mx[1]) mx[1] = block[4 * i + 1];
  595       if(block[4 * i + 2] > mx[2]) mx[2] = block[4 * i + 2];
  596    }
  597 
  598    inset[0] = (mx[0] - mn[0]) >> INSET_SHIFT;
  599    inset[1] = (mx[1] - mn[1]) >> INSET_SHIFT;
  600    inset[2] = (mx[2] - mn[2]) >> INSET_SHIFT;
  601 
  602    mn[0] = (mn[0] + inset[0] <= 255) ? mn[0] + inset[0] : 255;
  603    mn[1] = (mn[1] + inset[1] <= 255) ? mn[1] + inset[1] : 255;
  604    mn[2] = (mn[2] + inset[2] <= 255) ? mn[2] + inset[2] : 255;
  605 
  606    mx[0] = (mx[0] >= inset[0]) ? mx[0] - inset[0] : 0;
  607    mx[1] = (mx[1] >= inset[1]) ? mx[1] - inset[1] : 0;
  608    mx[2] = (mx[2] >= inset[2]) ? mx[2] - inset[2] : 0;
  609 
  610    *min16 = pack_rgb565(mn);
  611    *max16 = pack_rgb565(mx);
  612 }
  613 
  614 static void get_min_max_YCoCg(const unsigned char *block,
  615                               unsigned char *mincolor, unsigned char *maxcolor)
  616 {
  617    int i;
  618 
  619    mincolor[2] = mincolor[1] = 255;
  620    maxcolor[2] = maxcolor[1] = 0;
  621 
  622    for(i = 0; i < 16; ++i)
  623    {
  624       if(block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2];
  625       if(block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1];
  626       if(block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2];
  627       if(block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1];
  628    }
  629 }
  630 
  631 static void scale_YCoCg(unsigned char *block,
  632                         unsigned char *mincolor, unsigned char *maxcolor)
  633 {
  634    const int s0 = 128 / 2 - 1;
  635    const int s1 = 128 / 4 - 1;
  636    int m0, m1, m2, m3;
  637    int mask0, mask1, scale;
  638    int i;
  639 
  640    m0 = abs(mincolor[2] - 128);
  641    m1 = abs(mincolor[1] - 128);
  642    m2 = abs(maxcolor[2] - 128);
  643    m3 = abs(maxcolor[1] - 128);
  644 
  645    if(m1 > m0) m0 = m1;
  646    if(m3 > m2) m2 = m3;
  647    if(m2 > m0) m0 = m2;
  648 
  649    mask0 = -(m0 <= s0);
  650    mask1 = -(m0 <= s1);
  651    scale = 1 + (1 & mask0) + (2 & mask1);
  652 
  653    mincolor[2] = (mincolor[2] - 128) * scale + 128;
  654    mincolor[1] = (mincolor[1] - 128) * scale + 128;
  655    mincolor[0] = (scale - 1) << 3;
  656 
  657    maxcolor[2] = (maxcolor[2] - 128) * scale + 128;
  658    maxcolor[1] = (maxcolor[1] - 128) * scale + 128;
  659    maxcolor[0] = (scale - 1) << 3;
  660 
  661    for(i = 0; i < 16; ++i)
  662    {
  663       block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128;
  664       block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128;
  665    }
  666 }
  667 
  668 static void inset_bbox_YCoCg(unsigned char *mincolor, unsigned char *maxcolor)
  669 {
  670    int inset[4], mini[4], maxi[4];
  671 
  672    inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1);
  673    inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1);
  674 
  675    mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT;
  676    mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT;
  677 
  678    maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT;
  679    maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT;
  680 
  681    mini[2] = (mini[2] >= 0) ? mini[2] : 0;
  682    mini[1] = (mini[1] >= 0) ? mini[1] : 0;
  683 
  684    maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255;
  685    maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255;
  686 
  687    mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5);
  688    mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6);
  689 
  690    maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5);
  691    maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6);
  692 }
  693 
  694 static void select_diagonal_YCoCg(const unsigned char *block,
  695                                   unsigned char *mincolor,
  696                                   unsigned char *maxcolor)
  697 {
  698    unsigned char mid0, mid1, side, mask, b0, b1, c0, c1;
  699    int i;
  700 
  701    mid0 = ((int)mincolor[2] + maxcolor[2] + 1) >> 1;
  702    mid1 = ((int)mincolor[1] + maxcolor[1] + 1) >> 1;
  703 
  704    side = 0;
  705    for(i = 0; i < 16; ++i)
  706    {
  707       b0 = block[i * 4 + 2] >= mid0;
  708       b1 = block[i * 4 + 1] >= mid1;
  709       side += (b0 ^ b1);
  710    }
  711 
  712    mask = -(side > 8);
  713    mask &= -(mincolor[2] != maxcolor[2]);
  714 
  715    c0 = mincolor[1];
  716    c1 = maxcolor[1];
  717 
  718    c0 ^= c1;
  719    mask &= c0;
  720    c1 ^= mask;
  721    c0 ^= c1;
  722 
  723    mincolor[1] = c0;
  724    maxcolor[1] = c1;
  725 }
  726 
  727 static void eval_colors(unsigned char color[4][3],
  728                         unsigned short c0, unsigned short c1)
  729 {
  730    unpack_rgb565(color[0], c0);
  731    unpack_rgb565(color[1], c1);
  732    if(c0 > c1)
  733    {
  734       lerp_rgb(color[2], color[0], color[1], 0x55);
  735       lerp_rgb(color[3], color[0], color[1], 0xaa);
  736    }
  737    else
  738    {
  739       color[2][0] = (color[0][0] + color[1][0]) >> 1;
  740       color[2][1] = (color[0][1] + color[1][1]) >> 1;
  741       color[2][2] = (color[0][2] + color[1][2]) >> 1;
  742 
  743       color[3][0] = color[3][1] = color[3][2] = 0;
  744    }
  745 }
  746 
  747 static void encode_color_block(unsigned char *dst,
  748                                const unsigned char *block,
  749                                int type, int dither, int dxt1_alpha)
  750 {
  751    unsigned char dblock[64], color[4][3];
  752    unsigned short min16, max16;
  753    unsigned int v, mn, mx, mask;
  754    int i, block_has_alpha = 0;
  755 
  756    /* find min/max colors, determine if alpha values present in block
  757     * (for DXT1-alpha)
  758     */
  759    mn = mx = GETL32(block);
  760    for(i = 0; i < 16; ++i)
  761    {
  762       block_has_alpha = block_has_alpha || (block[4 * i + 3] < 255);
  763       v = GETL32(&block[4 * i]);
  764       mx = MAX(mx, v);
  765       mn = MIN(mn, v);
  766    }
  767 
  768    if(mn != mx) /* block is not a solid color, continue with compression */
  769    {
  770       /* compute dithered block for PCA if desired */
  771       if(dither)
  772          dither_block(dblock, block);
  773 
  774       switch(type)
  775       {
  776          case DDS_COLOR_DISTANCE:
  777             get_min_max_colors_distance(dither ? dblock : block, &max16, &min16);
  778             break;
  779          case DDS_COLOR_LUMINANCE:
  780             get_min_max_colors_luminance(dither ? dblock : block, &max16, &min16);
  781             break;
  782          case DDS_COLOR_INSET_BBOX:
  783             get_min_max_colors_inset_bbox(dither ? dblock : block, &max16, &min16);
  784             break;
  785          default:
  786             /* pca + map along principal axis */
  787             optimize_colors_block(dither ? dblock : block, &max16, &min16);
  788             if(max16 != min16)
  789             {
  790                eval_colors(color, max16, min16);
  791                mask = match_colors_block(block, color, dither != 0);
  792             }
  793             else
  794                mask = 0;
  795 
  796             /* refine */
  797             refine_block(dither ? dblock : block, &max16, &min16, mask);
  798             break;
  799       }
  800 
  801       if(max16 != min16)
  802       {
  803          eval_colors(color, max16, min16);
  804          mask = match_colors_block(block, color, dither != 0);
  805       }
  806       else
  807          mask = 0;
  808    }
  809    else /* constant color */
  810    {
  811       mask = 0xaaaaaaaa;
  812       max16 = (omatch5[block[2]][0] << 11) |
  813               (omatch6[block[1]][0] <<  5) |
  814               (omatch5[block[0]][0]      );
  815       min16 = (omatch5[block[2]][1] << 11) |
  816               (omatch6[block[1]][1] <<  5) |
  817               (omatch5[block[0]][1]      );
  818    }
  819 
  820    /* HACK! for DXT1 blocks which have non-opaque pixels */
  821    if(dxt1_alpha && block_has_alpha)
  822    {
  823       if(max16 > min16)
  824       {
  825          max16 ^= min16; min16 ^= max16; max16 ^= min16;
  826       }
  827       eval_colors(color, max16, min16);
  828       mask = match_colors_block_DXT1alpha(block, color);
  829    }
  830 
  831    if(max16 < min16 && !(dxt1_alpha && block_has_alpha))
  832    {
  833       max16 ^= min16; min16 ^= max16; max16 ^= min16;
  834       mask ^= 0x55555555;
  835    }
  836 
  837    PUTL16(&dst[0], max16);
  838    PUTL16(&dst[2], min16);
  839    PUTL32(&dst[4], mask);
  840 }
  841 
  842 /* write DXT3 alpha block */
  843 static void encode_alpha_block_DXT3(unsigned char *dst,
  844                                     const unsigned char *block)
  845 {
  846    int i, a1, a2;
  847 
  848    block += 3;
  849 
  850    for(i = 0; i < 8; ++i)
  851    {
  852       a1 = block[8 * i + 0];
  853       a2 = block[8 * i + 4];
  854       *dst++ = ((a2 >> 4) << 4) | (a1 >> 4);
  855    }
  856 }
  857 
  858 /* Write DXT5 alpha block */
  859 static void encode_alpha_block_DXT5(unsigned char *dst,
  860                                     const unsigned char *block,
  861                                     const int offset)
  862 {
  863    int i, v, mn, mx;
  864    int dist, bias, dist2, dist4, bits, mask;
  865    int a, idx, t;
  866 
  867    block += offset;
  868    block += 3;
  869 
  870    /* find min/max alpha pair */
  871    mn = mx = block[0];
  872    for(i = 0; i < 16; ++i)
  873    {
  874       v = block[4 * i];
  875       if(v > mx) mx = v;
  876       if(v < mn) mn = v;
  877    }
  878 
  879    /* encode them */
  880    *dst++ = mx;
  881    *dst++ = mn;
  882 
  883    /* determine bias and emit indices */
  884    dist = mx - mn;
  885    bias = mn * 7 - (dist >> 1);
  886    dist4 = dist * 4;
  887    dist2 = dist * 2;
  888    bits = 0;
  889    mask = 0;
  890 
  891    for(i = 0; i < 16; ++i)
  892    {
  893       a = block[4 * i] * 7 - bias;
  894 
  895       /* select index (hooray for bit magic) */
  896       t = (dist4 - a) >> 31; idx =  t & 4; a -= dist4 & t;
  897       t = (dist2 - a) >> 31; idx += t & 2; a -= dist2 & t;
  898       t = (dist  - a) >> 31; idx += t & 1;
  899 
  900       idx = -idx & 7;
  901       idx ^= (2 > idx);
  902 
  903       /* write index */
  904       mask |= idx << bits;
  905       if((bits += 3) >= 8)
  906       {
  907          *dst++ = mask;
  908          mask >>= 8;
  909          bits -= 8;
  910       }
  911    }
  912 }
  913 
  914 static void compress_DXT1(unsigned char *dst, const unsigned char *src,
  915                           int w, int h, int type, int dither, int alpha)
  916 {
  917    unsigned char block[64];
  918    int x, y;
  919 
  920    for(y = 0; y < h; y += 4)
  921    {
  922       for(x = 0; x < w; x += 4)
  923       {
  924          extract_block(src, x, y, w, h, block);
  925          encode_color_block(dst, block, type, dither, alpha);
  926          dst += 8;
  927       }
  928    }
  929 }
  930 
  931 static void compress_DXT3(unsigned char *dst, const unsigned char *src,
  932                           int w, int h, int type, int dither)
  933 {
  934    unsigned char block[64];
  935    int x, y;
  936 
  937    for(y = 0; y < h; y += 4)
  938    {
  939       for(x = 0; x < w; x += 4)
  940       {
  941          extract_block(src, x, y, w, h, block);
  942          encode_alpha_block_DXT3(dst, block);
  943          encode_color_block(dst + 8, block, type, dither, 0);
  944          dst += 16;
  945       }
  946    }
  947 }
  948 
  949 static void compress_DXT5(unsigned char *dst, const unsigned char *src,
  950                           int w, int h, int type, int dither)
  951 {
  952    unsigned char block[64];
  953    int x, y;
  954 
  955    for(y = 0; y < h; y += 4)
  956    {
  957       for(x = 0; x < w; x += 4)
  958       {
  959          extract_block(src, x, y, w, h, block);
  960          encode_alpha_block_DXT5(dst, block, 0);
  961          encode_color_block(dst + 8, block, type, dither, 0);
  962          dst += 16;
  963       }
  964    }
  965 }
  966 
  967 static void compress_BC4(unsigned char *dst, const unsigned char *src,
  968                          int w, int h)
  969 {
  970    unsigned char block[64];
  971    int x, y;
  972 
  973    for(y = 0; y < h; y += 4)
  974    {
  975       for(x = 0; x < w; x += 4)
  976       {
  977          extract_block(src, x, y, w, h, block);
  978          encode_alpha_block_DXT5(dst, block, -1);
  979          dst += 8;
  980       }
  981    }
  982 }
  983 
  984 static void compress_BC5(unsigned char *dst, const unsigned char *src,
  985                          int w, int h)
  986 {
  987    unsigned char block[64];
  988    int x, y;
  989 
  990    for(y = 0; y < h; y += 4)
  991    {
  992       for(x = 0; x < w; x += 4)
  993       {
  994          extract_block(src, x, y, w, h, block);
  995          encode_alpha_block_DXT5(dst, block, -2);
  996          encode_alpha_block_DXT5(dst + 8, block, -1);
  997          dst += 16;
  998       }
  999    }
 1000 }
 1001 
 1002 static void compress_YCoCg(unsigned char *dst, const unsigned char *src,
 1003                            int w, int h)
 1004 {
 1005    unsigned char block[64], colors[4][3];
 1006    unsigned char *maxcolor, *mincolor;
 1007    unsigned int mask;
 1008    int c0, c1, d0, d1, d2, d3;
 1009    int b0, b1, b2, b3, b4;
 1010    int x0, x1, x2;
 1011    int x, y, i;
 1012 
 1013    for(y = 0; y < h; y += 4)
 1014    {
 1015       for(x = 0; x < w; x += 4)
 1016       {
 1017          extract_block(src, x, y, w, h, block);
 1018 
 1019          encode_alpha_block_DXT5(dst, block, 0);
 1020 
 1021          maxcolor = &colors[0][0];
 1022          mincolor = &colors[1][0];
 1023 
 1024          get_min_max_YCoCg(block, mincolor, maxcolor);
 1025          scale_YCoCg(block, mincolor, maxcolor);
 1026          inset_bbox_YCoCg(mincolor, maxcolor);
 1027          select_diagonal_YCoCg(block, mincolor, maxcolor);
 1028 
 1029          lerp_rgb(&colors[2][0], maxcolor, mincolor, 0x55);
 1030          lerp_rgb(&colors[3][0], maxcolor, mincolor, 0xaa);
 1031 
 1032          mask = 0;
 1033 
 1034          for(i = 15; i >= 0; --i)
 1035          {
 1036             c0 = block[4 * i + 2];
 1037             c1 = block[4 * i + 1];
 1038 
 1039             d0 = abs(colors[0][2] - c0) + abs(colors[0][1] - c1);
 1040             d1 = abs(colors[1][2] - c0) + abs(colors[1][1] - c1);
 1041             d2 = abs(colors[2][2] - c0) + abs(colors[2][1] - c1);
 1042             d3 = abs(colors[3][2] - c0) + abs(colors[3][1] - c1);
 1043 
 1044             b0 = d0 > d3;
 1045             b1 = d1 > d2;
 1046             b2 = d0 > d2;
 1047             b3 = d1 > d3;
 1048             b4 = d2 > d3;
 1049 
 1050             x0 = b1 & b2;
 1051             x1 = b0 & b3;
 1052             x2 = b0 & b4;
 1053 
 1054             mask <<= 2;
 1055             mask |= (x1 | ((x0 | x1) << 1));
 1056          }
 1057 
 1058          PUTL16(&dst[ 8], pack_rgb565(maxcolor));
 1059          PUTL16(&dst[10], pack_rgb565(mincolor));
 1060          PUTL32(&dst[12], mask);
 1061 
 1062          dst += 16;
 1063       }
 1064    }
 1065 }
 1066 
 1067 int dxt_compress(unsigned char *dst, unsigned char *src, int format,
 1068                  unsigned int width, unsigned int height, int bpp,
 1069                  int mipmaps, int type, int dither, int filter)
 1070 {
 1071    int i, size, w, h;
 1072    unsigned int offset;
 1073    unsigned char *tmp;
 1074    int j;
 1075    unsigned char *tmp2, *s;
 1076    int dxt1_alpha = 0;
 1077 
 1078    if(!(IS_MUL4(width) && IS_MUL4(height)))
 1079       return(0);
 1080 
 1081    if((mipmaps > 1) && !(IS_POW2(width) && IS_POW2(height)))
 1082       return(0);
 1083 
 1084    size = get_mipmapped_size(width, height, bpp, 0, mipmaps,
 1085                              DDS_COMPRESS_NONE);
 1086    tmp = g_malloc(size);
 1087    generate_mipmaps(tmp, src, width, height, bpp, 0, mipmaps, filter);
 1088 
 1089    if(bpp == 4 && format == DDS_COMPRESS_BC1)
 1090       dxt1_alpha = 1;
 1091 
 1092    if(bpp == 1)
 1093    {
 1094       /* grayscale promoted to BGRA */
 1095 
 1096       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1097                                 DDS_COMPRESS_NONE);
 1098       tmp2 = g_malloc(size);
 1099 
 1100       for(i = j = 0; j < size; ++i, j += 4)
 1101       {
 1102          tmp2[j + 0] = tmp[i];
 1103          tmp2[j + 1] = tmp[i];
 1104          tmp2[j + 2] = tmp[i];
 1105          tmp2[j + 3] = 255;
 1106       }
 1107 
 1108       g_free(tmp);
 1109       tmp = tmp2;
 1110       bpp = 4;
 1111    }
 1112    else if(bpp == 2)
 1113    {
 1114       /* gray-alpha promoted to BGRA */
 1115 
 1116       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1117                                 DDS_COMPRESS_NONE);
 1118       tmp2 = g_malloc(size);
 1119 
 1120       for(i = j = 0; j < size; i += 2, j += 4)
 1121       {
 1122          tmp2[j + 0] = tmp[i];
 1123          tmp2[j + 1] = tmp[i];
 1124          tmp2[j + 2] = tmp[i];
 1125          tmp2[j + 3] = tmp[i + 1];
 1126       }
 1127 
 1128       g_free(tmp);
 1129       tmp = tmp2;
 1130       bpp = 4;
 1131    }
 1132    else if(bpp == 3)
 1133    {
 1134       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
 1135                                 DDS_COMPRESS_NONE);
 1136       tmp2 = g_malloc(size);
 1137 
 1138       for(i = j = 0; j < size; i += 3, j += 4)
 1139       {
 1140          tmp2[j + 0] = tmp[i + 0];
 1141          tmp2[j + 1] = tmp[i + 1];
 1142          tmp2[j + 2] = tmp[i + 2];
 1143          tmp2[j + 3] = 255;
 1144       }
 1145 
 1146       g_free(tmp);
 1147       tmp = tmp2;
 1148       bpp = 4;
 1149    }
 1150 
 1151    offset = 0;
 1152    w = width;
 1153    h = height;
 1154    s = tmp;
 1155 
 1156    for(i = 0; i < mipmaps; ++i)
 1157    {
 1158       switch(format)
 1159       {
 1160          case DDS_COMPRESS_BC1:
 1161             compress_DXT1(dst + offset, s, w, h, type, dither, dxt1_alpha);
 1162             break;
 1163          case DDS_COMPRESS_BC2:
 1164             compress_DXT3(dst + offset, s, w, h, type, dither);
 1165             break;
 1166          case DDS_COMPRESS_BC3:
 1167             compress_DXT5(dst + offset, s, w, h, type, dither);
 1168             break;
 1169          case DDS_COMPRESS_BC4:
 1170             compress_BC4(dst + offset, s, w, h);
 1171             break;
 1172          case DDS_COMPRESS_BC5:
 1173             compress_BC5(dst + offset, s, w, h);
 1174             break;
 1175          case DDS_COMPRESS_YCOCGS:
 1176             compress_YCoCg(dst + offset, s, w, h);
 1177             break;
 1178          default:
 1179             compress_DXT5(dst + offset, s, w, h, type, dither);
 1180             break;
 1181       }
 1182       s += (w * h * bpp);
 1183       offset += get_mipmapped_size(w, h, 0, 0, 1, format);
 1184       w = MAX(1, w >> 1);
 1185       h = MAX(1, h >> 1);
 1186    }
 1187 
 1188    g_free(tmp);
 1189 
 1190    return(1);
 1191 }
 1192 
 1193 static void decode_color_block(unsigned char *dst, unsigned char *src,
 1194                                int w, int h, int rowbytes, int format)
 1195 {
 1196    int i, x, y;
 1197    unsigned int indexes, idx;
 1198    unsigned char *d;
 1199    unsigned char colors[4][3];
 1200    unsigned short c0, c1;
 1201 
 1202    c0 = GETL16(&src[0]);
 1203    c1 = GETL16(&src[2]);
 1204 
 1205    unpack_rgb565(colors[0], c0);
 1206    unpack_rgb565(colors[1], c1);
 1207 
 1208    if((c0 > c1) || (format == DDS_COMPRESS_BC3))
 1209    {
 1210       lerp_rgb(colors[2], colors[0], colors[1], 0x55);
 1211       lerp_rgb(colors[3], colors[0], colors[1], 0xaa);
 1212    }
 1213    else
 1214    {
 1215       for(i = 0; i < 3; ++i)
 1216       {
 1217          colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1;
 1218          colors[3][i] = 255;
 1219       }
 1220    }
 1221 
 1222    src += 4;
 1223    for(y = 0; y < h; ++y)
 1224    {
 1225       d = dst + (y * rowbytes);
 1226       indexes = src[y];
 1227       for(x = 0; x < w; ++x)
 1228       {
 1229          idx = indexes & 0x03;
 1230          d[0] = colors[idx][2];
 1231          d[1] = colors[idx][1];
 1232          d[2] = colors[idx][0];
 1233          if(format == DDS_COMPRESS_BC1)
 1234             d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255;
 1235          indexes >>= 2;
 1236          d += 4;
 1237       }
 1238    }
 1239 }
 1240 
 1241 static void decode_alpha_block_DXT3(unsigned char *dst, unsigned char *src,
 1242                                     int w, int h, int rowbytes)
 1243 {
 1244    int x, y;
 1245    unsigned char *d;
 1246    unsigned int bits;
 1247 
 1248    for(y = 0; y < h; ++y)
 1249    {
 1250       d = dst + (y * rowbytes);
 1251       bits = GETL16(&src[2 * y]);
 1252       for(x = 0; x < w; ++x)
 1253       {
 1254          d[0] = (bits & 0x0f) * 17;
 1255          bits >>= 4;
 1256          d += 4;
 1257       }
 1258    }
 1259 }
 1260 
 1261 static void decode_alpha_block_DXT5(unsigned char *dst, unsigned char *src,
 1262                                     int w, int h, int bpp, int rowbytes)
 1263 {
 1264    int x, y, code;
 1265    unsigned char *d;
 1266    unsigned char a0 = src[0];
 1267    unsigned char a1 = src[1];
 1268    unsigned long long bits = GETL64(src) >> 16;
 1269 
 1270    for(y = 0; y < h; ++y)
 1271    {
 1272       d = dst + (y * rowbytes);
 1273       for(x = 0; x < w; ++x)
 1274       {
 1275          code = ((unsigned int)bits) & 0x07;
 1276          if(code == 0)
 1277             d[0] = a0;
 1278          else if(code == 1)
 1279             d[0] = a1;
 1280          else if(a0 > a1)
 1281             d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7;
 1282          else if(code >= 6)
 1283             d[0] = (code == 6) ? 0 : 255;
 1284          else
 1285             d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5;
 1286          bits >>= 3;
 1287          d += bpp;
 1288       }
 1289       if(w < 4) bits >>= (3 * (4 - w));
 1290    }
 1291 }
 1292 
 1293 int dxt_decompress(unsigned char *dst, unsigned char *src, int format,
 1294                    unsigned int size, unsigned int width, unsigned int height,
 1295                    int bpp)
 1296 {
 1297    unsigned char *d, *s;
 1298    unsigned int x, y, sx, sy;
 1299 
 1300    if(!(IS_MUL4(width) && IS_MUL4(height)))
 1301       return(0);
 1302 
 1303    sx = (width  < 4) ? width  : 4;
 1304    sy = (height < 4) ? height : 4;
 1305 
 1306    s = src;
 1307 
 1308    for(y = 0; y < height; y += 4)
 1309    {
 1310       for(x = 0; x < width; x += 4)
 1311       {
 1312          d = dst + (y * width + x) * bpp;
 1313          if(format == DDS_COMPRESS_BC1)
 1314          {
 1315             decode_color_block(d, s, sx, sy, width * bpp, format);
 1316             s += 8;
 1317          }
 1318          else if(format == DDS_COMPRESS_BC2)
 1319          {
 1320             decode_alpha_block_DXT3(d + 3, s, sx, sy, width * bpp);
 1321             s += 8;
 1322             decode_color_block(d, s, sx, sy, width * bpp, format);
 1323             s += 8;
 1324          }
 1325          else if(format == DDS_COMPRESS_BC3)
 1326          {
 1327             decode_alpha_block_DXT5(d + 3, s, sx, sy, bpp, width * bpp);
 1328             s += 8;
 1329             decode_color_block(d, s, sx, sy, width * bpp, format);
 1330             s += 8;
 1331          }
 1332          else if(format == DDS_COMPRESS_BC4)
 1333          {
 1334             decode_alpha_block_DXT5(d, s, sx, sy, bpp, width * bpp);
 1335             s += 8;
 1336          }
 1337          else if(format == DDS_COMPRESS_BC5)
 1338          {
 1339             decode_alpha_block_DXT5(d, s + 8, sx, sy, bpp, width * bpp);
 1340             decode_alpha_block_DXT5(d + 1, s, sx, sy, bpp, width * bpp);
 1341             s += 16;
 1342          }
 1343       }
 1344    }
 1345 
 1346    return(1);
 1347 }

ViewVC Help
Powered by ViewVC 1.0.4