📄 video_util_resize.cpp
字号:
/* * Filtered Image Rescaling * Additional changes by Ray Gardener, Daylon Graphics Ltd. December 4, 1999 Summary: - Horizontal filter contributions are calculated on the fly, as each column is mapped from src to dst image. This lets us omit having to allocate a temporary full horizontal stretch of the src image. - If none of the src pixels within a sampling region differ, then the output pixel is forced to equal (any of) the source pixel. This ensures that filters do not corrupt areas of constant color. - Filter weight contribution results, after summing, are rounded to the nearest pixel color value instead of being casted to Pixel (usually an int or char). Otherwise, artifacting occurs. - All memory allocations checked for failure; scale() returns error code. new_image() returns NULL if unable to allocate pixel storage, even if Image struct can be allocated. Some assertions added. - load_image(), save_image() take filenames, not file handles. - TGA bitmap format available. If you want to add a filetype, extend the gImageHandlers array, and factor in your load_image_xxx() and save_image_xxx() functions. Search for string 'add your' to find appropriate code locations. - The 'input' and 'output' command-line arguments do not have to specify .bm files; any supported filetype is okay. - Added implementation of getopt() if compiling under Windows.*/#include "mp4live.h"#include "video_util_resize.h"#ifndef M_PI#define M_PI 3.14159265358979323846#endif#define WHITE_PIXEL (255)#define BLACK_PIXEL (0)#define CLAMP(v) (((v) < (BLACK_PIXEL)) ? \ (BLACK_PIXEL) : \ (((v) > (WHITE_PIXEL)) ? (WHITE_PIXEL) : (v)))#define get_pixel(image, y, x) ((image)->data[(x) + (y) * image->span])#define put_pixel(image, y, x, p) ((image)->data[(x) + (y) * image->span] = (p))/* Helper data structures: */typedef struct { int pixel; fixdouble weight;} CONTRIB;typedef struct { int n; /* number of contributors */ CONTRIB *p; /* pointer to list of contributions */} CLIST;void scale_setup_image(image_t *img, int w, int h, int depth, pixel_t *data){ img->xsize = h; img->ysize = w; img->pixspan = depth; img->span = w * depth; img->data = data;}image_t *scale_new_image(int w, int h, int depth) /* create a blank image */{ image_t *image; if((image = (image_t *)malloc(sizeof(image_t)))) { image->xsize = h; image->ysize = w; image->span = w * depth; image->pixspan = depth; image->data = NULL; } return image;}void scale_free_image(image_t *image){ free(image);}/* * filter function definitions */double Hermite_filter(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);}double Box_filter(double t){ if((t > -0.5) && (t <= 0.5)) return(1.0); return(0.0);}double Triangle_filter(double t){ if(t < 0.0) t = -t; if(t < 1.0) return(1.0 - t); return(0.0);}double Bell_filter(double t) /* box (*) box (*) box */{ 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);}double B_spline_filter(double t) /* box (*) box (*) box (*) box */{ 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);}static double sinc(double x){ x *= M_PI; if(x != 0) return(sin(x) / x); return(1.0);}double Lanczos3_filter(double t){ if(t < 0) t = -t; if(t < 3.0) return(sinc(t) * sinc(t/3.0)); return(0.0);}#define B (1.0 / 3.0)#define C (1.0 / 3.0)double Mitchell_filter(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 *//* calc_x_contrib( CLIST* contribX; * Receiver of contrib info double xscale; * Horizontal scaling double fwidth; * Filter sampling width int dstwidth; * Target bitmap width int srcwidth; * Source bitmap width double (*filterf)(double); * Filter proc int i; * pixel_t column in source bitmap being processed ) Calculates the filter weights for a single target column. contribX->p must be freed afterwards. Returns -1 if error, 0 otherwise.*/static int calc_x_contrib(CLIST* contribX, double xscale, double fwidth, int dstwidth, int srcwidth, double (*filterf)(double), int i){ double width; double fscale; double center, left, right; double weight; int j, k, n; if(xscale < 1.0) { /* Shrinking image */ width = fwidth / xscale; fscale = 1.0 / xscale; contribX->n = 0; contribX->p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB)); if(contribX->p == NULL) return -1; center = (double) i / xscale; left = ceil(center - width); right = floor(center + width); for(j = (int)left; j <= right; ++j) { weight = center - (double) j; weight = (*filterf)(weight / fscale) / fscale; if(j < 0) n = -j; else if(j >= srcwidth) n = (srcwidth - j) + srcwidth - 1; else n = j; k = contribX->n++; contribX->p[k].pixel = n; contribX->p[k].weight = double2fixdouble(weight); } } else { /* Expanding image */ contribX->n = 0; contribX->p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); if(contribX->p == NULL) return -1; center = (double) i / xscale; left = ceil(center - fwidth); right = floor(center + fwidth); for(j = (int)left; j <= right; ++j) { weight = center - (double) j; weight = (*filterf)(weight); if(j < 0) { n = -j; } else if(j >= srcwidth) { n = (srcwidth - j) + srcwidth - 1; } else { n = j; } k = contribX->n++; contribX->p[k].pixel = n; contribX->p[k].weight = double2fixdouble(weight); } } return 0;} /* calc_x_contrib */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -