[gimp-dds] / tags / release-2.0.4 / mipmap.c Repository:
ViewVC logotype

View of /tags/release-2.0.4/mipmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 109 - (download) (as text) (annotate)
Thu May 8 05:16:35 2008 UTC (18 months, 2 weeks ago) by cocidius
File size: 18249 byte(s)
Fixing a boo-boo part 2/2
    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 #include <string.h>
   24 #include <math.h>
   25 
   26 #include "dds.h"
   27 #include "mipmap.h"
   28 #include "imath.h"
   29 
   30 typedef void (*mipmapfunc_t)(unsigned char *, int, int, unsigned char *, int, int, int);
   31 typedef void (*volmipmapfunc_t)(unsigned char *, int, int, int, unsigned char *, int, int, int, int);
   32 
   33 int get_num_mipmaps(int width, int height)
   34 {
   35    int w = width << 1;
   36    int h = height << 1;
   37    int n = 0;
   38 
   39    while(w != 1 || h != 1)
   40    {
   41       if(w > 1) w >>= 1;
   42       if(h > 1) h >>= 1;
   43       ++n;
   44    }
   45 
   46    return(n);
   47 }
   48 
   49 unsigned int get_mipmapped_size(int width, int height, int bpp,
   50                                 int level, int num, int format)
   51 {
   52    int w, h, n = 0;
   53    unsigned int size = 0;
   54 
   55    w = width >> level;
   56    h = height >> level;
   57    if(w == 0) w = 1;
   58    if(h == 0) h = 1;
   59    w <<= 1;
   60    h <<= 1;
   61 
   62    while(n < num && (w != 1 || h != 1))
   63    {
   64       if(w > 1) w >>= 1;
   65       if(h > 1) h >>= 1;
   66       if(format == DDS_COMPRESS_NONE)
   67          size += (w * h);
   68       else
   69          size += ((w + 3) >> 2) * ((h + 3) >> 2);
   70       ++n;
   71    }
   72 
   73    if(format == DDS_COMPRESS_NONE)
   74       size *= bpp;
   75    else
   76    {
   77       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
   78          size *= 8;
   79       else
   80          size *= 16;
   81    }
   82 
   83    return(size);
   84 }
   85 
   86 unsigned int get_volume_mipmapped_size(int width, int height,
   87                                        int depth, int bpp, int level,
   88                                        int num, int format)
   89 {
   90    int w, h, d, n = 0;
   91    unsigned int size = 0;
   92 
   93    w = width >> level;
   94    h = height >> level;
   95    d = depth >> level;
   96    if(w == 0) w = 1;
   97    if(h == 0) h = 1;
   98    if(d == 0) d = 1;
   99    w <<= 1;
  100    h <<= 1;
  101    d <<= 1;
  102 
  103    while(n < num && (w != 1 || h != 1))
  104    {
  105       if(w > 1) w >>= 1;
  106       if(h > 1) h >>= 1;
  107       if(d > 1) d >>= 1;
  108       if(format == DDS_COMPRESS_NONE)
  109          size += (w * h * d);
  110       else
  111          size += (((w + 3) >> 2) * ((h + 3) >> 2) * d);
  112       ++n;
  113    }
  114 
  115    if(format == DDS_COMPRESS_NONE)
  116       size *= bpp;
  117    else
  118    {
  119       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  120          size *= 8;
  121       else
  122          size *= 16;
  123    }
  124 
  125    return(size);
  126 }
  127 
  128 static void scale_image_nearest(unsigned char *dst, int dw, int dh,
  129                                 unsigned char *src, int sw, int sh,
  130                                 int bpp)
  131 {
  132    int n, x, y;
  133    int ix, iy;
  134    int srowbytes = sw * bpp;
  135    int drowbytes = dw * bpp;
  136 
  137    for(y = 0; y < dh; ++y)
  138    {
  139       iy = (y * sh + sh / 2) / dh;
  140       for(x = 0; x < dw; ++x)
  141       {
  142          ix = (x * sw + sw / 2) / dw;
  143          for(n = 0; n < bpp; ++n)
  144          {
  145             dst[y * drowbytes + (x * bpp) + n] =
  146                src[iy * srowbytes + (ix * bpp) + n];
  147          }
  148       }
  149    }
  150 }
  151 
  152 static void scale_image_bilinear(unsigned char *dst, int dw, int dh,
  153                                  unsigned char *src, int sw, int sh,
  154                                  int bpp)
  155 {
  156    int x, y, n, ix, iy, wx, wy, v, v0, v1;
  157    int dstride = dw * bpp;
  158    unsigned char *s;
  159 
  160    for(y = 0; y < dh; ++y)
  161    {
  162       if(dh > 1)
  163       {
  164          iy = (((sh - 1) * y) << 8) / (dh - 1);
  165          if(y == dh - 1) --iy;
  166          wy = iy & 0xff;
  167          iy >>= 8;
  168       }
  169       else
  170          iy = wy = 0;
  171 
  172       for(x = 0; x < dw; ++x)
  173       {
  174          if(dw > 1)
  175          {
  176             ix = (((sw - 1) * x) << 8) / (dw - 1);
  177             if(x == dw - 1) --ix;
  178             wx = ix & 0xff;
  179             ix >>= 8;
  180          }
  181          else
  182             ix = wx = 0;
  183 
  184          s = src + (iy * sw + ix) * bpp;
  185 
  186          for(n = 0; n < bpp; ++n)
  187          {
  188             v0 = blerp(s[0], s[bpp], wx);
  189             v1 = blerp(s[sw * bpp], s[(sw + 1) * bpp], wx);
  190             v = blerp(v0, v1, wy);
  191             if(v < 0) v = 0;
  192             if(v > 255) v = 255;
  193             dst[(y * dstride) + (x * bpp) + n] = v;
  194             ++s;
  195          }
  196       }
  197    }
  198 }
  199 
  200 static void scale_image_bicubic(unsigned char *dst, int dw, int dh,
  201                                 unsigned char *src, int sw, int sh,
  202                                 int bpp)
  203 {
  204    int x, y, n, ix, iy, wx, wy, v;
  205    int a, b, c, d;
  206    int dstride = dw * bpp;
  207    unsigned char *s;
  208 
  209    for(y = 0; y < dh; ++y)
  210    {
  211       if(dh > 1)
  212       {
  213          iy = (((sh - 1) * y) << 7) / (dh - 1);
  214          if(y == dh - 1) --iy;
  215          wy = iy & 0x7f;
  216          iy >>= 7;
  217       }
  218       else
  219          iy = wy = 0;
  220 
  221       for(x = 0; x < dw; ++x)
  222       {
  223          if(dw > 1)
  224          {
  225             ix = (((sw - 1) * x) << 7) / (dw - 1);
  226             if(x == dw - 1) --ix;
  227             wx = ix & 0x7f;
  228             ix >>= 7;
  229          }
  230          else
  231             ix = wx = 0;
  232 
  233          s = src + ((iy - 1) * sw + (ix - 1)) * bpp;
  234 
  235          for(n = 0; n < bpp; ++n)
  236          {
  237             b = icerp(s[(sw + 0) * bpp],
  238                       s[(sw + 1) * bpp],
  239                       s[(sw + 2) * bpp],
  240                       s[(sw + 3) * bpp], wx);
  241             if(iy > 0)
  242             {
  243                a = icerp(s[      0],
  244                          s[    bpp],
  245                          s[2 * bpp],
  246                          s[3 * bpp], wx);
  247             }
  248             else
  249                a = b;
  250 
  251             c = icerp(s[(2 * sw + 0) * bpp],
  252                       s[(2 * sw + 1) * bpp],
  253                       s[(2 * sw + 2) * bpp],
  254                       s[(2 * sw + 3) * bpp], wx);
  255             if(iy < dh - 1)
  256             {
  257                d = icerp(s[(3 * sw + 0) * bpp],
  258                          s[(3 * sw + 1) * bpp],
  259                          s[(3 * sw + 2) * bpp],
  260                          s[(3 * sw + 3) * bpp], wx);
  261             }
  262             else
  263                d = c;
  264 
  265             v = icerp(a, b, c, d, wy);
  266             if(v < 0) v = 0;
  267             if(v > 255) v = 255;
  268             dst[(y * dstride) + (x * bpp) + n] = v;
  269             ++s;
  270          }
  271       }
  272    }
  273 }
  274 
  275 int generate_mipmaps(unsigned char *dst, unsigned char *src,
  276                      unsigned int width, unsigned int height, int bpp,
  277                      int indexed, int mipmaps, int filter)
  278 {
  279    int i;
  280    unsigned int sw, sh, dw, dh;
  281    unsigned char *s, *d;
  282    mipmapfunc_t mipmap_func = NULL;
  283 
  284    if(indexed)
  285       mipmap_func = scale_image_nearest;
  286    else
  287    {
  288       switch(filter)
  289       {
  290          case DDS_MIPMAP_NEAREST:  mipmap_func = scale_image_nearest;  break;
  291          case DDS_MIPMAP_BICUBIC:  mipmap_func = scale_image_bicubic;  break;
  292          case DDS_MIPMAP_BILINEAR:
  293          default:                  mipmap_func = scale_image_bilinear; break;
  294       }
  295    }
  296 
  297    memcpy(dst, src, width * height * bpp);
  298 
  299    s = dst;
  300    d = dst + (width * height * bpp);
  301 
  302    sw = width;
  303    sh = height;
  304 
  305    for(i = 1; i < mipmaps; ++i)
  306    {
  307       dw = sw >> 1;
  308       dh = sh >> 1;
  309       if(dw < 1) dw = 1;
  310       if(dh < 1) dh = 1;
  311 
  312       mipmap_func(d, dw, dh, s, sw, sh, bpp);
  313 
  314       s = d;
  315       sw = dw;
  316       sh = dh;
  317       d += (dw * dh * bpp);
  318    }
  319 
  320    return(1);
  321 }
  322 
  323 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd,
  324                                        unsigned char *src, int sw, int sh, int sd,
  325                                        int bpp)
  326 {
  327    int n, x, y, z;
  328    int ix, iy, iz;
  329 
  330    for(z = 0; z < dd; ++z)
  331    {
  332       iz = (z * sd + sd / 2) / dd;
  333       for(y = 0; y < dh; ++y)
  334       {
  335          iy = (y * sh + sh / 2) / dh;
  336          for(x = 0; x < dw; ++x)
  337          {
  338             ix = (x * sw + sw / 2) / dw;
  339             for(n = 0; n < bpp; ++n)
  340             {
  341                dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] =
  342                   src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n];
  343             }
  344          }
  345       }
  346    }
  347 }
  348 
  349 static void scale_volume_image_bilinear(unsigned char *dst, int dw, int dh, int dd,
  350                                         unsigned char *src, int sw, int sh, int sd,
  351                                         int bpp)
  352 {
  353    int x, y, z, n, ix, iy, iz, wx, wy, wz, v, v0, v1, r0, r1;
  354    unsigned char *s1, *s2, *d = dst;
  355 
  356    for(z = 0; z < dd; ++z)
  357    {
  358       if(dd > 1)
  359       {
  360          iz = (((sd - 1) * z) << 8) / (dd - 1);
  361          if(z == dd - 1) --iz;
  362          wz = iz & 0xff;
  363          iz >>= 8;
  364       }
  365       else
  366          iz = wz = 0;
  367 
  368       for(y = 0; y < dh; ++y)
  369       {
  370          if(dh > 1)
  371          {
  372             iy = (((sh - 1) * y) << 8) / (dh - 1);
  373             if(y == dh - 1) --iy;
  374             wy = iy & 0xff;
  375             iy >>= 8;
  376          }
  377          else
  378             iy = wy = 0;
  379 
  380          for(x = 0; x < dw; ++x)
  381          {
  382             if(dw > 1)
  383             {
  384                ix = (((sw - 1) * x) << 8) / (dw - 1);
  385                if(x == dw - 1) --ix;
  386                wx = ix & 0xff;
  387                ix >>= 8;
  388             }
  389             else
  390                ix = wx = 0;
  391 
  392             s1 = src + ((iz * (sw * sh)) + (iy * sw) + ix) * bpp;
  393             s2 = src + (((iz + 1) * (sw * sh)) + (iy * sw) + ix) * bpp;
  394 
  395             for(n = 0; n < bpp; ++n)
  396             {
  397                r0 = blerp(s1[0], s1[bpp], wx);
  398                r1 = blerp(s1[sw * bpp], s1[(sw + 1) * bpp], wx);
  399                v0 = blerp(r0, r1, wy);
  400 
  401                r0 = blerp(s2[0], s2[bpp], wx);
  402                r1 = blerp(s2[sw * bpp], s2[(sw + 1) * bpp], wx);
  403                v1 = blerp(r0, r1, wy);
  404 
  405                v = blerp(v0, v1, wz);
  406                if(v < 0) v = 0;
  407                if(v > 255) v = 255;
  408                *d++ = v;
  409                ++s1;
  410                ++s2;
  411             }
  412          }
  413       }
  414    }
  415 }
  416 
  417 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd,
  418                                      unsigned char *src, int sw, int sh, int sd,
  419                                      int bpp)
  420 {
  421    int n, x, y, z;
  422    int ix, iy, iz;
  423    int wx, wy, wz;
  424    int a, b, c, d;
  425    int val, v0, v1, v2, v3;
  426    int dstride = dw * bpp;
  427    int sslice = sw * sh * bpp;
  428    int dslice = dw * dh * bpp;
  429    unsigned char *s0, *s1, *s2, *s3;
  430 
  431    for(z = 0; z < dd; ++z)
  432    {
  433       if(dd > 1)
  434       {
  435          iz = (((sd - 1) * z) << 7) / (dd - 1);
  436          if(z == dd - 1) --iz;
  437          wz = iz & 0x7f;
  438          iz >>= 7;
  439       }
  440       else
  441          iz = wz = 0;
  442 
  443       for(y = 0; y < dh; ++y)
  444       {
  445          if(dh > 1)
  446          {
  447             iy = (((sh - 1) * y) << 7) / (dh - 1);
  448             if(y == dh - 1) --iy;
  449             wy = iy & 0x7f;
  450             iy >>= 7;
  451          }
  452          else
  453             iy = wy = 0;
  454 
  455          for(x = 0; x < dw; ++x)
  456          {
  457             if(dw > 1)
  458             {
  459                ix = (((sw - 1) * x) << 7) / (dw - 1);
  460                if(x == dw - 1) --ix;
  461                wx = ix & 0x7f;
  462                ix >>= 7;
  463             }
  464             else
  465                ix = wx = 0;
  466 
  467             s0 = src + (((iz - 1) * (sw * sh)) + ((iy - 1) * sw) + (ix - 1)) * bpp;
  468             s1 = s0 + sslice;
  469             s2 = s1 + sslice;
  470             s3 = s2 + sslice;
  471 
  472             for(n = 0; n < bpp; ++n)
  473             {
  474                b = icerp(s1[(sw + 0) * bpp],
  475                          s1[(sw + 1) * bpp],
  476                          s1[(sw + 2) * bpp],
  477                          s1[(sw + 3) * bpp], wx);
  478                if(iy > 0)
  479                {
  480                   a = icerp(s1[      0],
  481                             s1[    bpp],
  482                             s1[2 * bpp],
  483                             s1[3 * bpp], wx);
  484                }
  485                else
  486                   a = b;
  487 
  488                c = icerp(s1[(2 * sw + 0) * bpp],
  489                          s1[(2 * sw + 1) * bpp],
  490                          s1[(2 * sw + 2) * bpp],
  491                          s1[(2 * sw + 3) * bpp], wx);
  492                if(iy < dh - 1)
  493                {
  494                   d = icerp(s1[(3 * sw + 0) * bpp],
  495                             s1[(3 * sw + 1) * bpp],
  496                             s1[(3 * sw + 2) * bpp],
  497                             s1[(3 * sw + 3) * bpp], wx);
  498                }
  499                else
  500                   d = c;
  501 
  502                v1 = icerp(a, b, c, d, wy);
  503 
  504                if(iz > 0)
  505                {
  506                   b = icerp(s0[(sw + 0) * bpp],
  507                             s0[(sw + 1) * bpp],
  508                             s0[(sw + 2) * bpp],
  509                             s0[(sw + 3) * bpp], wx);
  510                   if(iy > 0)
  511                   {
  512                      a = icerp(s0[      0],
  513                                s0[    bpp],
  514                                s0[2 * bpp],
  515                                s0[3 * bpp], wx);
  516                   }
  517                   else
  518                      a = b;
  519 
  520                   c = icerp(s0[(2 * sw + 0) * bpp],
  521                             s0[(2 * sw + 1) * bpp],
  522                             s0[(2 * sw + 2) * bpp],
  523                             s0[(2 * sw + 3) * bpp], wx);
  524                   if(iy < dh - 1)
  525                   {
  526                      d = icerp(s0[(3 * sw + 0) * bpp],
  527                                s0[(3 * sw + 1) * bpp],
  528                                s0[(3 * sw + 2) * bpp],
  529                                s0[(3 * sw + 3) * bpp], wx);
  530                   }
  531                   else
  532                      d = c;
  533 
  534                   v0 = icerp(a, b, c, d, wy);
  535                }
  536                else
  537                   v0 = v1;
  538 
  539                b = icerp(s2[(sw + 0) * bpp],
  540                          s2[(sw + 1) * bpp],
  541                          s2[(sw + 2) * bpp],
  542                          s2[(sw + 3) * bpp], wx);
  543                if(iy > 0)
  544                {
  545                   a = icerp(s2[      0],
  546                             s2[    bpp],
  547                             s2[2 * bpp],
  548                             s2[3 * bpp], wx);
  549                }
  550                else
  551                   a = b;
  552 
  553                c = icerp(s2[(2 * sw + 0) * bpp],
  554                          s2[(2 * sw + 1) * bpp],
  555                          s2[(2 * sw + 2) * bpp],
  556                          s2[(2 * sw + 3) * bpp], wx);
  557                if(iy < dh - 1)
  558                {
  559                   d = icerp(s2[(3 * sw + 0) * bpp],
  560                             s2[(3 * sw + 1) * bpp],
  561                             s2[(3 * sw + 2) * bpp],
  562                             s2[(3 * sw + 3) * bpp], wx);
  563                }
  564                else
  565                   d = c;
  566 
  567                v2 = icerp(a, b, c, d, wy);
  568 
  569                if(iz < dd - 1)
  570                {
  571                   b = icerp(s3[(sw + 0) * bpp],
  572                             s3[(sw + 1) * bpp],
  573                             s3[(sw + 2) * bpp],
  574                             s3[(sw + 3) * bpp], wx);
  575                   if(iy > 0)
  576                   {
  577                      a = icerp(s3[      0],
  578                                s3[    bpp],
  579                                s3[2 * bpp],
  580                                s3[3 * bpp], wx);
  581                   }
  582                   else
  583                      a = b;
  584 
  585                   c = icerp(s3[(2 * sw + 0) * bpp],
  586                             s3[(2 * sw + 1) * bpp],
  587                             s3[(2 * sw + 2) * bpp],
  588                             s3[(2 * sw + 3) * bpp], wx);
  589                   if(iy < dh - 1)
  590                   {
  591                      d = icerp(s3[(3 * sw + 0) * bpp],
  592                                s3[(3 * sw + 1) * bpp],
  593                                s3[(3 * sw + 2) * bpp],
  594                                s3[(3 * sw + 3) * bpp], wx);
  595                   }
  596                   else
  597                      d = c;
  598 
  599                   v3 = icerp(a, b, c, d, wy);
  600                }
  601                else
  602                   v3 = v2;
  603 
  604                val = icerp(v0, v1, v2, v3, wz);
  605 
  606                if(val <   0) val = 0;
  607                if(val > 255) val = 255;
  608 
  609                dst[(z * dslice) + (y * dstride) + (x * bpp) + n] = val;
  610 
  611                ++s0;
  612                ++s1;
  613                ++s2;
  614                ++s3;
  615             }
  616          }
  617       }
  618    }
  619 }
  620 
  621 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src,
  622                             unsigned int width, unsigned int height,
  623                             unsigned int depth, int bpp, int indexed,
  624                             int mipmaps, int filter)
  625 {
  626    int i;
  627    unsigned int sw, sh, sd;
  628    unsigned int dw, dh, dd;
  629    unsigned char *s, *d;
  630    volmipmapfunc_t mipmap_func = NULL;
  631 
  632    if(indexed)
  633       mipmap_func = scale_volume_image_nearest;
  634    else
  635    {
  636       switch(filter)
  637       {
  638          case DDS_MIPMAP_NEAREST:  mipmap_func = scale_volume_image_nearest;  break;
  639          case DDS_MIPMAP_BICUBIC:  mipmap_func = scale_volume_image_cubic;    break;
  640          case DDS_MIPMAP_BILINEAR:
  641          default:                  mipmap_func = scale_volume_image_bilinear; break;
  642       }
  643    }
  644 
  645    memcpy(dst, src, width * height * depth * bpp);
  646 
  647    s = dst;
  648    d = dst + (width * height * depth * bpp);
  649 
  650    sw = width;
  651    sh = height;
  652    sd = depth;
  653 
  654    for(i = 1; i < mipmaps; ++i)
  655    {
  656       dw = sw >> 1;
  657       dh = sh >> 1;
  658       dd = sd >> 1;
  659       if(dw < 1) dw = 1;
  660       if(dh < 1) dh = 1;
  661       if(dd < 1) dd = 1;
  662 
  663       mipmap_func(d, dw, dh, dd, s, sw, sh, sd, bpp);
  664 
  665       s = d;
  666       sw = dw;
  667       sh = dh;
  668       sd = dd;
  669       d += (dw * dh * dd * bpp);
  670    }
  671 
  672    return(1);
  673 }

ViewVC Help
Powered by ViewVC 1.0.4