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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

ViewVC Help
Powered by ViewVC 1.0.4