Beispiel #1
0
//---------------------------------------------------------------------------
static int ib_resample(tTVPBaseBitmap *dst,
	const tTVPRect &destrect,
	const tTVPBaseBitmap *src,
	const tTVPRect &srcrect,
	real_t (*filterf)(real_t),
//	void (*blend)(tjs_uint32 *dest, tjs_uint32 src),
	real_t fwidth)
{
	pixel_t * tmp;
	real_t xscale, yscale;          /* zoom scale factors */
	int xx;
	int i, j, k;                    /* loop variables */
	int n;                          /* pixel number */
	real_t center, left, right;     /* filter calculation variables */
	real_t width, fscale;   /* filter calculation variables */
	pixel_real_t_t weight;
	pixel_t pel, pel2;
	pixel_t bPelDelta;
	CLIST   *contribY;              /* array of contribution lists */
	CLIST   contribX;
	int             nRet = -1;
	int srcwidth = srcrect.get_width();
	int srcheight = srcrect.get_height();
	int destwidth = destrect.get_width();
	int destheight = destrect.get_height();

	/* create intermediate column to hold horizontal dst column zoom */
	tmp = (pixel_t*)malloc(srcheight * sizeof(pixel_t));
	if(tmp == NULL)
		return 0;

	xscale = (real_t) destwidth / (real_t) srcwidth;

	/* Build y weights */
	/* pre-calculate filter contributions for a column */
	contribY = (CLIST *)calloc(destheight, sizeof(CLIST));
	if(contribY == NULL)
	{
		free(tmp);
		return -1;
	}

	yscale = (real_t) destheight / (real_t) srcheight;

	if(yscale < 1.0)
	{
		real_t weight;
		width = fwidth / yscale;
		fscale = static_cast<real_t>(1.0 / yscale);
		for(i = 0; i < destheight; ++i)
		{
			real_t w_sum = 0;

			contribY[i].n = 0;
			contribY[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
							sizeof(CONTRIB));
			if(contribY[i].p == NULL)
			{
				free(tmp);
				free(contribY);
				return -1;
			}
			center = (real_t) i * fscale;
			left = ceil(center - width);
			right = floor(center + width);
			for(j = (int)left; j <= right; ++j)
			{
				weight = center - (real_t) j;
				weight = (*filterf)(weight * yscale); //* yscale;
				w_sum += weight;
				if(j < 0)
				{
					n = -j;
				}
				else if(j >= srcheight)
				{
					n = (srcheight - j) + srcheight - 1;
				}
				else
				{
					n = j;
				}
				if(n < 0) n = 0;
				if(n >= srcheight - 1) n = srcheight - 1;
				k = contribY[i].n++;
				contribY[i].p[k].pixel = n;
				contribY[i].p[k].weight = weight;
			}

			if(w_sum != 0.0)
			{
				w_sum = static_cast<real_t>(1.0 / w_sum);
				for(j = 0; j < contribY[i].n; j ++)
					contribY[i].p[j].weight *= w_sum;
			}

		}
	}
	else
	{
		real_t weight;
		for(i = 0; i < destheight; ++i)
		{
			contribY[i].n = 0;
			contribY[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
							sizeof(CONTRIB));
			if(contribY[i].p == NULL)
			{
				free(tmp);
				free(contribY);
				return -1;
			}
			center = (real_t) i / yscale;
			left = ceil(center - fwidth);
			right = floor(center + fwidth);
			for(j = (int)left; j <= right; ++j)
			{
				weight = center - (real_t) j;
				weight = (*filterf)(weight);
				if(j < 0)
				{
					n = -j;
				}
				else if(j >= srcheight)
				{
					n = (srcheight - j) + srcheight - 1;
				}
				else
				{
					n = j;
				}
				if(n < 0) n = 0;
				if(n >= srcheight - 1) n = srcheight - 1;
				k = contribY[i].n++;
				contribY[i].p[k].pixel = n;
				contribY[i].p[k].weight = weight;
			}
		}
	}


	const pixel_t *srclinestart = (const pixel_t*)src->GetScanLine(srcrect.top) +
		srcrect.left;
	tjs_int srcpitchbytes = src->GetPitchBytes();

	pixel_t *destlinestart = (pixel_t*)dst->GetScanLineForWrite(destrect.top) +
		destrect.left;
	tjs_int destpitchbytes = dst->GetPitchBytes();

	for(xx = 0; xx < destwidth; xx++)
	{
		if(0 != calc_x_contrib(&contribX, xscale, fwidth,
			destwidth, srcwidth, filterf, xx))
		{
			goto __zoom_cleanup;
		}
		/* Apply horz filter to make dst column in tmp. */
		{
			const pixel_t *line = srclinestart;
			for(k = 0; k < srcheight; ++k)
			{
				weight.r = weight.g = weight.b = weight.a = 0;
				bPelDelta.r = bPelDelta.g = bPelDelta.b = bPelDelta.a = FALSE;
				pel = line[contribX.p[0].pixel];
				for(j = contribX.n - 1; j >= 0; --j)
				{
					CONTRIB *c = contribX.p + j;
					pel2 = line[c->pixel];
					bPelDelta.r |= (pel2.r - pel.r);
					bPelDelta.b |= (pel2.b - pel.b);
					bPelDelta.g |= (pel2.g - pel.g);
					bPelDelta.a |= (pel2.a - pel.a);
					weight.r += pel2.r * c->weight;
					weight.g += pel2.g * c->weight;
					weight.b += pel2.b * c->weight;
					weight.a += pel2.a * c->weight;
				}
				weight.r = static_cast<real_t>(bPelDelta.r ? roundcloser(weight.r) : pel.r);
				weight.g = static_cast<real_t>(bPelDelta.g ? roundcloser(weight.g) : pel.g);
				weight.b = static_cast<real_t>(bPelDelta.b ? roundcloser(weight.b) : pel.b);
				weight.a = static_cast<real_t>(bPelDelta.a ? roundcloser(weight.a) : pel.a);

				tmp[k].r = (unsigned char)CLAMP(static_cast<int>(weight.r), 0, 255);
				tmp[k].g = (unsigned char)CLAMP(static_cast<int>(weight.g), 0, 255);
				tmp[k].b = (unsigned char)CLAMP(static_cast<int>(weight.b), 0, 255);
				tmp[k].a = (unsigned char)CLAMP(static_cast<int>(weight.a), 0, 255);
				
				//(tjs_uint8*)(line) += srcpitchbytes;
				const tjs_uint8* b = reinterpret_cast<const tjs_uint8*>(line);
				b += srcpitchbytes;
				line = reinterpret_cast<const pixel_t*>(b);
			} /* next row in temp column */
		}

		free(contribX.p);

		/* The temp column has been built. Now stretch it
		 vertically into dst column. */
		{
			pixel_t *line = destlinestart;
			for(i = 0; i < destheight; ++i)
			{
				CLIST *cl = contribY + i;
				weight.r = weight.g = weight.b = weight.a = 0;
				bPelDelta.r = bPelDelta.g = bPelDelta.b = bPelDelta.a = FALSE;
				pel = tmp[cl->p[0].pixel];

				for(j = cl->n - 1; j >= 0; --j)
				{
					CONTRIB *c = cl->p + j;
					pel2 = tmp[c->pixel];
					bPelDelta.r |= (pel2.r - pel.r);
					bPelDelta.b |= (pel2.b - pel.b);
					bPelDelta.g |= (pel2.g - pel.g);
					bPelDelta.a |= (pel2.a - pel.a);
					weight.r += pel2.r * c->weight;
					weight.g += pel2.g * c->weight;
					weight.b += pel2.b * c->weight;
					weight.a += pel2.a * c->weight;
				}
				weight.r = static_cast<real_t>(bPelDelta.r ? roundcloser(weight.r) : pel.r);
				weight.g = static_cast<real_t>(bPelDelta.g ? roundcloser(weight.g) : pel.g);
				weight.b = static_cast<real_t>(bPelDelta.b ? roundcloser(weight.b) : pel.b);
				weight.a = static_cast<real_t>(bPelDelta.a ? roundcloser(weight.a) : pel.a);
				line[xx].r = (unsigned char)CLAMP(static_cast<int>(weight.r), 0, 255);
				line[xx].g = (unsigned char)CLAMP(static_cast<int>(weight.g), 0, 255);
				line[xx].b = (unsigned char)CLAMP(static_cast<int>(weight.b), 0, 255);
				line[xx].a = (unsigned char)CLAMP(static_cast<int>(weight.a), 0, 255);

				const tjs_uint8* b = reinterpret_cast<const tjs_uint8*>(line);
				b += destpitchbytes;
				line = const_cast<pixel_t*>(reinterpret_cast<const pixel_t*>(b));
 				//(const tjs_uint8*)(line) += destpitchbytes;
			} /* next dst row */
		}
	} /* next dst column */
	nRet = 0; /* success */

__zoom_cleanup:
	free(tmp);

	/* free the memory allocated for vertical filter weights */
	for(i = 0; i < destheight; ++i)
			free(contribY[i].p);
	free(contribY);

	return nRet;
} /* ib_resample */
/*
	zoom()

	Resizes bitmaps while resampling them.
	Returns -1 if error, 0 if success.
*/
int zoom( ILimage *dst, ILimage *src, double (*filterf)(double), double fwidth) {
	ILubyte* tmp;
	double xscale, yscale;		/* zoom scale factors */
	int xx;
	int i, j, k;			/* loop variables */
	int n;				/* pixel number */
	double center, left, right;	/* filter calculation variables */
	double width, fscale, weight;	/* filter calculation variables */
	ILubyte pel, pel2;
	int bPelDelta;
	CLIST	*contribY;		/* array of contribution lists */
	CLIST	contribX;
	int		nRet = -1;

	/* create intermediate column to hold horizontal dst column zoom */
	tmp = (ILubyte*)ialloc(src->Height * sizeof(ILubyte));
	if (tmp == NULL) {
		return 0;
	}

	xscale = (double) dst->Width / (double) src->Width;

	/* Build y weights */
	/* pre-calculate filter contributions for a column */
	contribY = (CLIST*)icalloc(dst->Height, sizeof(CLIST));
	if (contribY == NULL) {
		ifree(tmp);
		return -1;
	}

	yscale = (double) dst->Height / (double) src->Height;

	if(yscale < 1.0)
	{
		width = fwidth / yscale;
		fscale = 1.0 / yscale;
		for(i = 0; i < (ILint)dst->Height; ++i)
		{
			contribY[i].n = 0;
			contribY[i].p = (CONTRIB*)icalloc((int) (width * 2 + 1),
					sizeof(CONTRIB));
			if(contribY[i].p == NULL) {
				ifree(tmp);
				ifree(contribY);
				return -1;
			}
			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;
				n = wrap_filter_sample(j, src->Height);
				k = contribY[i].n++;
				contribY[i].p[k].pixel = n;
				contribY[i].p[k].weight = weight;
			}
		}
	} else {
		for(i = 0; i < (ILint)dst->Height; ++i) {
			contribY[i].n = 0;
			contribY[i].p = (CONTRIB*)icalloc((int) (fwidth * 2 + 1),
					sizeof(CONTRIB));
			if (contribY[i].p == NULL) {
				ifree(tmp);
				ifree(contribY);
				return -1;
			}
			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);
				n = wrap_filter_sample(j, src->Height);
				k = contribY[i].n++;
				contribY[i].p[k].pixel = n;
				contribY[i].p[k].weight = weight;
			}
		}
	}


	for(xx = 0; xx < (ILint)dst->Width; xx++)
	{
		if(0 != calc_x_contrib(&contribX, xscale, fwidth, 
								dst->Width, src->Width, filterf, xx))
		{
			goto __zoom_cleanup;
		}
		/* Apply horz filter to make dst column in tmp. */
		for(k = 0; k < (ILint)src->Height; ++k)
		{
			weight = 0.0;
			bPelDelta = IL_FALSE;
			// Denton:  Put get_pixel source here
			//pel = get_pixel(src, contribX.p[0].pixel, k);
			pel = src->Data[k * src->Bps + contribX.p[0].pixel * src->Bpp + c];
			for(j = 0; j < contribX.n; ++j)
			{
				// Denton:  Put get_pixel source here
				//pel2 = get_pixel(src, contribX.p[j].pixel, k);
				pel2 = src->Data[k * src->Bps + contribX.p[j].pixel * src->Bpp + c];
				if(pel2 != pel)
					bPelDelta = IL_TRUE;
				weight += pel2 * contribX.p[j].weight;
			}
			weight = bPelDelta ? roundcloser(weight) : pel;

			tmp[k] = (ILubyte)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
		} /* next row in temp column */

		ifree(contribX.p);

		/* The temp column has been built. Now stretch it 
		 vertically into dst column. */
		for(i = 0; i < (ILint)dst->Height; ++i)
		{
			weight = 0.0;
			bPelDelta = IL_FALSE;
			pel = tmp[contribY[i].p[0].pixel];

			for(j = 0; j < contribY[i].n; ++j)
			{
				pel2 = tmp[contribY[i].p[j].pixel];
				if(pel2 != pel)
					bPelDelta = IL_TRUE;
				weight += pel2 * contribY[i].p[j].weight;
			}
			weight = bPelDelta ? roundcloser(weight) : pel;
			// Denton:  Put set_pixel source here
			//put_pixel(dst, xx, i, (ILubyte)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL));
			dst->Data[i * dst->Bps + xx * dst->Bpp + c] =
				(ILubyte)CLAMP(weight, BLACK_PIXEL, WHITE_PIXEL);
		} /* next dst row */
	} /* next dst column */
	nRet = 0; /* success */

