- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-ILU/src/ilu_scaling.c

    00001 // http://www.cse.ucsc.edu/~pang/160/f98/Gems/GemsIII/
    00002
    00003 /*
    00004  *              Filtered Image Rescaling
    00005  *
    00006  *                by Dale Schumacher
    00007  */
    00008
    00009 #if 0
    00010
    00011 #include "ilu_internal.h"
    00012
    00013 char _Copyright[] = "Public Domain 1991 by Dale Schumacher";
    00014
    00015 #define WHITE_PIXEL     (255)
    00016 #define BLACK_PIXEL     (0)
    00017
    00018 /*
    00019  *      generic image access and i/o support routines
    00020  */
    00021
    00022
    00023 ILubyte get_pixel(ILuint x, ILuint y)
    00024 {
    00025         Image   *im = NULL;
    00026         int             yy = -1;
    00027         Pixel   *p = NULL;
    00028
    00029         if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) {
    00030                 return(0);
    00031         }
    00032         if((im != image) || (yy != y)) {
    00033                 im = image;
    00034                 yy = y;
    00035                 p = image->data + (y * image->span);
    00036         }
    00037         return(p[x]);
    00038 }
    00039
    00040 void
    00041 get_row(row, image, y)
    00042 Pixel *row;
    00043 Image *image;
    00044 int y;
    00045 {
    00046         if((y < 0) || (y >= image->ysize)) {
    00047                 return;
    00048         }
    00049         memcpy(row,
    00050                 image->data + (y * image->span),
    00051                 (sizeof(Pixel) * image->xsize));
    00052 }
    00053
    00054 void
    00055 get_column(column, image, x)
    00056 Pixel *column;
    00057 Image *image;
    00058 int x;
    00059 {
    00060         int i, d;
    00061         Pixel *p;
    00062
    00063         if((x < 0) || (x >= image->xsize)) {
    00064                 return;
    00065         }
    00066         d = image->span;
    00067         for(i = image->ysize, p = image->data + x; i-- > 0; p += d) {
    00068                 *column++ = *p;
    00069         }
    00070 }
    00071
    00072 Pixel
    00073 put_pixel(image, x, y, data)
    00074 Image *image;
    00075 int x, y;
    00076 Pixel data;
    00077 {
    00078         Image   *im = NULL;
    00079         ILint   yy = -1;
    00080         Pixel   *p = NULL;
    00081
    00082         if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) {
    00083                 return(0);
    00084         }
    00085         if((im != image) || (yy != y)) {
    00086                 im = image;
    00087                 yy = y;
    00088                 p = image->data + (y * image->span);
    00089         }
    00090         return(p[x] = data);
    00091 }
    00092
    00093
    00094 /*
    00095  *      filter function definitions
    00096  */
    00097
    00098 #define filter_support          (1.0)
    00099
    00100 double filter( double t) {
    00101         /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
    00102         if(t < 0.0) t = -t;
    00103         if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
    00104         return(0.0);
    00105 }
    00106
    00107 #define box_support             (0.5)
    00108
    00109 double box_filter( double t) {
    00110         if((t > -0.5) && (t <= 0.5)) return(1.0);
    00111         return(0.0);
    00112 }
    00113
    00114 #define triangle_support        (1.0)
    00115
    00116 double triangle_filter( double t ) {
    00117         if(t < 0.0) t = -t;
    00118         if(t < 1.0) return(1.0 - t);
    00119         return(0.0);
    00120 }
    00121
    00122 #define bell_support            (1.5)
    00123
    00124 double bell_filter( double t) {         /* box (*) box (*) box */
    00125         if(t < 0) t = -t;
    00126         if(t < .5) return(.75 - (t * t));
    00127         if(t < 1.5) {
    00128                 t = (t - 1.5);
    00129                 return(.5 * (t * t));
    00130         }
    00131         return(0.0);
    00132 }
    00133
    00134 #define B_spline_support        (2.0)
    00135
    00136 double
    00137 B_spline_filter(t)      /* box (*) box (*) box (*) box */
    00138 double t;
    00139 {
    00140         double tt;
    00141
    00142         if(t < 0) t = -t;
    00143         if(t < 1) {
    00144                 tt = t * t;
    00145                 return((.5 * tt * t) - tt + (2.0 / 3.0));
    00146         } else if(t < 2) {
    00147                 t = 2 - t;
    00148                 return((1.0 / 6.0) * (t * t * t));
    00149         }
    00150         return(0.0);
    00151 }
    00152
    00153 double
    00154 sinc(x)
    00155 double x;
    00156 {
    00157         x *= IL_PI;
    00158         if(x != 0) return(sin(x) / x);
    00159         return(1.0);
    00160 }
    00161
    00162 #define Lanczos3_support        (3.0)
    00163
    00164 double
    00165 Lanczos3_filter(t)
    00166 double t;
    00167 {
    00168         if(t < 0) t = -t;
    00169         if(t < 3.0) return(sinc(t) * sinc(t/3.0));
    00170         return(0.0);
    00171 }
    00172
    00173 #define Mitchell_support        (2.0)
    00174
    00175 #define B       (1.0 / 3.0)
    00176 #define C       (1.0 / 3.0)
    00177
    00178 double
    00179 Mitchell_filter(t)
    00180 double t;
    00181 {
    00182         double tt;
    00183
    00184         tt = t * t;
    00185         if(t < 0) t = -t;
    00186         if(t < 1.0) {
    00187                 t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
    00188                    + ((-18.0 + 12.0 * B + 6.0 * C) * tt)
    00189                    + (6.0 - 2 * B));
    00190                 return(t / 6.0);
    00191         } else if(t < 2.0) {
    00192                 t = (((-1.0 * B - 6.0 * C) * (t * tt))
    00193                    + ((6.0 * B + 30.0 * C) * tt)
    00194                    + ((-12.0 * B - 48.0 * C) * t)
    00195                    + (8.0 * B + 24 * C));
    00196                 return(t / 6.0);
    00197         }
    00198         return(0.0);
    00199 }
    00200
    00201 /*
    00202  *      image rescaling routine
    00203  */
    00204
    00205 typedef struct {
    00206         int     pixel;
    00207         double  weight;
    00208 } CONTRIB;
    00209
    00210 typedef struct {
    00211         int     n;              /* number of contributors */
    00212         CONTRIB *p;             /* pointer to list of contributions */
    00213 } CLIST;
    00214
    00215 CLIST   *contrib;               /* array of contribution lists */
    00216
    00217 void
    00218 zoom(dst, src, filterf, fwidth)
    00219 Image *dst;                             /* destination image structure */
    00220 Image *src;                             /* source image structure */
    00221 double (*filterf)();                    /* filter function */
    00222 double fwidth;                          /* filter width (support) */
    00223 {
    00224         Image *tmp;                     /* intermediate image */
    00225         double xscale, yscale;          /* zoom scale factors */
    00226         int i, j, k;                    /* loop variables */
    00227         int n;                          /* pixel number */
    00228         double center, left, right;     /* filter calculation variables */
    00229         double width, fscale, weight;   /* filter calculation variables */
    00230         Pixel *raster;                  /* a row or column of pixels */
    00231
    00232         /* create intermediate image to hold horizontal zoom */
    00233         tmp = new_image(dst->xsize, src->ysize);
    00234         xscale = (double) dst->xsize / (double) src->xsize;
    00235         yscale = (double) dst->ysize / (double) src->ysize;
    00236
    00237         /* pre-calculate filter contributions for a row */
    00238         contrib = (CLIST*)icalloc(dst->xsize, sizeof(CLIST));
    00239         if(xscale < 1.0) {
    00240                 width = fwidth / xscale;
    00241                 fscale = 1.0 / xscale;
    00242                 for(i = 0; i < dst->xsize; ++i) {
    00243                         contrib[i].n = 0;
    00244                         contrib[i].p = (CONTRIB*)icalloc((int) (width * 2 + 1),
    00245                                         sizeof(CONTRIB));
    00246                         center = (double) i / xscale;
    00247                         left = ceil(center - width);
    00248                         right = floor(center + width);
    00249                         for(j = left; j <= right; ++j) {
    00250                                 weight = center - (double) j;
    00251                                 weight = (*filterf)(weight / fscale) / fscale;
    00252                                 if(j < 0) {
    00253                                         n = -j;
    00254                                 } else if(j >= src->xsize) {
    00255                                         n = (src->xsize - j) + src->xsize - 1;
    00256                                 } else {
    00257                                         n = j;
    00258                                 }
    00259                                 k = contrib[i].n++;
    00260                                 contrib[i].p[k].pixel = n;
    00261                                 contrib[i].p[k].weight = weight;
    00262                         }
    00263                 }
    00264         } else {
    00265                 for(i = 0; i < dst->xsize; ++i) {
    00266                         contrib[i].n = 0;
    00267                         contrib[i].p = (CONTRIB*)icalloc((int) (fwidth * 2 + 1), sizeof(CONTRIB));
    00268                         center = (double) i / xscale;
    00269                         left = ceil(center - fwidth);
    00270                         right = floor(center + fwidth);
    00271                         for(j = left; j <= right; ++j) {
    00272                                 weight = center - (double) j;
    00273                                 weight = (*filterf)(weight);
    00274                                 if(j < 0) {
    00275                                         n = -j;
    00276                                 } else if(j >= src->xsize) {
    00277                                         n = (src->xsize - j) + src->xsize - 1;
    00278                                 } else {
    00279                                         n = j;
    00280                                 }
    00281                                 k = contrib[i].n++;
    00282                                 contrib[i].p[k].pixel = n;
    00283                                 contrib[i].p[k].weight = weight;
    00284                         }
    00285                 }
    00286         }
    00287
    00288         /* apply filter to zoom horizontally from src to tmp */
    00289         raster = (Pixel*)icalloc(src->xsize, sizeof(Pixel));
    00290         for(k = 0; k < tmp->ysize; ++k) {
    00291                 get_row(raster, src, k);
    00292                 for(i = 0; i < tmp->xsize; ++i) {
    00293                         weight = 0.0;
    00294                         for(j = 0; j < contrib[i].n; ++j) {
    00295                                 weight += raster[contrib[i].p[j].pixel]
    00296                                         * contrib[i].p[j].weight;
    00297                         }
    00298                         put_pixel(tmp, i, k,
    00299                                 (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));
    00300                 }
    00301         }
    00302         ifree(raster);
    00303
    00304         /* free the memory allocated for horizontal filter weights */
    00305         for(i = 0; i < tmp->xsize; ++i) {
    00306                 ifree(contrib[i].p);
    00307         }
    00308         ifree(contrib);
    00309
    00310         /* pre-calculate filter contributions for a column */
    00311         contrib = (CLIST*)icalloc(dst->ysize, sizeof(CLIST));
    00312         if(yscale < 1.0) {
    00313                 width = fwidth / yscale;
    00314                 fscale = 1.0 / yscale;
    00315                 for(i = 0; i < dst->ysize; ++i) {
    00316                         contrib[i].n = 0;
    00317                         contrib[i].p = (CONTRIB*)icalloc((int) (width * 2 + 1), sizeof(CONTRIB));
    00318                         center = (double) i / yscale;
    00319                         left = ceil(center - width);
    00320                         right = floor(center + width);
    00321                         for(j = left; j <= right; ++j) {
    00322                                 weight = center - (double) j;
    00323                                 weight = (*filterf)(weight / fscale) / fscale;
    00324                                 if(j < 0) {
    00325                                         n = -j;
    00326                                 } else if(j >= tmp->ysize) {
    00327                                         n = (tmp->ysize - j) + tmp->ysize - 1;
    00328                                 } else {
    00329                                         n = j;
    00330                                 }
    00331                                 k = contrib[i].n++;
    00332                                 contrib[i].p[k].pixel = n;
    00333                                 contrib[i].p[k].weight = weight;
    00334                         }
    00335                 }
    00336         } else {
    00337                 for(i = 0; i < dst->ysize; ++i) {
    00338                         contrib[i].n = 0;
    00339                         contrib[i].p = (CONTRIB*)icalloc((int) (fwidth * 2 + 1),
    00340                                         sizeof(CONTRIB));
    00341                         center = (double) i / yscale;
    00342                         left = ceil(center - fwidth);
    00343                         right = floor(center + fwidth);
    00344                         for(j = left; j <= right; ++j) {
    00345                                 weight = center - (double) j;
    00346                                 weight = (*filterf)(weight);
    00347                                 if(j < 0) {
    00348                                         n = -j;
    00349                                 } else if(j >= tmp->ysize) {
    00350                                         n = (tmp->ysize - j) + tmp->ysize - 1;
    00351                                 } else {
    00352                                         n = j;
    00353                                 }
    00354                                 k = contrib[i].n++;
    00355                                 contrib[i].p[k].pixel = n;
    00356                                 contrib[i].p[k].weight = weight;
    00357                         }
    00358                 }
    00359         }
    00360
    00361         /* apply filter to zoom vertically from tmp to dst */
    00362         raster = (Pixel*)icalloc(tmp->ysize, sizeof(Pixel));
    00363         for(k = 0; k < dst->xsize; ++k) {
    00364                 get_column(raster, tmp, k);
    00365                 for(i = 0; i < dst->ysize; ++i) {
    00366                         weight = 0.0;
    00367                         for(j = 0; j < contrib[i].n; ++j) {
    00368                                 weight += raster[contrib[i].p[j].pixel]
    00369                                         * contrib[i].p[j].weight;
    00370                         }
    00371                         put_pixel(dst, k, i,
    00372                                 (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));
    00373                 }
    00374         }
    00375         ifree(raster);
    00376
    00377         /* free the memory allocated for vertical filter weights */
    00378         for(i = 0; i < dst->ysize; ++i) {
    00379                 ifree(contrib[i].p);
    00380         }
    00381         ifree(contrib);
    00382
    00383         free_image(tmp);
    00384 }
    00385
    00386 /*
    00387  *      command line interface
    00388  */
    00389
    00390 void
    00391 usage()
    00392 {
    00393         fprintf(stderr, "usage: %s [-options] input.bm output.bm\n", _Program);
    00394         fprintf(stderr, "\
    00395 options:\n\
    00396         -x xsize                output x size\n\
    00397         -y ysize                output y size\n\
    00398         -f filter               filter type\n\
    00399 {b=box, t=triangle, q=bell, B=B-spline, h=hermite, l=Lanczos3, m=Mitchell}\n\
    00400 ");
    00401         exit(1);
    00402 }
    00403
    00404
    00405 main(argc, argv)
    00406 int argc;
    00407 char *argv[];
    00408 {
    00409         register int c;
    00410         int optind;
    00411         char *optarg;
    00412         int xsize = 0, ysize = 0;
    00413         double (*f)() = filter;
    00414         double s = filter_support;
    00415         char *dstfile, *srcfile;
    00416         Image *dst, *src;
    00417         FILE *fp;
    00418
    00419         while((c = getopt(argc, argv, "x:y:f:V")) != EOF) {
    00420                 switch(c) {
    00421                 case 'x': xsize = atoi(optarg); break;
    00422                 case 'y': ysize = atoi(optarg); break;
    00423                 case 'f':
    00424                         switch(*optarg) {
    00425                         case 'b': f=box_filter; s=box_support; break;
    00426                         case 't': f=triangle_filter; s=triangle_support; break;
    00427                         case 'q': f=bell_filter; s=bell_support; break;
    00428                         case 'B': f=B_spline_filter; s=B_spline_support; break;
    00429                         case 'h': f=filter; s=filter_support; break;
    00430                         case 'l': f=Lanczos3_filter; s=Lanczos3_support; break;
    00431                         case 'm': f=Mitchell_filter; s=Mitchell_support; break;
    00432                         default: usage();
    00433                         }
    00434                         break;
    00435                 case 'V': banner(); exit(EXIT_SUCCESS);
    00436                 case '?': usage();
    00437                 default:  usage();
    00438                 }
    00439         }
    00440         if((argc - optind) != 2) usage();
    00441         srcfile = argv[optind];
    00442         dstfile = argv[optind + 1];
    00443         if(((fp = fopen(srcfile, "r")) == NULL)
    00444         || ((src = load_image(fp)) == NULL)) {
    00445                 fprintf(stderr, "%s: can't load source image '%s'\n",
    00446                         _Program, srcfile);
    00447                 exit(EXIT_FAILURE);
    00448         }
    00449         fclose(fp);
    00450         if(xsize <= 0) xsize = src->xsize;
    00451         if(ysize <= 0) ysize = src->ysize;
    00452         dst = new_image(xsize, ysize);
    00453         zoom(dst, src, f, s);
    00454         if(((fp = fopen(dstfile, "w")) == NULL)
    00455         || (save_image(fp, dst) != 0)) {
    00456                 fprintf(stderr, "%s: can't save destination image '%s'\n",
    00457                         _Program, dstfile);
    00458                 exit(EXIT_FAILURE);
    00459         }
    00460         fclose(fp);
    00461         exit(EXIT_SUCCESS);
    00462 }
    00463
    00464 #endif
    00465
    00466