⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_util_resize.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 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 */scaler_t *scale_image_init(image_t *dst, image_t *src, double (*filterf)(double), double fwidth){    scaler_t *scaler;    int i, j, k;            /* loop variables */    int n;              /* pixel number */    int xx;    double center = 0.0, left, right;   /* filter calculation variables */    double width, fscale, weight;   /* filter calculation variables */    double xscale, yscale;    double maxwidth;    CLIST  contribX;    CLIST *contribY;    instruction_t *prg;        scaler = (scaler_t*)malloc(sizeof(scaler_t));    scaler->src = src;    scaler->dst = dst;    /* create intermediate column to hold horizontal dst column scale */    scaler->tmp = (pixel_t*)malloc(src->ysize * sizeof(pixel_t));    if(scaler->tmp == NULL)    {        free(scaler);        return 0;    }    xscale = (double) dst->xsize / (double) src->xsize;    /* Build y weights */    /* pre-calculate filter contributions for a column */    contribY = (CLIST *)calloc(dst->ysize, sizeof(CLIST));    if(contribY == NULL)    {        free(scaler->tmp);        free(scaler);        return 0;    }    yscale = (double) dst->ysize / (double) src->ysize;    if(yscale < 1.0)    {        width = fwidth / yscale;        fscale = 1.0 / yscale;        for(i = 0; i < dst->ysize; ++i)        {            contribY[i].n = 0;            contribY[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB));            if(contribY[i].p == NULL)            {                free(scaler->tmp);                free(contribY);                free(scaler);                return 0;            }            center = (double) i / yscale;            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 >= src->ysize) {                    n = (src->ysize - j) + src->ysize - 1;                } else {                    n = j;                }                k = contribY[i].n++;                contribY[i].p[k].pixel = n;                contribY[i].p[k].weight = double2fixdouble(weight);            }        }    } else {        for(i = 0; i < dst->ysize; ++i) {            contribY[i].n = 0;            contribY[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB));            if(contribY[i].p == NULL)            {                free(scaler->tmp);                free(scaler);                return 0;            }            center = (double) i / yscale;            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 >= src->ysize) {                    n = (src->ysize - j) + src->ysize - 1;                } else {                    n = j;                }                k = contribY[i].n++;                contribY[i].p[k].pixel = n;                contribY[i].p[k].weight = double2fixdouble(weight);            }        }    }    /* -------------------------------------------------------------       streamline contributions into two simple bytecode programs. This       single optimalization nearly doubles the performance! */    maxwidth = fwidth;    if (xscale < 1.0 || yscale < 1.0)       maxwidth = fwidth / (xscale < yscale ? xscale : yscale);    prg = scaler->programX = (instruction_t*)calloc(scaler->dst->xsize *                                     (2 + 2*(int)(maxwidth*2+1)),                                    sizeof(instruction_t));    for(xx = 0; xx < scaler->dst->xsize; xx++)    {        calc_x_contrib(&contribX, xscale, fwidth,                        scaler->dst->xsize, scaler->src->xsize,                       filterf, xx);        /*pel = get_pixel(scaler->src, contribX.p[0].pixel, k);*/        (prg++)->index = contribX.p[0].pixel * scaler->src->span;        (prg++)->count = contribX.n;        for(j = 0; j < contribX.n; ++j)        {            /*pel2 = get_pixel(scaler->src, contribX.p[j].pixel, k);*/            (prg++)->index = contribX.p[j].pixel * scaler->src->span;            /*weight += pel2 * contribX.p[j].weight;*/            (prg++)->weight = contribX.p[j].weight;        }        free(contribX.p);    }    prg = scaler->programY = (instruction_t*)calloc(scaler->dst->ysize *                                     (2 + 2*(int)(maxwidth*2+1)),                                    sizeof(instruction_t));        /* The temp column has been built. Now stretch it      vertically into dst column. */    for(i = 0; i < scaler->dst->ysize; ++i)    {        /**(prg++) = scaler->contribY[i].p[0].pixel;*/        (prg++)->pixel = scaler->tmp + contribY[i].p[0].pixel;        (prg++)->count = contribY[i].n;        for(j = 0; j < contribY[i].n; ++j)        {            /*(prg++) = scaler->contribY[i].p[j].pixel;*/            (prg++)->pixel = scaler->tmp + contribY[i].p[j].pixel;            (prg++)->weight = contribY[i].p[j].weight;        }    } /* next dst row */    /* ---------------------------------------------------       free the memory allocated for vertical filter weights -- no        longer needed, we have programX and programY */    for(i = 0; i < scaler->dst->ysize; ++i)        free(contribY[i].p);    free(contribY);    return scaler;}void scale_image_process(scaler_t *scaler){    int x;    int i = 0, j, k;            /* loop variables */    pixel_t pel, pel2;    int bPelDelta;    fixdouble weight;    pixel_t *in;    pixel_t *out = scaler->dst->data;    pixel_t *tmpOut;    instruction_t *prgY, *prgX = NULL, *prgXa;    prgXa = scaler->programX;        for(x = scaler->dst->xsize; x; --x) {		/* Apply horz filter to make dst column in tmp. */		for(in = scaler->src->data, tmpOut = scaler->tmp, 		  k = scaler->src->ysize; k; --k, in++) {			prgX = prgXa;			weight = 0;			bPelDelta = false;			pel = in[(prgX++)->index];			for(j = (prgX++)->count; j; --j) {				pel2 = in[(prgX++)->index];				if(pel2 != pel) {					bPelDelta = true;				}				weight += pel2 * (prgX++)->weight;			}			*(tmpOut++) = 				bPelDelta ? (pixel_t)CLAMP(fixdouble2int(weight)) : pel;		} /* next row in temp column */		prgXa = prgX;		/*		 * The temp column has been built. 		 * Now stretch it vertically into dst column. 		 */		prgY = scaler->programY;		for(i = scaler->dst->ysize; i; --i) {			weight = 0;			bPelDelta = false;			pel = *((prgY++)->pixel);			for(j = (prgY++)->count; j; --j) {				pel2 = *((prgY++)->pixel);				if(pel2 != pel) {					bPelDelta = true;				}				weight += pel2 * (prgY++)->weight;			}			*(out++) = 				bPelDelta ? (pixel_t)CLAMP(fixdouble2int(weight)) : pel;		} /* next dst row */    } /* next dst column */}void scale_image_done(scaler_t *scaler){    free(scaler->tmp);    free(scaler->programY);    free(scaler->programX);    free(scaler);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -