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

View of /trunk/mipmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 120 - (download) (as text) (annotate)
Tue Nov 11 19:05:16 2008 UTC (12 months, 1 week ago) by cocidius
File size: 23375 byte(s)
* Fix some gcc 4.3 warnings
* Corrected mipmap image generation for DXT compressed images when mipmap
image has a dimension smaller than 4 pixels
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004-2008 Shawn Kirst <skirst@insightbb.com>,
    5    with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
    6 
    7    This program is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU General Public
    9    License as published by the Free Software Foundation; either
   10    version 2 of the License, or (at your option) any later version.
   11 
   12    This program is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    General Public License for more details.
   16 
   17    You should have received a copy of the GNU General Public License
   18    along with this program; see the file COPYING.  If not, write to
   19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20    Boston, MA 02111-1307, USA.
   21 */
   22 
   23 #include <string.h>
   24 #include <math.h>
   25 
   26 #include <gtk/gtk.h>
   27 
   28 #include "dds.h"
   29 #include "mipmap.h"
   30 #include "imath.h"
   31 
   32 typedef void (*mipmapfunc_t)(unsigned char *, int, int, unsigned char *, int, int, int);
   33 typedef void (*volmipmapfunc_t)(unsigned char *, int, int, int, unsigned char *, int, int, int, int);
   34 
   35 int get_num_mipmaps(int width, int height)
   36 {
   37    int w = width << 1;
   38    int h = height << 1;
   39    int n = 0;
   40 
   41    while(w != 1 || h != 1)
   42    {
   43       if(w > 1) w >>= 1;
   44       if(h > 1) h >>= 1;
   45       ++n;
   46    }
   47 
   48    return(n);
   49 }
   50 
   51 unsigned int get_mipmapped_size(int width, int height, int bpp,
   52                                 int level, int num, int format)
   53 {
   54    int w, h, cw, ch, n = 0;
   55    unsigned int size = 0;
   56 
   57    w = width >> level;
   58    h = height >> level;
   59    w = MAX(1, w);
   60    h = MAX(1, h);
   61    w <<= 1;
   62    h <<= 1;
   63 
   64    while(n < num && (w != 1 || h != 1))
   65    {
   66       if(w > 1) w >>= 1;
   67       if(h > 1) h >>= 1;
   68       if(format == DDS_COMPRESS_NONE)
   69          size += (w * h);
   70       else
   71       {
   72          cw = MAX(w, 4);
   73          ch = MAX(h, 4);
   74          size += ((cw + 3) >> 2) * ((ch + 3) >> 2);
   75       }
   76       ++n;
   77    }
   78 
   79    if(format == DDS_COMPRESS_NONE)
   80       size *= bpp;
   81    else
   82    {
   83       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
   84          size *= 8;
   85       else
   86          size *= 16;
   87    }
   88 
   89    return(size);
   90 }
   91 
   92 unsigned int get_volume_mipmapped_size(int width, int height,
   93                                        int depth, int bpp, int level,
   94                                        int num, int format)
   95 {
   96    int w, h, d, n = 0;
   97    unsigned int size = 0;
   98 
   99    w = width >> level;
  100    h = height >> level;
  101    d = depth >> level;
  102    w = MAX(1, w);
  103    h = MAX(1, h);
  104    d = MAX(1, d);
  105    w <<= 1;
  106    h <<= 1;
  107    d <<= 1;
  108 
  109    while(n < num && (w != 1 || h != 1))
  110    {
  111       if(w > 1) w >>= 1;
  112       if(h > 1) h >>= 1;
  113       if(d > 1) d >>= 1;
  114       if(format == DDS_COMPRESS_NONE)
  115          size += (w * h * d);
  116       else
  117          size += (((w + 3) >> 2) * ((h + 3) >> 2) * d);
  118       ++n;
  119    }
  120 
  121    if(format == DDS_COMPRESS_NONE)
  122       size *= bpp;
  123    else
  124    {
  125       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  126          size *= 8;
  127       else
  128          size *= 16;
  129    }
  130 
  131    return(size);
  132 }
  133 
  134 static void scale_image_nearest(unsigned char *dst, int dw, int dh,
  135                                 unsigned char *src, int sw, int sh,
  136                                 int bpp)
  137 {
  138    int n, x, y;
  139    int ix, iy;
  140    int srowbytes = sw * bpp;
  141    int drowbytes = dw * bpp;
  142 
  143    for(y = 0; y < dh; ++y)
  144    {
  145       iy = (y * sh + sh / 2) / dh;
  146       for(x = 0; x < dw; ++x)
  147       {
  148          ix = (x * sw + sw / 2) / dw;
  149          for(n = 0; n < bpp; ++n)
  150          {
  151             dst[y * drowbytes + (x * bpp) + n] =
  152                src[iy * srowbytes + (ix * bpp) + n];
  153          }
  154       }
  155    }
  156 }
  157 
  158 static void scale_image_box(unsigned char *dst, int dw, int dh,
  159                             unsigned char *src, int sw, int sh,
  160                             int bpp)
  161 {
  162    int x, y, n, ix, iy, v;
  163    int dstride = dw * bpp;
  164    unsigned char *s;
  165 
  166    for(y = 0; y < dh; ++y)
  167    {
  168       iy = (y * sh + sh / 2) / dh;
  169 
  170       for(x = 0; x < dw; ++x)
  171       {
  172          ix = (x * sw + sh / 2) / dw;
  173 
  174          s = src + (iy * sw + ix) * bpp;
  175 
  176          for(n = 0; n < bpp; ++n)
  177          {
  178             v = (s[0] + s[bpp] + s[sw * bpp] + s[(sw + 1) * bpp]) >> 2;
  179             dst[(y * dstride) + (x * bpp) + n] = v;
  180             ++s;
  181          }
  182       }
  183    }
  184 }
  185 
  186 static void scale_image_bilinear(unsigned char *dst, int dw, int dh,
  187                                  unsigned char *src, int sw, int sh,
  188                                  int bpp)
  189 {
  190    int x, y, n, ix, iy, wx, wy, v, v0, v1;
  191    int dstride = dw * bpp;
  192    unsigned char *s;
  193 
  194    for(y = 0; y < dh; ++y)
  195    {
  196       if(dh > 1)
  197       {
  198          iy = (((sh - 1) * y) << 8) / (dh - 1);
  199          if(y == dh - 1) --iy;
  200          wy = iy & 0xff;
  201          iy >>= 8;
  202       }
  203       else
  204          iy = wy = 0;
  205 
  206       for(x = 0; x < dw; ++x)
  207       {
  208          if(dw > 1)
  209          {
  210             ix = (((sw - 1) * x) << 8) / (dw - 1);
  211             if(x == dw - 1) --ix;
  212             wx = ix & 0xff;
  213             ix >>= 8;
  214          }
  215          else
  216             ix = wx = 0;
  217 
  218          s = src + (iy * sw + ix) * bpp;
  219 
  220          for(n = 0; n < bpp; ++n)
  221          {
  222             v0 = blerp(s[0], s[bpp], wx);
  223             v1 = blerp(s[sw * bpp], s[(sw + 1) * bpp], wx);
  224             v = blerp(v0, v1, wy);
  225             if(v < 0) v = 0;
  226             if(v > 255) v = 255;
  227             dst[(y * dstride) + (x * bpp) + n] = v;
  228             ++s;
  229          }
  230       }
  231    }
  232 }
  233 
  234 static void scale_image_bicubic(unsigned char *dst, int dw, int dh,
  235                                 unsigned char *src, int sw, int sh,
  236                                 int bpp)
  237 {
  238    int x, y, n, ix, iy, wx, wy, v;
  239    int a, b, c, d;
  240    int dstride = dw * bpp;
  241    unsigned char *s;
  242 
  243    for(y = 0; y < dh; ++y)
  244    {
  245       if(dh > 1)
  246       {
  247          iy = (((sh - 1) * y) << 7) / (dh - 1);
  248          if(y == dh - 1) --iy;
  249          wy = iy & 0x7f;
  250          iy >>= 7;
  251       }
  252       else
  253          iy = wy = 0;
  254 
  255       for(x = 0; x < dw; ++x)
  256       {
  257          if(dw > 1)
  258          {
  259             ix = (((sw - 1) * x) << 7) / (dw - 1);
  260             if(x == dw - 1) --ix;
  261             wx = ix & 0x7f;
  262             ix >>= 7;
  263          }
  264          else
  265             ix = wx = 0;
  266 
  267          s = src + ((iy - 1) * sw + (ix - 1)) * bpp;
  268 
  269          for(n = 0; n < bpp; ++n)
  270          {
  271             b = icerp(s[(sw + 0) * bpp],
  272                       s[(sw + 1) * bpp],
  273                       s[(sw + 2) * bpp],
  274                       s[(sw + 3) * bpp], wx);
  275             if(iy > 0)
  276             {
  277                a = icerp(s[      0],
  278                          s[    bpp],
  279                          s[2 * bpp],
  280                          s[3 * bpp], wx);
  281             }
  282             else
  283                a = b;
  284 
  285             c = icerp(s[(2 * sw + 0) * bpp],
  286                       s[(2 * sw + 1) * bpp],
  287                       s[(2 * sw + 2) * bpp],
  288                       s[(2 * sw + 3) * bpp], wx);
  289             if(iy < dh - 1)
  290             {
  291                d = icerp(s[(3 * sw + 0) * bpp],
  292                          s[(3 * sw + 1) * bpp],
  293                          s[(3 * sw + 2) * bpp],
  294                          s[(3 * sw + 3) * bpp], wx);
  295             }
  296             else
  297                d = c;
  298 
  299             v = icerp(a, b, c, d, wy);
  300             if(v < 0) v = 0;
  301             if(v > 255) v = 255;
  302             dst[(y * dstride) + (x * bpp) + n] = v;
  303             ++s;
  304          }
  305       }
  306    }
  307 }
  308 
  309 static const float FILTER_RADIUS = 5.0f;
  310 
  311 static float lanczos(float r, float x)
  312 {
  313    float t;
  314    if(x == 0.0f) return(1.0f);
  315    if(x <= -r || x >= r) return(0.0f);
  316    t = x * M_PI;
  317    return(r * sinf(t) * sinf(t / r) / (t * t));
  318 }
  319 
  320 static void scale_image_lanczos(unsigned char *dst, int dw, int dh,
  321                                 unsigned char *src, int sw, int sh,
  322                                 int bpp)
  323 {
  324    const float blur = 1.0f;
  325    const float xfactor = (float)dw / (float)sw;
  326    const float yfactor = (float)dh / (float)sh;
  327 
  328    int x, y, start, stop, nmax, n, i;
  329    int sstride = sw * bpp;
  330    float center, contrib, density, s, r;
  331 
  332    unsigned char *d, *row, *col;
  333 
  334    float xscale = MIN(xfactor, 1.0f) / blur;
  335    float yscale = MIN(yfactor, 1.0f) / blur;
  336    float xsupport = FILTER_RADIUS / xscale;
  337    float ysupport = FILTER_RADIUS / yscale;
  338 
  339    if(xsupport <= 0.5f)
  340    {
  341       xsupport = 0.5f + 1e-12f;
  342       xscale = 1.0f;
  343    }
  344    if(ysupport <= 0.5f)
  345    {
  346       ysupport = 0.5f + 1e-12f;
  347       yscale = 1.0f;
  348    }
  349 
  350    /* resample in Y direction first to temporary buffer */
  351    unsigned char *tmp;
  352 
  353    tmp = g_malloc(sw * dh * bpp);
  354    d = tmp;
  355 
  356    for(y = 0; y < dh; ++y)
  357    {
  358       for(x = 0; x < sw; ++x)
  359       {
  360          col = src + (x * bpp);
  361 
  362          center = ((float)y + 0.5f) / yfactor;
  363          start = (int)MAX(center - ysupport + 0.5f, 0);
  364          stop = (int)MIN(center + ysupport + 0.5f, sh);
  365          nmax = stop - start;
  366          s = (float)start - center + 0.5f;
  367 
  368          for(i = 0; i < bpp; ++i)
  369          {
  370             density = 0.0f;
  371             r = 0.0f;
  372 
  373             for(n = 0; n < nmax; ++n)
  374             {
  375                contrib = lanczos(FILTER_RADIUS, (s + n) * yscale);
  376                density += contrib;
  377                r += (float)col[((start + n) * sstride) + i] * contrib;
  378             }
  379 
  380             if(density != 0.0f && density != 1.0f)
  381                r /= density;
  382 
  383             if(r < 0) r = 0;
  384             if(r > 255) r = 255;
  385 
  386             *d++ = (unsigned char)r;
  387          }
  388       }
  389    }
  390 
  391    /* resample temp buffer in X direction */
  392 
  393    d = dst;
  394 
  395    for(y = 0; y < dh; ++y)
  396    {
  397       row = tmp + (y * sstride);
  398 
  399       for(x = 0; x < dw; ++x)
  400       {
  401          center = ((float)x + 0.5f) / xfactor;
  402          start = (int)MAX(center - xsupport + 0.5f, 0);
  403          stop = (int)MIN(center + xsupport + 0.5f, sw);
  404          nmax = stop - start;
  405          s = (float)start - center + 0.5f;
  406 
  407          for(i = 0; i < bpp; ++i)
  408          {
  409             density = 0.0f;
  410             r = 0.0f;
  411 
  412             for(n = 0; n < nmax; ++n)
  413             {
  414                contrib = lanczos(FILTER_RADIUS, (s + n) * xscale);
  415                density += contrib;
  416                r += (float)row[((start + n) * bpp) + i] * contrib;
  417             }
  418 
  419             if(density != 0.0f && density != 1.0f)
  420                r /= density;
  421 
  422             if(r < 0) r = 0;
  423             if(r > 255) r = 255;
  424 
  425             *d++ = (unsigned char)r;
  426          }
  427       }
  428    }
  429 
  430    g_free(tmp);
  431 }
  432 
  433 int generate_mipmaps(unsigned char *dst, unsigned char *src,
  434                      unsigned int width, unsigned int height, int bpp,
  435                      int indexed, int mipmaps, int filter)
  436 {
  437    int i;
  438    unsigned int sw, sh, dw, dh;
  439    unsigned char *s, *d;
  440    mipmapfunc_t mipmap_func = NULL;
  441 
  442    if(indexed)
  443       mipmap_func = scale_image_nearest;
  444    else
  445    {
  446       switch(filter)
  447       {
  448          case DDS_MIPMAP_NEAREST:  mipmap_func = scale_image_nearest;  break;
  449          case DDS_MIPMAP_BILINEAR: mipmap_func = scale_image_bilinear; break;
  450          case DDS_MIPMAP_BICUBIC:  mipmap_func = scale_image_bicubic;  break;
  451          case DDS_MIPMAP_LANCZOS:  mipmap_func = scale_image_lanczos;  break;
  452          case DDS_MIPMAP_BOX:
  453          default:                  mipmap_func = scale_image_box;      break;
  454       }
  455    }
  456 
  457    memcpy(dst, src, width * height * bpp);
  458 
  459    s = dst;
  460    d = dst + (width * height * bpp);
  461 
  462    sw = width;
  463    sh = height;
  464 
  465    for(i = 1; i < mipmaps; ++i)
  466    {
  467       dw = MAX(1, sw >> 1);
  468       dh = MAX(1, sh >> 1);
  469 
  470       mipmap_func(d, dw, dh, s, sw, sh, bpp);
  471 
  472       s = d;
  473       sw = dw;
  474       sh = dh;
  475       d += (dw * dh * bpp);
  476    }
  477 
  478    return(1);
  479 }
  480 
  481 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd,
  482                                        unsigned char *src, int sw, int sh, int sd,
  483                                        int bpp)
  484 {
  485    int n, x, y, z;
  486    int ix, iy, iz;
  487 
  488    for(z = 0; z < dd; ++z)
  489    {
  490       iz = (z * sd + sd / 2) / dd;
  491       for(y = 0; y < dh; ++y)
  492       {
  493          iy = (y * sh + sh / 2) / dh;
  494          for(x = 0; x < dw; ++x)
  495          {
  496             ix = (x * sw + sw / 2) / dw;
  497             for(n = 0; n < bpp; ++n)
  498             {
  499                dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] =
  500                   src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n];
  501             }
  502          }
  503       }
  504    }
  505 }
  506 
  507 static void scale_volume_image_box(unsigned char *dst, int dw, int dh, int dd,
  508                                    unsigned char *src, int sw, int sh, int sd,
  509                                    int bpp)
  510 {
  511    int n, x, y, z, v;
  512    int ix, iy, iz;
  513    unsigned char *s1, *s2, *d = dst;
  514 
  515    for(z = 0; z < dd; ++z)
  516    {
  517       iz = (z * sd + sd / 2) / dd;
  518       for(y = 0; y < dh; ++y)
  519       {
  520          iy = (y * sh + sh / 2) / dh;
  521          for(x = 0; x < dw; ++x)
  522          {
  523             ix = (x * sw + sw / 2) / dw;
  524 
  525             s1 = src + ((iz * (sw * sh)) + (iy * sw) + ix) * bpp;
  526             if(iz < dd - 1)
  527                s2 = src + (((iz + 1) * (sw * sh)) + (iy * sw) + ix) * bpp;
  528             else
  529                s2 = src;
  530 
  531             for(n = 0; n < bpp; ++n)
  532             {
  533                v =
  534                   ((s1[0] + s1[bpp] + s1[sw * bpp] + s1[(sw + 1) * bpp]) +
  535                    (s2[0] + s2[bpp] + s2[sw * bpp] + s2[(sw + 1) * bpp])) >> 3;
  536                *d++ = v;
  537                ++s1;
  538                ++s2;
  539             }
  540          }
  541       }
  542    }
  543 }
  544 
  545 static void scale_volume_image_bilinear(unsigned char *dst, int dw, int dh, int dd,
  546                                         unsigned char *src, int sw, int sh, int sd,
  547                                         int bpp)
  548 {
  549    int x, y, z, n, ix, iy, iz, wx, wy, wz, v, v0, v1, r0, r1;
  550    unsigned char *s1, *s2, *d = dst;
  551 
  552    for(z = 0; z < dd; ++z)
  553    {
  554       if(dd > 1)
  555       {
  556          iz = (((sd - 1) * z) << 8) / (dd - 1);
  557          if(z == dd - 1) --iz;
  558          wz = iz & 0xff;
  559          iz >>= 8;
  560       }
  561       else
  562          iz = wz = 0;
  563 
  564       for(y = 0; y < dh; ++y)
  565       {
  566          if(dh > 1)
  567          {
  568             iy = (((sh - 1) * y) << 8) / (dh - 1);
  569             if(y == dh - 1) --iy;
  570             wy = iy & 0xff;
  571             iy >>= 8;
  572          }
  573          else
  574             iy = wy = 0;
  575 
  576          for(x = 0; x < dw; ++x)
  577          {
  578             if(dw > 1)
  579             {
  580                ix = (((sw - 1) * x) << 8) / (dw - 1);
  581                if(x == dw - 1) --ix;
  582                wx = ix & 0xff;
  583                ix >>= 8;
  584             }
  585             else
  586                ix = wx = 0;
  587 
  588             s1 = src + ((iz * (sw * sh)) + (iy * sw) + ix) * bpp;
  589             s2 = src + (((iz + 1) * (sw * sh)) + (iy * sw) + ix) * bpp;
  590 
  591             for(n = 0; n < bpp; ++n)
  592             {
  593                r0 = blerp(s1[0], s1[bpp], wx);
  594                r1 = blerp(s1[sw * bpp], s1[(sw + 1) * bpp], wx);
  595                v0 = blerp(r0, r1, wy);
  596 
  597                r0 = blerp(s2[0], s2[bpp], wx);
  598                r1 = blerp(s2[sw * bpp], s2[(sw + 1) * bpp], wx);
  599                v1 = blerp(r0, r1, wy);
  600 
  601                v = blerp(v0, v1, wz);
  602                if(v < 0) v = 0;
  603                if(v > 255) v = 255;
  604                *d++ = v;
  605                ++s1;
  606                ++s2;
  607             }
  608          }
  609       }
  610    }
  611 }
  612 
  613 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd,
  614                                      unsigned char *src, int sw, int sh, int sd,
  615                                      int bpp)
  616 {
  617    int n, x, y, z;
  618    int ix, iy, iz;
  619    int wx, wy, wz;
  620    int a, b, c, d;
  621    int val, v0, v1, v2, v3;
  622    int dstride = dw * bpp;
  623    int sslice = sw * sh * bpp;
  624    int dslice = dw * dh * bpp;
  625    unsigned char *s0, *s1, *s2, *s3;
  626 
  627    for(z = 0; z < dd; ++z)
  628    {
  629       if(dd > 1)
  630       {
  631          iz = (((sd - 1) * z) << 7) / (dd - 1);
  632          if(z == dd - 1) --iz;
  633          wz = iz & 0x7f;
  634          iz >>= 7;
  635       }
  636       else
  637          iz = wz = 0;
  638 
  639       for(y = 0; y < dh; ++y)
  640       {
  641          if(dh > 1)
  642          {
  643             iy = (((sh - 1) * y) << 7) / (dh - 1);
  644             if(y == dh - 1) --iy;
  645             wy = iy & 0x7f;
  646             iy >>= 7;
  647          }
  648          else
  649             iy = wy = 0;
  650 
  651          for(x = 0; x < dw; ++x)
  652          {
  653             if(dw > 1)
  654             {
  655                ix = (((sw - 1) * x) << 7) / (dw - 1);
  656                if(x == dw - 1) --ix;
  657                wx = ix & 0x7f;
  658                ix >>= 7;
  659             }
  660             else
  661                ix = wx = 0;
  662 
  663             s0 = src + (((iz - 1) * (sw * sh)) + ((iy - 1) * sw) + (ix - 1)) * bpp;
  664             s1 = s0 + sslice;
  665             s2 = s1 + sslice;
  666             s3 = s2 + sslice;
  667 
  668             for(n = 0; n < bpp; ++n)
  669             {
  670                b = icerp(s1[(sw + 0) * bpp],
  671                          s1[(sw + 1) * bpp],
  672                          s1[(sw + 2) * bpp],
  673                          s1[(sw + 3) * bpp], wx);
  674                if(iy > 0)
  675                {
  676                   a = icerp(s1[      0],
  677                             s1[    bpp],
  678                             s1[2 * bpp],
  679                             s1[3 * bpp], wx);
  680                }
  681                else
  682                   a = b;
  683 
  684                c = icerp(s1[(2 * sw + 0) * bpp],
  685                          s1[(2 * sw + 1) * bpp],
  686                          s1[(2 * sw + 2) * bpp],
  687                          s1[(2 * sw + 3) * bpp], wx);
  688                if(iy < dh - 1)
  689                {
  690                   d = icerp(s1[(3 * sw + 0) * bpp],
  691                             s1[(3 * sw + 1) * bpp],
  692                             s1[(3 * sw + 2) * bpp],
  693                             s1[(3 * sw + 3) * bpp], wx);
  694                }
  695                else
  696                   d = c;
  697 
  698                v1 = icerp(a, b, c, d, wy);
  699 
  700                if(iz > 0)
  701                {
  702                   b = icerp(s0[(sw + 0) * bpp],
  703                             s0[(sw + 1) * bpp],
  704                             s0[(sw + 2) * bpp],
  705                             s0[(sw + 3) * bpp], wx);
  706                   if(iy > 0)
  707                   {
  708                      a = icerp(s0[      0],
  709                                s0[    bpp],
  710                                s0[2 * bpp],
  711                                s0[3 * bpp], wx);
  712                   }
  713                   else
  714                      a = b;
  715 
  716                   c = icerp(s0[(2 * sw + 0) * bpp],
  717                             s0[(2 * sw + 1) * bpp],
  718                             s0[(2 * sw + 2) * bpp],
  719                             s0[(2 * sw + 3) * bpp], wx);
  720                   if(iy < dh - 1)
  721                   {
  722                      d = icerp(s0[(3 * sw + 0) * bpp],
  723                                s0[(3 * sw + 1) * bpp],
  724                                s0[(3 * sw + 2) * bpp],
  725                                s0[(3 * sw + 3) * bpp], wx);
  726                   }
  727                   else
  728                      d = c;
  729 
  730                   v0 = icerp(a, b, c, d, wy);
  731                }
  732                else
  733                   v0 = v1;
  734 
  735                b = icerp(s2[(sw + 0) * bpp],
  736                          s2[(sw + 1) * bpp],
  737                          s2[(sw + 2) * bpp],
  738                          s2[(sw + 3) * bpp], wx);
  739                if(iy > 0)
  740                {
  741                   a = icerp(s2[      0],
  742                             s2[    bpp],
  743                             s2[2 * bpp],
  744                             s2[3 * bpp], wx);
  745                }
  746                else
  747                   a = b;
  748 
  749                c = icerp(s2[(2 * sw + 0) * bpp],
  750                          s2[(2 * sw + 1) * bpp],
  751                          s2[(2 * sw + 2) * bpp],
  752                          s2[(2 * sw + 3) * bpp], wx);
  753                if(iy < dh - 1)
  754                {
  755                   d = icerp(s2[(3 * sw + 0) * bpp],
  756                             s2[(3 * sw + 1) * bpp],
  757                             s2[(3 * sw + 2) * bpp],
  758                             s2[(3 * sw + 3) * bpp], wx);
  759                }
  760                else
  761                   d = c;
  762 
  763                v2 = icerp(a, b, c, d, wy);
  764 
  765                if(iz < dd - 1)
  766                {
  767                   b = icerp(s3[(sw + 0) * bpp],
  768                             s3[(sw + 1) * bpp],
  769                             s3[(sw + 2) * bpp],
  770                             s3[(sw + 3) * bpp], wx);
  771                   if(iy > 0)
  772                   {
  773                      a = icerp(s3[      0],
  774                                s3[    bpp],
  775                                s3[2 * bpp],
  776                                s3[3 * bpp], wx);
  777                   }
  778                   else
  779                      a = b;
  780 
  781                   c = icerp(s3[(2 * sw + 0) * bpp],
  782                             s3[(2 * sw + 1) * bpp],
  783                             s3[(2 * sw + 2) * bpp],
  784                             s3[(2 * sw + 3) * bpp], wx);
  785                   if(iy < dh - 1)
  786                   {
  787                      d = icerp(s3[(3 * sw + 0) * bpp],
  788                                s3[(3 * sw + 1) * bpp],
  789                                s3[(3 * sw + 2) * bpp],
  790                                s3[(3 * sw + 3) * bpp], wx);
  791                   }
  792                   else
  793                      d = c;
  794 
  795                   v3 = icerp(a, b, c, d, wy);
  796                }
  797                else
  798                   v3 = v2;
  799 
  800                val = icerp(v0, v1, v2, v3, wz);
  801 
  802                if(val <   0) val = 0;
  803                if(val > 255) val = 255;
  804 
  805                dst[(z * dslice) + (y * dstride) + (x * bpp) + n] = val;
  806 
  807                ++s0;
  808                ++s1;
  809                ++s2;
  810                ++s3;
  811             }
  812          }
  813       }
  814    }
  815 }
  816 
  817 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src,
  818                             unsigned int width, unsigned int height,
  819                             unsigned int depth, int bpp, int indexed,
  820                             int mipmaps, int filter)
  821 {
  822    int i;
  823    unsigned int sw, sh, sd;
  824    unsigned int dw, dh, dd;
  825    unsigned char *s, *d;
  826    volmipmapfunc_t mipmap_func = NULL;
  827 
  828    if(indexed)
  829       mipmap_func = scale_volume_image_nearest;
  830    else
  831    {
  832       switch(filter)
  833       {
  834          case DDS_MIPMAP_NEAREST:  mipmap_func = scale_volume_image_nearest;  break;
  835          case DDS_MIPMAP_BILINEAR: mipmap_func = scale_volume_image_bilinear; break;
  836          case DDS_MIPMAP_BICUBIC:  mipmap_func = scale_volume_image_cubic;    break;
  837          case DDS_MIPMAP_BOX:
  838          default:
  839                                    mipmap_func = scale_volume_image_box;      break;
  840       }
  841    }
  842 
  843    memcpy(dst, src, width * height * depth * bpp);
  844 
  845    s = dst;
  846    d = dst + (width * height * depth * bpp);
  847 
  848    sw = width;
  849    sh = height;
  850    sd = depth;
  851 
  852    for(i = 1; i < mipmaps; ++i)
  853    {
  854       dw = MAX(1, sw >> 1);
  855       dh = MAX(1, sh >> 1);
  856       dd = MAX(1, sd >> 1);
  857 
  858       mipmap_func(d, dw, dh, dd, s, sw, sh, sd, bpp);
  859 
  860       s = d;
  861       sw = dw;
  862       sh = dh;
  863       sd = dd;
  864       d += (dw * dh * dd * bpp);
  865    }
  866 
  867    return(1);
  868 }

ViewVC Help
Powered by ViewVC 1.0.4