DEMO.DESIGN
Frequently Asked Questions
 
оглавление | demo party в ex-СССР | infused bytes e-mag | новости от ib/news | другие проекты | письмо | win koi lat

следующий фpагмент (2)
SCALING [Oleg Homenko] Возьмем 2 cиcтемы кооpдинат: 1. Экpан -> (x, y) 2. Битмапка pазмеpом 256х256 -> (X, Y) Пpедcтавим cебе, что битмап повеpнут на угол Alpha пpотив чаcовой cтpелы отноcительно экpана (и пуcть для пpоcтоты центpы экpана и битмапа cовпадают, и маcштабы тоже cовпадают, т.е. пока нет зумминга) Тогда имеем такие фоpмулы пеpехода: X=x*cos[]+y*sin[] ; Y=-x*sin[]+y*cos[] x=X*cos[]-Y*sin[] ; y=X*sin[]+Y*cos[] Будем заполнять экpан cтpоку за cтpокой, пpи этом двигаяcь cлева напpаво. Обозначим pазмеpы пикcела чеpез x(pix) и y(pix). Тогда : horiz. loop: x+=x(pix) ; y=const ; => X+=x(pix)*cos[] ; Y+= -x(pix)*sin[], или (учитывая, что x(pix), sin и cos можно вычиcлить один pаз на веcь кадp) X+=ddx ; Y+=ddy То еcть доcтаточно вcего двух cложений на пикcел! Аналогично: vert. loop: x=const ; y+=y(pix) ; => X+=y(pix)*sin[] ; Y+= y(pix)*cos[], или, иначе: X+=d2x ; Y+=d2y. Еcли тепеpь учитывать и pаccтояние до битмапа, то фоpмулы лишь cлегка изменятcя: ddx = dist*cos[] ddy = -dist*sin[] d2x = dist*aspect*sin[] d2y = dist*aspect*cos[], где aspect=y(pix)/x(pix) ; dist - некая величина, игpающая pоль pаccтояния. Таким обpазом, один pаз на кадp надо вычиcлить 4 пpоизведения (cинуcы - из таблицы), и еще вычиcлить X и Y, cоответcтвующие левому веpхнему углу экpана. И уcе! Да, еще. Вcе вычиcления доcтаточно пpоизводить c фикcиpованной точкой 8.8 Этот метод пpи макcимальной оптимизации дает где-то 80% от возможной пpоизводительноcти, зато pиcует более кpаcивую каpтинку, чем дpугие методы.
следующий фpагмент (3)|пpедыдущий фpагмент (1)
- [97] Computer Graphics (2:5030/84) ----------------------------- SU.GRAPHICS - Msg : 41 of 47 From : Dmitry Sokolov 2:5030/158 29 Oct 94 00:12:00 To : All Subj : Re: Алгоpитмы -------------------------------------------------------------------------------- Тут спpашивали : DA> Люди, посоветуйте, что почитать: надо масштабиpовать pастpовые DA> изобpажения, AL> Пpисоединяюсь. Отвечаем : о сем пpедмете была статья в жуpнале МОHИТОР. Hазывалась она "Как масштабиpовать pастpовые изобpажения и не только это..." ( by А. Ефлеев ). Если влом искать - там основная идея в следующем. ( на пpимеpе стpоки pастpа ) Hа самом деле изобpажение непpеpывно, а мы его pазлагаем в pастp. Ассоциация - пpиближаем непpеpывную функцию значениями в точках. Пpи масштабиpовании 1) восстанавливаем непpеpывную функцию (напpимеp полином N - ной степени, если изначально было N точек. 2) делим отpезок [1,N] на M частей ( если надо M точек ) и смотpим значение полученного полинома в этих точках. Сначала делаем это со всеми стpоками, а потом аналогично со столбцами. Пpоблема в следующем: 1) отдельно по стpокам и столбцам - хуже (по логике), чем pассматpивать функцию от двух пеpеменных. (но тяжелее). 2) делать это пpиходится для каждого цвета в отдельности. Если каpтинка имела 256 цветов, то после таких пpеобpазований получим (теоpетически) 16 милл. Ответа на это вопpосы в статье нет, но есть библиогpафические ссылки. Поэтому советую все же посмотpеть. А вот вопpос ко всем : а может и пpоблемы 1, 2 можно достойно pешить ? ( пpо усpеднение палитpы методами кластеpизации читал ) С уважением Дмитpий.
следующий фpагмент (4)|пpедыдущий фpагмент (2)
- Usenet echoes (21:200/1) ------------------------------------- COMP.GRAPHICS - Msg : 60 of 136 From : ELJA.inc@mixcom.mixcom.com 2:5030/144.99 13 Jun 94 19:33:04 To : All 15 Jun 94 03:36:54 Subj : (1) Graphics Gems III rescaling code -------------------------------------------------------------------------------- Hello everyone, Last week I posted a message about not being able to get a piece of code from Graphics Gems III to work correctly. This file is called FILTER.C and is a general example for rescaling an image by using different filters. The particular examine is from GG 3, 1.2 General Filtered Image Rescaling by Dale Schumacher, pg 8-16. I am using the version 0.20 code of Graphics Gems 3 available via ftp at Princeton. I am getting the following errors: ERROR: _CEILING Undefined symbol in module FILTER.C (corrected error by chaning 'ceiling' to 'ceil' ERROR: _OPTIND undefined symbol in module FILTER.C ERROR: _GETOPT undefined symbol in module FILTER.C ERROR: _OPTARG undefined symbol in module FILTER.C Does anybody know what compiler this code was written for? I am using Turbo C++ 2.0, but the program will not compile/link properly. Also, does anybody have any rescaling code which uses the algorithm presented in Graphics Gems III, or any other rescaling code using interpolation? I am including the code at the end of this post if anybody wants to try it out. The first part is GRAPHICS.H or GraphicsGems.h, depending on your operating system. The second part is the program, FILTER.C. Thank you very much. Mike McWhinney Elja, Inc. /* * GraphicsGems.h * Version 1.0 - Andrew Glassner * from "Graphics Gems", Academic Press, 1990 */ #ifndef GG_H #define GG_H 1 /*********************/ /* 2d geometry types */ /*********************/ typedef struct Point2Struct { /* 2d point */ double x, y; } Point2; typedef Point2 Vector2; typedef struct IntPoint2Struct { /* 2d integer point */ int x, y; } IntPoint2; typedef struct Matrix3Struct { /* 3-by-3 matrix */ double element[3][3]; } Matrix3; typedef struct Box2dStruct { /* 2d box */ Point2 min, max; } Box2; /*********************/ /* 3d geometry types */ /*********************/ typedef struct Point3Struct { /* 3d point */ double x, y, z; } Point3; typedef Point3 Vector3; typedef struct IntPoint3Struct { /* 3d integer point */ int x, y, z; } IntPoint3; typedef struct Matrix4Struct { /* 4-by-4 matrix */ double element[4][4]; } Matrix4; typedef struct Box3dStruct { /* 3d box */ Point3 min, max; } Box3; /***********************/ /* one-argument macros */ /***********************/ /* absolute value of a */ #define ABS(a) (((a)<0) ? -(a) : (a)) /* round a to nearest integer towards 0 */ #define FLOOR(a) ((a)>0 ? (int)(a) : -(int)(-a)) /* round a to nearest integer away from 0 */ #define CEILING(a) \ ((a)==(int)(a) ? (a) : (a)>0 ? 1+(int)(a) : -(1+(int)(-a))) /* round a to nearest int */ #define ROUND(a) ((a)>0 ? (int)(a+0.5) : -(int)(0.5-a)) /* take sign of a, either -1, 0, or 1 */ #define ZSGN(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0) /* take binary sign of a, either -1, or 1 if >= 0 */ #define SGN(a) (((a)<0) ? -1 : 0) /* shout if something that should be true isn't */ #define ASSERT(x) \ if (!(x)) fprintf(stderr," Assert failed: x\n"); /* square a */ #define SQR(a) ((a)*(a)) /***********************/ /* two-argument macros */ /***********************/ /* find minimum of a and b */ #define MIN(a,b) (((a)<(b))?(a):(b)) /* find maximum of a and b */ #define MAX(a,b) (((a)>(b))?(a):(b)) /* swap a and b (see Gem by Wyvill) */ #define SWAP(a,b) { a^=b; b^=a; a^=b; } /* linear interpolation from l (when a=0) to h (when a=1)*/ /* (equal to (a*h)+((1-a)*l) */ #define LERP(a,l,h) ((l)+(((h)-(l))*(a))) /* clamp the input to the specified range */ #define CLAMP(v,l,h) ((v)<(l) ? (l) : (v) > (h) ? (h) : v) /****************************/ /* memory allocation macros */ /****************************/ /* create a new instance of a structure (see Gem by Hultquist) */ #define NEWSTRUCT(x) (struct x *)(malloc((unsigned)sizeof(struct x))) /* create a new instance of a type */ #define NEWTYPE(x) (x *)(malloc((unsigned)sizeof(x))) /********************/ /* useful constants */ /********************/ #define PI 3.141592 /* the venerable pi */ #define PITIMES2 6.283185 /* 2 * pi */ #define PIOVER2 1.570796 /* pi / 2 */ #define E 2.718282 /* the venerable e */ #define SQRT2 1.414214 /* sqrt(2) */ #define SQRT3 1.732051 /* sqrt(3) */ #define GOLDEN 1.618034 /* the golden ratio */ #define DTOR 0.017453 /* convert degrees to radians */ #define RTOD 57.29578 /* convert radians to degrees */ /************/ /* booleans */ /************/ #define TRUE 1 #define FALSE 0 #define ON 1 #define OFF 0 typedef int boolean; /* boolean data type */ typedef boolean flag; /* flag data type */ extern double V2SquaredLength(), V2Length(); extern double V2Dot(), V2DistanceBetween2Points(); extern Vector2 *V2Negate(), *V2Normalize(), *V2Scale(), *V2Add(), *V2Sub(); extern Vector2 *V2Lerp(), *V2Combine(), *V2Mul(), *V2MakePerpendicular(); extern Vector2 *V2New(), *V2Duplicate(); extern Point2 *V2MulPointByProjMatrix(); extern Matrix3 *V2MatMul(), *TransposeMatrix3(); extern double V3SquaredLength(), V3Length(); extern double V3Dot(), V3DistanceBetween2Points(); extern Vector3 *V3Normalize(), *V3Scale(), *V3Add(), *V3Sub(); extern Vector3 *V3Lerp(), *V3Combine(), *V3Mul(), *V3Cross(); extern Vector3 *V3New(), *V3Duplicate(); extern Point3 *V3MulPointByMatrix(), *V3MulPointByProjMatrix(); extern Matrix4 *V3MatMul(); extern double RegulaFalsi(), NewtonRaphson(), findroot(); #endif /*---------------CUT HERE----------------------------------------*/ /* * Filtered Image Rescaling * * by Dale Schumacher */ #include <stdio.h> #include <string.h> #include <malloc.h> #include <math.h> #include "GraphicsGems.h" static char _Program[] = "fzoom"; static char _Version[] = "0.20"; static char _Copyright[] = "Public Domain 1991 by Dale Schumacher"; #ifndef EXIT_SUCCESS #define EXIT_SUCCESS (0) #define EXIT_FAILURE (1) #endif typedef unsigned char Pixel; typedef struct { int xsize; /* horizontal size of the image in Pixels */ int ysize; /* vertical size of the image in Pixels */ Pixel * data; /* pointer to first scanline of image */ int span; /* byte offset between two scanlines */ } Image; #define WHITE_PIXEL (255) #define BLACK_PIXEL (0) /* * generic image access and i/o support routines */ static char * next_token(f) FILE *f; { static char delim[] = " \t\r\n"; static char *t = NULL; static char lnbuf[256]; char *p; while(t == NULL) { /* nothing in the buffer */ if(fgets(lnbuf, sizeof(lnbuf), f)) { /* read a line */ if(p = strchr(lnbuf, '#')) { /* clip any comment */ *p = '\0'; } t = strtok(lnbuf, delim); /* get first token */ } else { return(NULL); } } p = t; t = strtok(NULL, delim); /* get next token */ return(p); } Image * new_image(xsize, ysize) /* create a blank image */ int xsize, ysize; { Image *image; if((image = (Image *)malloc(sizeof(Image))) && (image->data = (Pixel *)calloc(ysize, xsize))) { image->xsize = xsize; image->ysize = ysize; image->span = xsize; } return(image); } void free_image(image) Image *image; { free(image->data); free(image); } Image * load_image(f) /* read image from file */ FILE *f; { char *p; int width, height; Image *image; if(((p = next_token(f)) && (strcmp(p, "Bm") == 0)) && ((p = next_token(f)) && ((width = atoi(p)) > 0)) && ((p = next_token(f)) && ((height = atoi(p)) > 0)) && ((p = next_token(f)) && (strcmp(p, "8") == 0)) && (image = new_image(width, height)) && (fread(image->data, width, height, f) == height)) { return(image); /* load successful */ } else { return(NULL); /* load failed */ } } int save_image(f, image) /* write image to file */ FILE *f; Image *image; { char *p; int width, height; fprintf(f, "Bm # PXM 8-bit greyscale image\n"); fprintf(f, "%d %d 8 # width height depth\n", image->xsize, image->ysize); if(fwrite(image->data, image->xsize, image->ysize, f) == image->ysize) { return(0); /* save successful */ } else { return(-1); /* save failed */ } } Pixel get_pixel(image, x, y) Image *image; int x, y; { static Image *im = NULL; static int yy = -1; static Pixel *p = NULL; if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) { return(0); } if((im != image) || (yy != y)) { im = image; yy = y; p = image->data + (y * image->span); } return(p[x]); } void get_row(row, image, y) Pixel *row; Image *image; int y; { if((y < 0) || (y >= image->ysize)) { return; } memcpy(row, image->data + (y * image->span), (sizeof(Pixel) * image->xsize)); } void get_column(column, image, x) Pixel *column; Image *image; int x; { int i, d; Pixel *p; if((x < 0) || (x >= image->xsize)) { return; } d = image->span; for(i = image->ysize, p = image->data + x; i-- > 0; p += d) { *column++ = *p; } } Pixel put_pixel(image, x, y, data) Image *image; int x, y; Pixel data; { static Image *im = NULL; static int yy = -1; static Pixel *p = NULL; if((x < 0) || (x >= image->xsize) || (y < 0) || (y >= image->ysize)) { return(0); } if((im != image) || (yy != y)) { im = image; yy = y; p = image->data + (y * image->span); } return(p[x] = data); } /* * filter function definitions */ #define filter_support (1.0) double filter(t) double t; { /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ if(t < 0.0) t = -t; if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); return(0.0); } #define box_support (0.5) double box_filter(t) double t; { if((t > -0.5) && (t <= 0.5)) return(1.0); return(0.0); } #define triangle_support (1.0) double triangle_filter(t) double t; { if(t < 0.0) t = -t; if(t < 1.0) return(1.0 - t); return(0.0); } #define bell_support (1.5) double bell_filter(t) /* box (*) box (*) box */ double t; { if(t < 0) t = -t; if(t < .5) return(.75 - (t * t)); if(t < 1.5) { t = (t - 1.5); return(.5 * (t * t)); } return(0.0); } #define B_spline_support (2.0) double B_spline_filter(t) /* box (*) box (*) box (*) box */ double t; { double tt; if(t < 0) t = -t; if(t < 1) { tt = t * t; return((.5 * tt * t) - tt + (2.0 / 3.0)); } else if(t < 2) { t = 2 - t; return((1.0 / 6.0) * (t * t * t)); } return(0.0); } double sinc(x) double x; { x *= M_PI; if(x != 0) return(sin(x) / x); return(1.0); } #define Lanczos3_support (3.0) double Lanczos3_filter(t) double t; { if(t < 0) t = -t; if(t < 3.0) return(sinc(t) * sinc(t/3.0)); return(0.0); } #define Mitchell_support (2.0) #define B (1.0 / 3.0) #define C (1.0 / 3.0) double Mitchell_filter(t) double t; { double tt; tt = t * t; if(t < 0) t = -t; if(t < 1.0) { t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); return(t / 6.0); } else if(t < 2.0) { t = (((-1.0 * B - 6.0 * C) * (t * tt)) + ((6.0 * B + 30.0 * C) * tt) + ((-12.0 * B - 48.0 * C) * t) + (8.0 * B + 24 * C)); return(t / 6.0); } return(0.0); } /* * image rescaling routine */ typedef struct { int pixel; double weight; } CONTRIB; typedef struct { int n; /* number of contributors */ CONTRIB *p; /* pointer to list of contributions */ } CLIST; CLIST *contrib; /* array of contribution lists */ void zoom(dst, src, filter, fwidth) Image *dst; /* destination image structure */ Image *src; /* source image structure */ double (*filter)(); /* filter function */ double fwidth; /* filter width (support) */ { Image *tmp; /* intermediate image */ double xscale, yscale; /* zoom scale factors */ int i, j, k; /* loop variables */ int n; /* pixel number */ double center, left, right; /* filter calculation variables */ double width, fscale, weight; /* filter calculation variables */ Pixel *raster; /* a row or column of pixels */ /* create intermediate image to hold horizontal zoom */ tmp = new_image(dst->xsize, src->ysize); xscale = (double) dst->xsize / (double) src->xsize; yscale = (double) dst->ysize / (double) src->ysize; /* pre-calculate filter contributions for a row */ contrib = (CLIST *)calloc(dst->xsize, sizeof(CLIST)); if(xscale < 1.0) { width = fwidth / xscale; fscale = 1.0 / xscale; for(i = 0; i < dst->xsize; ++i) { contrib[i].n = 0; contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB)); center = (double) i / xscale; left = ceiling(center - width); right = floor(center + width); for(j = left; j <= right; ++j) { weight = center - (double) j; weight = (*filter)(weight / fscale) / fscale; if(j < 0) { n = -j; } else if(j >= src->xsize) { n = (src->xsize - j) + src->xsize - 1; } else { n = j; } k = contrib[i].n++; contrib[i].p[k].pixel = n; contrib[i].p[k].weight = weight; } } } else { for(i = 0; i < dst->xsize; ++i) { contrib[i].n = 0; contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); center = (double) i / xscale; left = ceiling(center - fwidth); right = floor(center + fwidth); for(j = left; j <= right; ++j) { weight = center - (double) j; weight = (*filter)(weight); if(j < 0) { n = -j; } else if(j >= src->xsize) { n = (src->xsize - j) + src->xsize - 1; } else { n = j; } k = contrib[i].n++; contrib[i].p[k].pixel = n; contrib[i].p[k].weight = weight; } } } /* apply filter to zoom horizontally from src to tmp */ raster = (Pixel *)calloc(src->xsize, sizeof(Pixel)); for(k = 0; k < tmp->ysize; ++k) { get_row(raster, src, k); for(i = 0; i < tmp->xsize; ++i) { weight = 0.0; for(j = 0; j < contrib[i].n; ++j) { weight += raster[contrib[i].p[j].pixel] * contrib[i].p[j].weight; } put_pixel(tmp, i, k, (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL)); } } free(raster); /* free the memory allocated for horizontal filter weights */ for(i = 0; i < tmp->xsize; ++i) { free(contrib[i].p); } free(contrib); /* pre-calculate filter contributions for a column */ contrib = (CLIST *)calloc(dst->ysize, sizeof(CLIST)); if(yscale < 1.0) { width = fwidth / yscale; fscale = 1.0 / yscale; for(i = 0; i < dst->ysize; ++i) { contrib[i].n = 0; contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB)); center = (double) i / yscale; left = ceiling(center - width); right = floor(center + width); for(j = left; j <= right; ++j) { weight = center - (double) j; weight = (*filter)(weight / fscale) / fscale; if(j < 0) { n = -j; } else if(j >= tmp->ysize) { n = (tmp->ysize - j) + tmp->ysize - 1; } else { n = j; } k = contrib[i].n++; contrib[i].p[k].pixel = n; contrib[i].p[k].weight = weight; } } } else { for(i = 0; i < dst->ysize; ++i) { contrib[i].n = 0; contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); center = (double) i / yscale; left = ceiling(center - fwidth); right = floor(center + fwidth); for(j = left; j <= right; ++j) { weight = center - (double) j; weight = (*filter)(weight); if(j < 0) { n = -j; } else if(j >= tmp->ysize) { n = (tmp->ysize - j) + tmp->ysize - 1; } else { n = j; } k = contrib[i].n++; contrib[i].p[k].pixel = n; contrib[i].p[k].weight = weight; } } } /* apply filter to zoom vertically from tmp to dst */ raster = (Pixel *)calloc(tmp->ysize, sizeof(Pixel)); for(k = 0; k < dst->xsize; ++k) { get_column(raster, tmp, k); for(i = 0; i < dst->ysize; ++i) { weight = 0.0; for(j = 0; j < contrib[i].n; ++j) { weight += raster[contrib[i].p[j].pixel] * contrib[i].p[j].weight; } put_pixel(dst, k, i, (Pixel)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL)); } } free(raster); /* free the memory allocated for vertical filter weights */ for(i = 0; i < tmp->xsize; ++i) { free(contrib[i].p); } free(contrib); free_image(tmp); } /* * command line interface */ void usage() { fprintf(stderr, "usage: %s [-options] input.bm output.bm\n", _Program); fprintf(stderr, "\ options:\n\ -x xsize output x size\n\ -y ysize output y size\n\ -f filter filter type\n\ {b=box, t=triangle, q=bell, B=B-spline, h=hermite, l=Lanczos3, m=Mitchell}\n\ "); exit(1); } void banner() { printf("%s v%s -- %s\n", _Program, _Version, _Copyright); } main(argc, argv) int argc; char *argv[]; { register int c; register char *p; extern int optind; extern char *optarg; int xsize = 0, ysize = 0; double (*f)() = filter; double s = filter_support; char *dstfile, *srcfile; Image *dst, *src; FILE *fp; while((c = getopt(argc, argv, "x:y:f:V")) != EOF) { switch(c) { case 'x': xsize = atoi(optarg); break; case 'y': ysize = atoi(optarg); break; case 'f': switch(*optarg) { case 'b': f=box_filter; s=box_support; break; case 't': f=triangle_filter; s=triangle_support; break; case 'q': f=bell_filter; s=bell_support; break; case 'B': f=B_spline_filter; s=B_spline_support; break; case 'h': f=filter; s=filter_support; break; case 'l': f=Lanczos3_filter; s=Lanczos3_support; break; case 'm': f=Mitchell_filter; s=Mitchell_support; break; default: usage(); } break; case 'V': banner(); exit(EXIT_SUCCESS); case '?': usage(); default: usage(); } } if((argc - optind) != 2) usage(); srcfile = argv[optind]; dstfile = argv[optind + 1]; if(((fp = fopen(srcfile, "r")) == NULL) || ((src = load_image(fp)) == NULL)) { fprintf(stderr, "%s: can't load source image '%s'\n", _Program, srcfile); exit(EXIT_FAILURE); } fclose(fp); if(xsize <= 0) xsize = src->xsize; if(ysize <= 0) ysize = src->ysize; dst = new_image(xsize, ysize); zoom(dst, src, f, s); if(((fp = fopen(dstfile, "w")) == NULL) || (save_image(fp, dst) != 0)) { fprintf(stderr, "%s: can't save destination image '%s'\n", _Program, dstfile); exit(EXIT_FAILURE); } fclose(fp); exit(EXIT_SUCCESS); } -- ======================================================================== ELJA, Inc. TEL: (414) 357-6771 FAX: (414) 357-9394 email: elja.inc@mixcom.com ========================================================================
следующий фpагмент (5)|пpедыдущий фpагмент (3)
From: bcrow1962@aol.com (BCrow1962) Newsgroups: comp.graphics.algorithms Subject: Re: BICUBIC Image Scaling Routine Help Please !!! >Hi > I'm in need of a good image scaling algorithm. I'm assuming that a >Bicubic interpolation by rows and colomns of adjacent pixels is the best >technique. Actually, in my opinion there is very little difference between bicubic interpolation and averaging of nearest neighbors for upscaling and simple subsampling for downscaling as far as image quality goes. Here's an example of bitscaling in that mannner. This only works if you are scaling an image to less than twice or more than half its original size, in which case you would have to do some preprocessing, such as an average blocks of four or some other kind of consolidation for downsizing and a similar process before upsizing. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/time.h> #include <math.h> init_interval_type(interval_type, dim, new_dim) int *interval_type; int dim, new_dim; { int i, j; int delta; float differential, extra_differential; int length, number, difference; int number_of_intervals; int number_of_long_intervals; float real_pixel_index; short start, end; delta = dim - new_dim; if(delta < 0) delta = -delta; number = delta; length = dim / number; difference = dim - number * length; differential = extra_differential = difference; differential /= number; extra_differential /= number * number; i = 0; i++; real_pixel_index = 0.; number_of_intervals = 0; number_of_long_intervals = 0; while(i < dim) { for(j = 1; j < length -1; j++) { i++; } start = real_pixel_index; real_pixel_index += differential; end = real_pixel_index; if(end > start) { i += 2; real_pixel_index += extra_differential; interval_type[number_of_intervals + 2] = 1; number_of_intervals++; number_of_long_intervals++; } else { interval_type[number_of_intervals + 2] = 0; number_of_intervals++; i++; } if(i < dim) { i++; } } interval_type[0] = number_of_intervals; interval_type[1] = length; fprintf(stderr, "The number of intervals was %d.\nThe number of long intervals was %d.\n", number_of_intervals, number_of_long_intervals); } xy_transform_down(src, xdim, ydim, dst, new_xdim, new_ydim, x_interval_type, y_interval_type) unsigned char *src, *dst; int *x_interval_type, *y_interval_type; register int xdim, ydim, new_xdim, new_ydim; { register int i, j, k, m; register int xend, yend, x, y; register int xlength, ylength; register int number_of_xintervals; register int number_of_yintervals; k = 0; m = 0; number_of_xintervals = x_interval_type[0]; xlength = x_interval_type[1] - 1; number_of_yintervals = y_interval_type[0]; ylength = y_interval_type[1] - 1; for(i = 0; i < number_of_yintervals; i++) { if(y_interval_type[i + 2]) yend = ylength + 1; else yend = ylength; for(y = 0; y < yend; y++) { for(j = 0; j < number_of_xintervals; j++) { if(x_interval_type[j + 2]) xend = xlength + 1; else xend = xlength; for(x = 0; x < xend; x++) dst[k++] = src[m++]; m++; } } m += xdim; } } xy_transform_up(src, xdim, ydim, dst, new_xdim, new_ydim, x_interval_type, y_interval_type) unsigned char *src, *dst; int *x_interval_type, *y_interval_type; int xdim, ydim, new_xdim, new_ydim; { register int i, j, k, m; register int xend, yend, x, y; register int xlength, ylength; register int number_of_xintervals; register int number_of_yintervals; k = 0; m = 0; number_of_xintervals = x_interval_type[0]; xlength = x_interval_type[1] - 1; number_of_yintervals = y_interval_type[0]; ylength = y_interval_type[1] - 1; for(i = 0; i < number_of_yintervals; i++) { for(j = 0; j < number_of_xintervals; j++) { dst[k + 1] = (src[m] >> 1) + (src[m + 1] >> 1); dst[k + new_xdim] = (src[m] >> 1) + (src[m + xdim] >> 1); dst[k + 1 + new_xdim] = (dst[k + 1] >> 1) + (dst[k + new_xdim] >> 1); k += 2; m++; if(x_interval_type[j + 2]) xend = xlength + 1; else xend = xlength; for(x = 0; x < xend; x++) { dst[k] = src[m]; dst[k + new_xdim] = (src[m] >> 1) + (src[m + xdim] >> 1); k++; m++; } } k += new_xdim; if(y_interval_type[i + 2]) yend = ylength + 1; else yend = ylength; for(y = 0; y < yend; y++) { for(j = 0; j < number_of_xintervals; j++) { dst[k] = src[m]; dst[k + 1] = (src[m] >> 1) + (src[m + 1] >> 1); k += 2; m++; if(x_interval_type[j + 2]) xend = xlength + 1; else xend = xlength; for(x = 0; x < xend; x++) dst[k++] = src[m++]; } } } } main(int argc,char **argv) { int error; int i; int old_xdim, old_ydim, new_xdim, new_ydim; int old_size, new_size; unsigned char *old, *new; int x_interval_type[1280], y_interval_type[960]; if(argc != 5) { fprintf(stderr,"Usage: %s <old xdim> <old ydim> <new xdim> <new ydim> \n",argv[0]); exit(0); } old_xdim = atoi(argv[1]); old_ydim = atoi(argv[2]); old_size = old_xdim * old_ydim; old = (unsigned char *) malloc(old_size * sizeof(char)); fread(old, old_size, 1, stdin); new_xdim = atoi(argv[3]); new_ydim = atoi(argv[4]); new_size = new_xdim * new_ydim; new = (unsigned char *) malloc(new_size * sizeof(char)); init_interval_type(x_interval_type, old_xdim, new_xdim); init_interval_type(y_interval_type, old_ydim, new_ydim); if(old_xdim < new_xdim && old_ydim < new_ydim) { xy_transform_up(old, old_xdim, old_ydim, new, new_xdim, new_ydim, x_interval_type, y_interval_type); } else { xy_transform_down(old, old_xdim, old_ydim, new, new_xdim, new_ydim, x_interval_type, y_interval_type); } fwrite(new, new_xdim * new_ydim, 1, stdout); }
следующий фpагмент (6)|пpедыдущий фpагмент (4)
- Usenet echoes (21:200/1) -------------------------- COMP.GRAPHICS.ALGORITHMS - Msg : 26 of 33 From : cxf@itd.dsto.gov.au 2:5030/144.99 07 Jul 94 01:46:28 To : All 10 Jul 94 03:25:46 Subj : Scaling Pixmap Algorithm. -------------------------------------------------------------------------------- I have written a routine to scale pixmaps which I have included below. Can anyone offer ideas on how this can be sped up? It is fast on a sparc10 but pretty slow on a sparc2. Also where can I find some decent documentation on pixmaps. I'd like to know how to have transparent pixels. Thanks, Chris. Pixmap ScalePixmap( theWindow, source, swidth, sheight, dwidth, dheight) Window theWindow; Pixmap source; int swidth, sheight; int dwidth,dheight; { Pixmap temp,dest; int j,end; float i; float xscale, yscale; xscale = (float) swidth / (float) dwidth; /* Scaling factors */ yscale = (float) sheight / (float) dheight; dest = XCreatePixmap(theDisplay,theWindow,dwidth,dheight,8); temp = XCreatePixmap(theDisplay,theWindow,dwidth,sheight,8); j = 0; end = dwidth*xscale; /* Scale width of source into temp pixmap */ for(i=0;i<end;i+=xscale) XCopyArea(theDisplay,source,temp,theGC,(int) i,0,1,sheight,j++,0); j = 0; end = dheight*yscale; /* Scale height of temp into dest pixmap */ for(i=0;i<end;i+=yscale) XCopyArea(theDisplay,temp,dest,theGC,0,(int) i,dwidth,1,0,j++); XFreePixmap( theDisplay, temp ); return (Pixmap) dest; }

Всего 5 фpагмент(а/ов) |пpедыдущий фpагмент (5)

Если вы хотите дополнить FAQ - пожалуйста пишите.

design/collection/some content by Frog,
DEMO DESIGN FAQ (C) Realm Of Illusion 1994-2000,
При перепечатке материалов этой страницы пожалуйста ссылайтесь на источник: "DEMO.DESIGN FAQ, http://www.enlight.ru/demo/faq".