• ### What is your GameDev Story?

#### Archived

This topic is now archived and is closed to further replies.

# Bicubic Interpolation for Image Resizing

This topic is 5327 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Does anybody have any good urls showing code for resizing image s using Bicubic Interpolation? Or at least a site that explains it well?

##### Share on other sites
Well I found an explanation for bicubic interpolation here http://astronomy.swin.edu.au/~pbourke/colour/bicubic/

and I''ve implemented it, but it does not seem to be working. I tried it on a single 2x2 image, with the 4 pixel values of Red,Blue,Yellow, and Green, and after enlarging the 2x2 image to an 8x8 image, it simply had a faded dark red in the upper left and then diagnolly down to the right was a darker red, then every other pixel was black.

Can anybody help me with my code?

code

##### Share on other sites

uint Interpolate_Value(uint v0, uint v1, uint v2, uint v3, float t){	int p = (v3 - v2) - (v0 - v1);	int q = (v0 - v1) - p;	int r = v2 - v0;	int s = v1;	float tSqrd = t * t;//	return (p * (tSqrd * t)) + (q * tSqrd) + (r * t) + s;	//return (p * (tSqrd * t) + 0.5f) + (q * tSqrd + 0.5f) + (r * t + 0.5f) + s; // Use this one for nicer interpolation, it rounds instead of truncates.}//// To interpolate a pixel we need to interpolate each color component seperately//ARGB Interpolate_Pixel(ARGB p0, ARGB p1, ARGB p2, ARGB p3, float t){	return InterpolateValue(p0.a, p1.a, p2.a, p3.a, t) << 24 |	       InterpolateValue(p0.r, p1.r, p2.r, p3.r, t) << 16 |	       InterpolateValue(p0.g, p1.g, p2.g, p3.g, t) << 08 |	       InterpolateValue(p0.b, p1.b, p2.b, p3.b, t);}//////Resize_Image(ARGB *Image, uint Width, uint Height, uint NewWidth, uint NewWidth, ARGB *NewImage){	uint	OldImageX, OldImageY;	float	dx = Width / NewWidth, dy = Height / NewHeight;	ARGB	Temp[4];//	//	for (y = 0; y < NewHeight; ++y)	{		OldImageY = dy * y;		ty = dy * y - OldImageY;//		for (x = 0; x < NewWidth; ++x)		{			OldImageX = dx * x;			tx = dx * x - OldImageX;//			// I don't know how image scaling works with regards to edges			// e.g. when OldImageX is 0 and you need pixels from behind (OldImageX - 1) you can either wrap around and get pixels to sample from the other side of the image (OldImageX = Width - 1)			// or you can just clamp to the edge (if (OldImageX - 1 < 0) OldImageX = 0), your choice, see what looks best.			// Likewise for when OldImageX == Width - 1 and you need to get OldImageX + 1//			// To interpolate 2D data correctly we first interpolate 4 pixels horizontally for each of 4 scanlines, which leaves us with 4 new pixels//			Temp[0] = Interpolate_Pixel(Image[(OldImageY - 1) * Width + OldImageX - 1],						Image[(OldImageY - 1) * Width + OldImageX],						Image[(OldImageY - 1) * Width + OldImageX + 1],						Image[(OldImageY - 1) * Width + OldImageX + 2],						tx);			Temp[1] = Interpolate_Pixel(Image[OldImageY * Width + OldImageX - 1],						Image[OldImageY * Width + OldImageX],						Image[OldImageY * Width + OldImageX + 1],						Image[OldImageY * Width + OldImageX + 2],						tx);			Temp[2] = Interpolate_Pixel(Image[(OldImageY + 1) * Width + OldImageX - 1],						Image[(OldImageY + 1) * Width + OldImageX],						Image[(OldImageY + 1) * Width + OldImageX + 1],						Image[(OldImageY + 1) * Width + OldImageX + 2],						tx);			Temp[3] = Interpolate_Pixel(Image[(OldImageY + 2) * Width + OldImageX - 1],						Image[(OldImageY + 2) * Width + OldImageX],						Image[(OldImageY + 2) * Width + OldImageX + 1],						Image[(OldImageY + 2) * Width + OldImageX + 2],						tx);//			// Then we interpolate those 4 pixels to get a single pixel that is a composite of 4 * 4 pixels, 16 pixels			NewImage[y * NewWidth + x] = Interpolate_Pixel(Temp[0], Temp[1], Temp[2], Temp[3], ty);		}	}}

Note that it contains a bit of pseudo-code, but I hope you understand. Note the caveats. You can do a lot of optimization, but for clarity I skipped most of it, you can obviously reuse some of the values instead of recalculating them. I haven't tested it, but if anyone spots something amiss feel free to jump in and correct it.

Arghhh.. better code parsing plz. x_x

------------
- outRider -

[edited by - outRider on June 5, 2004 4:26:54 PM]

##### Share on other sites
This is for bicubic interpolation? or bilinear ?

##### Share on other sites
Bicubic. Bilinear would sample the nearest 4 pixels, bicubic samples the nearest 16.

------------
- outRider -

[edited by - outRider on June 5, 2004 4:28:05 PM]

##### Share on other sites
Ah, okay. Well thanks a lot for the code :-)

##### Share on other sites
I tried implementing your code, but I still got very odd results. Here's the 8x8 image I was enlarging to a 32x32, and the result of what happened after enlarging.

8x8 image

32x32 image

I pretty much tried to copy your code piece by piece, although I had to convert it over to using char instead of int for the pixel data. But other than that, it is identical.

CODE

Any ideas ?

[edited by - oconnellseanm on June 5, 2004 5:55:49 PM]

##### Share on other sites
I''ll test it and get back to you later.

------------
- outRider -

##### Share on other sites
Oh I got it to work, thanks again. I updated the the code with the working version.

CODE

##### Share on other sites
Yeah, I just tested it myself and noticed I forgot to clamp the values in the 0-255 range in InterpolateValue(). Cubic interpolation can overflow or underflow, so you have to either clamp or rescale all your values.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 10
• 11
• 13
• 9
• 11
• ### Forum Statistics

• Total Topics
634090
• Total Posts
3015430
×