[gimp-dds] / tags / release-2.0.1 / dxt.c Repository:
ViewVC logotype

View of /tags/release-2.0.1/dxt.c

Parent Directory Parent Directory | Revision Log Revision Log


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

ViewVC Help
Powered by ViewVC 1.0.4