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

View of /tags/release-2.0.1/mipmap.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: 14267 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 <string.h>
   24 #include <math.h>
   25 
   26 #include "dds.h"
   27 #include "mipmap.h"
   28 
   29 int get_num_mipmaps(int width, int height)
   30 {
   31    int w = width << 1;
   32    int h = height << 1;
   33    int n = 0;
   34 
   35    while(w != 1 || h != 1)
   36    {
   37       if(w > 1) w >>= 1;
   38       if(h > 1) h >>= 1;
   39       ++n;
   40    }
   41 
   42    return(n);
   43 }
   44 
   45 unsigned int get_mipmapped_size(int width, int height, int bpp,
   46                                 int level, int num, int format)
   47 {
   48    int w, h, n = 0;
   49    unsigned int size = 0;
   50 
   51    w = width >> level;
   52    h = height >> level;
   53    if(w == 0) w = 1;
   54    if(h == 0) h = 1;
   55    w <<= 1;
   56    h <<= 1;
   57 
   58    while(n < num && (w != 1 || h != 1))
   59    {
   60       if(w > 1) w >>= 1;
   61       if(h > 1) h >>= 1;
   62       if(format == DDS_COMPRESS_NONE)
   63          size += (w * h);
   64       else
   65          size += ((w + 3) >> 2) * ((h + 3) >> 2);
   66       ++n;
   67    }
   68 
   69    if(format == DDS_COMPRESS_NONE)
   70       size *= bpp;
   71    else
   72    {
   73       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
   74          size *= 8;
   75       else
   76          size *= 16;
   77    }
   78 
   79    return(size);
   80 }
   81 
   82 unsigned int get_volume_mipmapped_size(int width, int height,
   83                                        int depth, int bpp, int level,
   84                                        int num, int format)
   85 {
   86    int w, h, d, n = 0;
   87    unsigned int size = 0;
   88 
   89    w = width >> level;
   90    h = height >> level;
   91    d = depth >> level;
   92    if(w == 0) w = 1;
   93    if(h == 0) h = 1;
   94    if(d == 0) d = 1;
   95    w <<= 1;
   96    h <<= 1;
   97    d <<= 1;
   98 
   99    while(n < num && (w != 1 || h != 1))
  100    {
  101       if(w > 1) w >>= 1;
  102       if(h > 1) h >>= 1;
  103       if(d > 1) d >>= 1;
  104       if(format == DDS_COMPRESS_NONE)
  105          size += (w * h * d);
  106       else
  107          size += (((w + 3) >> 2) * ((h + 3) >> 2) * d);
  108       ++n;
  109    }
  110 
  111    if(format == DDS_COMPRESS_NONE)
  112       size *= bpp;
  113    else
  114    {
  115       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  116          size *= 8;
  117       else
  118          size *= 16;
  119    }
  120 
  121    return(size);
  122 }
  123 
  124 float cubic_interpolate(float a, float b, float c, float d, float x)
  125 {
  126    float v0, v1, v2, v3, x2;
  127 
  128    x2 = x * x;
  129    v0 = d - c - a + b;
  130    v1 = a - b - v0;
  131    v2 = c - a;
  132    v3 = b;
  133 
  134    return(v0 * x * x2 + v1 * x2 + v2 * x + v3);
  135 }
  136 
  137 static void scale_image_cubic(unsigned char *dst, int dw, int dh,
  138                               unsigned char *src, int sw, int sh,
  139                               int bpp)
  140 {
  141    int n, x, y;
  142    int ix, iy;
  143    float fx, fy;
  144    float dx, dy, val;
  145    float r0, r1, r2, r3;
  146    int srowbytes = sw * bpp;
  147    int drowbytes = dw * bpp;
  148 
  149 #define VAL(x, y, c) \
  150    (float)src[((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes + \
  151               (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c]
  152 
  153    for(y = 0; y < dh; ++y)
  154    {
  155       fy = ((float)y / (float)dh) * (float)sh;
  156       iy = (int)fy;
  157       dy = fy - (float)iy;
  158       for(x = 0; x < dw; ++x)
  159       {
  160          fx = ((float)x / (float)dw) * (float)sw;
  161          ix = (int)fx;
  162          dx = fx - (float)ix;
  163 
  164          for(n = 0; n < bpp; ++n)
  165          {
  166             r0 = cubic_interpolate(VAL(ix - 1, iy - 1, n),
  167                                    VAL(ix,     iy - 1, n),
  168                                    VAL(ix + 1, iy - 1, n),
  169                                    VAL(ix + 2, iy - 1, n), dx);
  170             r1 = cubic_interpolate(VAL(ix - 1, iy,     n),
  171                                    VAL(ix,     iy,     n),
  172                                    VAL(ix + 1, iy,     n),
  173                                    VAL(ix + 2, iy,     n), dx);
  174             r2 = cubic_interpolate(VAL(ix - 1, iy + 1, n),
  175                                    VAL(ix,     iy + 1, n),
  176                                    VAL(ix + 1, iy + 1, n),
  177                                    VAL(ix + 2, iy + 1, n), dx);
  178             r3 = cubic_interpolate(VAL(ix - 1, iy + 2, n),
  179                                    VAL(ix,     iy + 2, n),
  180                                    VAL(ix + 1, iy + 2, n),
  181                                    VAL(ix + 2, iy + 2, n), dx);
  182             val = cubic_interpolate(r0, r1, r2, r3, dy);
  183             if(val <   0) val = 0;
  184             if(val > 255) val = 255;
  185             dst[y * drowbytes + (x * bpp) + n] = (unsigned char)val;
  186          }
  187       }
  188    }
  189 #undef VAL
  190 }
  191 
  192 static void scale_image_nearest(unsigned char *dst, int dw, int dh,
  193                                 unsigned char *src, int sw, int sh,
  194                                 int bpp)
  195 {
  196    int n, x, y;
  197    int ix, iy;
  198    int srowbytes = sw * bpp;
  199    int drowbytes = dw * bpp;
  200 
  201    for(y = 0; y < dh; ++y)
  202    {
  203       iy = (y * sh + sh / 2) / dh;
  204       for(x = 0; x < dw; ++x)
  205       {
  206          ix = (x * sw + sw / 2) / dw;
  207          for(n = 0; n < bpp; ++n)
  208          {
  209             dst[y * drowbytes + (x * bpp) + n] =
  210                src[iy * srowbytes + (ix * bpp) + n];
  211          }
  212       }
  213    }
  214 }
  215 
  216 int generate_mipmaps(unsigned char *dst, unsigned char *src,
  217                      unsigned int width, unsigned int height, int bpp,
  218                      int indexed, int mipmaps)
  219 {
  220    int i;
  221    unsigned int w, h;
  222    unsigned int offset;
  223 
  224    memcpy(dst, src, width * height * bpp);
  225    offset = width * height * bpp;
  226 
  227    for(i = 1; i < mipmaps; ++i)
  228    {
  229       w = width  >> i;
  230       h = height >> i;
  231       if(w < 1) w = 1;
  232       if(h < 1) h = 1;
  233 
  234       if(indexed)
  235          scale_image_nearest(dst + offset, w, h, src, width, height, bpp);
  236       else
  237          scale_image_cubic(dst + offset, w, h, src, width, height, bpp);
  238 
  239       offset += (w * h * bpp);
  240    }
  241 
  242    return(1);
  243 }
  244 
  245 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd,
  246                                      unsigned char *src, int sw, int sh, int sd,
  247                                      int bpp)
  248 {
  249    int n, x, y, z;
  250    int ix, iy, iz;
  251    float fx, fy, fz;
  252    float dx, dy, dz, val;
  253    float r0, r1, r2, r3;
  254    float v0, v1, v2, v3;
  255    int srowbytes = sw * bpp;
  256    int drowbytes = dw * bpp;
  257    int sslicebytes = sw * sh * bpp;
  258    int dslicebytes = dw * dh * bpp;
  259 
  260 #define VAL(x, y, z, c) \
  261    (float)src[(((z) < 0 ? 0 : (z) >= sd ? sd - 1 : (z)) * sslicebytes) + \
  262               (((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes) + \
  263               (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c]
  264 
  265    for(z = 0; z < dd; ++z)
  266    {
  267       fz = ((float)z / (float)dd) * (float)sd;
  268       iz = (int)fz;
  269       dz = fz - (float)iz;
  270       for(y = 0; y < dh; ++y)
  271       {
  272          fy = ((float)y / (float)dh) * (float)sh;
  273          iy = (int)fy;
  274          dy = fy - (float)iy;
  275          for(x = 0; x < dw; ++x)
  276          {
  277             fx = ((float)x / (float)dw) * (float)sw;
  278             ix = (int)fx;
  279             dx = fx - (float)ix;
  280             for(n = 0; n < bpp; ++n)
  281             {
  282                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z - 1, n),
  283                                       VAL(ix,     iy - 1, z - 1, n),
  284                                       VAL(ix + 1, iy - 1, z - 1, n),
  285                                       VAL(ix + 2, iy - 1, z - 1, n), dx);
  286                r1 = cubic_interpolate(VAL(ix - 1, iy,     z - 1, n),
  287                                       VAL(ix,     iy,     z - 1, n),
  288                                       VAL(ix + 1, iy,     z - 1, n),
  289                                       VAL(ix + 2, iy,     z - 1, n), dx);
  290                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z - 1, n),
  291                                       VAL(ix,     iy + 1, z - 1, n),
  292                                       VAL(ix + 1, iy + 1, z - 1, n),
  293                                       VAL(ix + 2, iy + 1, z - 1, n), dx);
  294                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z - 1, n),
  295                                       VAL(ix,     iy + 2, z - 1, n),
  296                                       VAL(ix + 1, iy + 2, z - 1, n),
  297                                       VAL(ix + 2, iy + 2, z - 1, n), dx);
  298                v0 = cubic_interpolate(r0, r1, r2, r3, dy);
  299 
  300                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z, n),
  301                                       VAL(ix,     iy - 1, z, n),
  302                                       VAL(ix + 1, iy - 1, z, n),
  303                                       VAL(ix + 2, iy - 1, z, n), dx);
  304                r1 = cubic_interpolate(VAL(ix - 1, iy,     z, n),
  305                                       VAL(ix,     iy,     z, n),
  306                                       VAL(ix + 1, iy,     z, n),
  307                                       VAL(ix + 2, iy,     z, n), dx);
  308                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z, n),
  309                                       VAL(ix,     iy + 1, z, n),
  310                                       VAL(ix + 1, iy + 1, z, n),
  311                                       VAL(ix + 2, iy + 1, z, n), dx);
  312                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z, n),
  313                                       VAL(ix,     iy + 2, z, n),
  314                                       VAL(ix + 1, iy + 2, z, n),
  315                                       VAL(ix + 2, iy + 2, z, n), dx);
  316                v1 = cubic_interpolate(r0, r1, r2, r3, dy);
  317 
  318                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 1, n),
  319                                       VAL(ix,     iy - 1, z + 1, n),
  320                                       VAL(ix + 1, iy - 1, z + 1, n),
  321                                       VAL(ix + 2, iy - 1, z + 1, n), dx);
  322                r1 = cubic_interpolate(VAL(ix - 1, iy,     z + 1, n),
  323                                       VAL(ix,     iy,     z + 1, n),
  324                                       VAL(ix + 1, iy,     z + 1, n),
  325                                       VAL(ix + 2, iy,     z + 1, n), dx);
  326                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 1, n),
  327                                       VAL(ix,     iy + 1, z + 1, n),
  328                                       VAL(ix + 1, iy + 1, z + 1, n),
  329                                       VAL(ix + 2, iy + 1, z + 1, n), dx);
  330                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 1, n),
  331                                       VAL(ix,     iy + 2, z + 1, n),
  332                                       VAL(ix + 1, iy + 2, z + 1, n),
  333                                       VAL(ix + 2, iy + 2, z + 1, n), dx);
  334                v2 = cubic_interpolate(r0, r1, r2, r3, dy);
  335 
  336                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 2, n),
  337                                       VAL(ix,     iy - 1, z + 2, n),
  338                                       VAL(ix + 1, iy - 1, z + 2, n),
  339                                       VAL(ix + 2, iy - 1, z + 2, n), dx);
  340                r1 = cubic_interpolate(VAL(ix - 1, iy,     z + 2, n),
  341                                       VAL(ix,     iy,     z + 2, n),
  342                                       VAL(ix + 1, iy,     z + 2, n),
  343                                       VAL(ix + 2, iy,     z + 2, n), dx);
  344                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 2, n),
  345                                       VAL(ix,     iy + 1, z + 2, n),
  346                                       VAL(ix + 1, iy + 1, z + 2, n),
  347                                       VAL(ix + 2, iy + 1, z + 2, n), dx);
  348                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 2, n),
  349                                       VAL(ix,     iy + 2, z + 2, n),
  350                                       VAL(ix + 1, iy + 2, z + 2, n),
  351                                       VAL(ix + 2, iy + 2, z + 2, n), dx);
  352                v3 = cubic_interpolate(r0, r1, r2, r3, dy);
  353 
  354                val = cubic_interpolate(v0, v1, v2, v3, dz);
  355 
  356                if(val <   0) val = 0;
  357                if(val > 255) val = 255;
  358 
  359                dst[(z * dslicebytes) + (y * drowbytes) + (x * bpp) + n] =
  360                   (unsigned char)val;
  361             }
  362          }
  363       }
  364    }
  365 #undef VAL
  366 }
  367 
  368 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd,
  369                                        unsigned char *src, int sw, int sh, int sd,
  370                                        int bpp)
  371 {
  372    int n, x, y, z;
  373    int ix, iy, iz;
  374 
  375    for(z = 0; z < dd; ++z)
  376    {
  377       iz = (z * sd + sd / 2) / dd;
  378       for(y = 0; y < dh; ++y)
  379       {
  380          iy = (y * sh + sh / 2) / dh;
  381          for(x = 0; x < dw; ++x)
  382          {
  383             ix = (x * sw + sw / 2) / dw;
  384             for(n = 0; n < bpp; ++n)
  385             {
  386                dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] =
  387                   src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n];
  388             }
  389          }
  390       }
  391    }
  392 }
  393 
  394 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src,
  395                             unsigned int width, unsigned int height,
  396                             unsigned int depth, int bpp, int indexed,
  397                             int mipmaps)
  398 {
  399    int i;
  400    unsigned int w, h, d;
  401    unsigned int offset;
  402 
  403    memcpy(dst, src, width * height * depth * bpp);
  404    offset = width * height * depth * bpp;
  405 
  406    for(i = 1; i < mipmaps; ++i)
  407    {
  408       w = width  >> i;
  409       h = height >> i;
  410       d = depth  >> i;
  411       if(w < 1) w = 1;
  412       if(h < 1) h = 1;
  413       if(d < 1) d = 1;
  414 
  415       if(indexed)
  416       {
  417          scale_volume_image_nearest(dst + offset, w, h, d, src, width, height,
  418                                     depth, bpp);
  419       }
  420       else
  421       {
  422          scale_volume_image_cubic(dst + offset, w, h, d, src, width, height,
  423                                   depth, bpp);
  424       }
  425 
  426       offset += (w * h * d * bpp);
  427    }
  428 
  429    return(1);
  430 }

ViewVC Help
Powered by ViewVC 1.0.4