__zoom_cleanup:
	ifree(tmp);

	// Free the memory allocated for vertical filter weights
	for (i = 0; i < (ILint)dst->Height; ++i)
		ifree(contribY[i].p);
	ifree(contribY);

	return nRet;
} /* zoom */
Beispiel #3
0
zoomer_t *
zoom_image_init(zoom_image_t *dst, zoom_image_t *src, double (*filterf)(double), double fwidth)
{
    zoomer_t *zoomer;
    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;
    
    zoomer = (zoomer_t*)malloc(sizeof(zoomer_t));
    zoomer->src = src;
    zoomer->dst = dst;

    /* create intermediate column to hold horizontal dst column zoom */
    zoomer->tmp = (pixel_t*)malloc(src->ysize * sizeof(pixel_t));
    if(zoomer->tmp == NULL)
    {
        free(zoomer);
        return 0;
    }

    xscale = (double) dst->xsize / (double) src->xsize;

    /* Build y weights */
    /* pre-calculate filter contributions for a column */

    printf ("allocating %d contribY items\n", dst->ysize);

    contribY = (CLIST *)calloc(dst->ysize, sizeof(CLIST));
    if(contribY == NULL)
    {
        free(zoomer->tmp);
        free(zoomer);
        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)
        {
	  /*printf ("zoom: i=%d \n", i); */

            contribY[i].n = 0;
            contribY[i].p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB));
            if(contribY[i].p == NULL)
            {
                free(zoomer->tmp);
                free(contribY);
                free(zoomer);
                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(zoomer->tmp);
                free(zoomer);
                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);

    printf ("zoom: fwidth = %d, maxwidth=%d, xscale=%f, yscale=%f\n", fwidth, maxwidth);

    prg = zoomer->programX = calloc(zoomer->dst->xsize * 
                                    (2 + 2*(int)(maxwidth*2+1)),
                                    sizeof(instruction_t));

    for(xx = 0; xx < zoomer->dst->xsize; xx++)
    {
        calc_x_contrib(&contribX, xscale, fwidth, 
                       zoomer->dst->xsize, zoomer->src->xsize,
                       filterf, xx);

        /*pel = get_pixel(zoomer->src, contribX.p[0].pixel, k);*/
        (prg++)->index = contribX.p[0].pixel * zoomer->src->span;
        (prg++)->count = contribX.n;
        for(j = 0; j < contribX.n; ++j)
        {
            /*pel2 = get_pixel(zoomer->src, contribX.p[j].pixel, k);*/
            (prg++)->index = contribX.p[j].pixel * zoomer->src->span;
            /*weight += pel2 * contribX.p[j].weight;*/
            (prg++)->weight = contribX.p[j].weight;
        }
        free(contribX.p);
    }

    prg = zoomer->programY = calloc(zoomer->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 < zoomer->dst->ysize; ++i)
    {
        /**(prg++) = zoomer->contribY[i].p[0].pixel;*/
        (prg++)->pixel = zoomer->tmp + contribY[i].p[0].pixel;
        (prg++)->count = contribY[i].n;
        for(j = 0; j < contribY[i].n; ++j)
        {
            /*(prg++) = zoomer->contribY[i].p[j].pixel;*/
            (prg++)->pixel = zoomer->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 < zoomer->dst->ysize; ++i)
        free(contribY[i].p);
    free(contribY);

    return zoomer;
}