예제 #1
0
/*
	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 */
예제 #2
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 */