Click here to Skip to main content
Click here to Skip to main content

Zoom an image with different interpolation types.

, 6 Aug 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Implementation of different interpolations[Bi-Linear and Bi-Cubic] with OpenGL.
This is an old version of the currently published article.

Table Of Contents 

Introduction 

This sample application demonstrates the implementation of Bi-linear interpolation and Bi-Cubic interpolation in a GLSL shader.  

ScreenShot.jpg 

Screenshot of ZoomInterpolation Application. 

Background 

In OpenGL, we can specify an interpolation type(Filter type) to create a resized image of texture. When a texture or region of a texture is mapped to a higher or lower screen region, OpenGL uses this interpolation type to create texture image in different size.

To create a large image from a small texture area, openGL provides two interpolation options, GL_LINEAR, and GL_LINEAR. In addition to OpenGL interpolation types, here bi-cubic interpolation is implemented through GLSL shader.   

OpenGL GL_NEAREST Interpolation.  

GL_NEAREST just copies data available in nearest pixel and it create a blocky effect when zoom to high region. In nearest interpolation, intermediate pixels are created with nearest valid pixel. This kind of interpolated image will be blocky since same data is copied to intermediate pixels.

Below image is created through opengl GL_NEAREST interpolation and its quality is very bad.

We can use the following code to achieve nearest interpolation in opengl fixed function pipeline. 

glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

 GL_Nearest.jpg

Interpolation with GL_NEAREST interpolation type. 

OpenGL GL_LINEAR Interpolation. 

OpenGL provides a good interpolation method, GL_LINEAR. It interpolates nearest 4 pixels and creates a smooth image comparing to the GL_NEAREST method. This method interpolate both in X direction and Y direction. Therefore it called Bi-Linear interpolation.  

The following code can be used to achieve Bi-Linear interpolation in openGL fixed function pipeline. 

glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 

The following image is created through GL_LINEAR interpolation and its edges are smooth when comparing to the image created through GL_NEAREST interpolation.

 GLLinear.jpg

Interpolation with GL_LINEAR interpolation type. 

GLSL Bi-Linear 

OpenGL provides only two interpolations methods to zoom an image. These interpolation methods are not enough when a small image is zoomed to large area. We can see small blocky effect in the above image ( GL_LINEAR ).

The first step is to create a GLSL shader for Bi-Linear interpolation. This interpolation provides same output of GL_LINEAR.

In Bi-Linear interpolation nearest four pixels are considered to create an intermediate pixel. 

BiLinearLogic.png

In the above figure an intermediate pixel F(p’,q’) is created by interpolating nearest four texels F(p,q), 

F(p,q+1), F(p+1,q), F(p+1,q+1).  Texel is the term used to indicate an element( similar to pixel) in a texture.

An interpolation factor a, is used in X direction to interpolate F(p,q) and F(p,q+1) as follows.

F(p’’) = a * F(p,q) + (1.0 – a ) F(p, q+1) // Linear interpolation in X direction[Top].
F(p+1’’) = a * F(p+1,q) + (1.0 – a ) F(p+1, q+1) // Linear interpolation in X direction[Bottom]. 

An interpolation factor b, is used in Y direction to interpolate F(p’’)and F(p+1’’) as follows.

 F(p’,q’) = b * F(p’’) + (1.0 - b) *  F(p+1’’)  

Corresponding GLSL shader code.  

// Function to get a texel data from a texture with GL_NEAREST property.
// Bi-Linear interpolation is implemented in this function with the 
// help of nearest four data.
vec4 tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
    vec4 p0q0 = texture2D(textureSampler_i, texCoord_i);
    vec4 p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0));

    vec4 p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY));
    vec4 p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY));

    float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
											 // Fraction near to valid data.

    vec4 pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
    vec4 pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.

    float b = fract( texCoord_i.y * fHeight ); // Get Interpolation factor for Y direction.
    return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}    

GLSL Bi-Cubic 

In this method nearest 16 pixels are used to create an intermediate pixel F(p’q’). 

BiCubicLogic.jpg

Following equation [from Digital Image Processing: PIKS Inside, Third Edition] is used to interpolate nearest 16 pixles.  

BiCubicEquation.png

Where Rc() denotes a bicubic interpolation function such as a cubic B-spline, Traingular, Bell cubic interpolation function.  In this sample I just use a Triangular, Bell, and B-Spline interpolation function. 

On zooming to a large space the intermediate pixels are created with nearest pixels. 

Where F(p’,q’) is an intermediate texel. F(p’,q’) is identified by interpolating nearest 16 pixels. Where a is the offset in X direction, and b is the offset in Y direction from nearest valid data. These offset are considered between 0 and 1. 

Following is a GLSL shader code for bi cubic interpolation. BiCubic function get a texture coordinate (x,y) and returns the interpolated value of nearest 16 texels.  Nearest 16 texels are iterated through 2 for loops from [x-1,y-1] to [x+2, y+2]. For each nearest element an interpolation factor is calculated with the corresponding bi-cubic interpolation function. In this method Triangular() is used to get an interpolation factor. Different versions of Bi-Cubic interpolation[BSpline, Traingular, Bell] can be created by changing Triangular() and its logic. When plotting values from Triangular(), we will get the below image in a triangle form. 

From plotting of triangular function, left most value of X axis is -2 and right most value of X axis is +2. It indicates Triangular function returns lower value for a high input and high value for a low input.  

In BiCubic(), the nearest data get a high weightage[From Triangular()] and farthest pixel get a low weightage. In effect an intermediate pixel is created by interpolating nearest 16 data. The weightage will be higher for nearest pixels. The output image of Triangular Bi-Cubic is smoother than Bi-Linear . 

Following code is a GLSL implementation of Bi-Cubic interpolation. 

vec4 BiCubic( sampler2D textureSampler, vec2 TexCoord )
{
    float texelSizeX = 1.0 / fWidth; //size of one texel 
    float texelSizeY = 1.0 / fHeight; //size of one texel 
    vec4 nSum = vec4( 0.0, 0.0, 0.0, 0.0 );
    vec4 nDenom = vec4( 0.0, 0.0, 0.0, 0.0 );
    float a = fract( TexCoord.x * fWidth ); // get the decimal part
    float b = fract( TexCoord.y * fHeight ); // get the decimal part
    for( int m = -1; m <=2; m++ )
    {
        for( int n =-1; n<= 2; n++)
        {
			vec4 vecData = texture2D(textureSampler, TexCoord + vec2(texelSizeX * float( m ), texelSizeY * float( n )));
			float f  = Triangular( float( m ) - a );
			vec4 vecCooef1 = vec4( f,f,f,f );
			float f1 = Triangular ( -( float( n ) - b ) );
			vec4 vecCoeef2 = vec4( f1, f1, f1, f1 );
            nSum = nSum + ( vecData * vecCoeef2 * vecCooef1  );
            nDenom = nDenom + (( vecCoeef2 * vecCooef1 ));
        }
    }
    return nSum / nDenom;
}   

Implementation of Bi-Cubic Interpolation[ Triangular ]

Triangular function is a simple bi-cubic function, as defined in the following equation. 

TriangularEquation.png

TriangularCurve.png

 float Triangular( float f )
{
	f = f / 2.0;
	if( f < 0.0 )
	{
		return ( f + 1.0 );
	}
	else
	{
		return ( 1.0 - f );
	}
	return 0.0;
}

 TriangularZoom.jpg

Interpolation with GLSL BiCubic Triangular interpolation type. 

Implementation of Bi-Cubic Interpolation[ Bell]  

When comparing the Bi-Cubic Triangular image with Bi-Linear, the edges are blurred. The reason of this edge is weightage provided for nearest and farthest data. If weightage to nearest data is high and far pixels are very low, then Bi-Cubic interpolation can achieve a smooth edges.  Another Bi-cubic interpolation funciton which creates a bell shaped( nearest vaues[Center] are high) and far values are low[left and right ends]. 

BellEquation.png

BellCurve.png

float BellFunc( float x )
{
	float f = ( x / 2.0 ) * 1.5; // Converting -2 to +2 to -1.5 to +1.5
	if( f > -1.5 && f < -0.5 )
	{
		return( 0.5 * pow(f + 1.5, 2.0));
	}
	else if( f > -0.5 && f < 0.5 )
	{
		return 3.0 / 4.0 - ( f * f );
	}
	else if( ( f > 0.5 && f < 1.5 ) )
	{
		return( 0.5 * pow(f - 1.5, 2.0));
	}
	return 0.0;
} 

 BellZoom.jpg

Interpolation with BiCubic Bell interpolation type. 

Implementation of Bi-Cubic Interpolation[ B-Spline]  

When comparing the Bi-Cubic Bell shaped, B spline is smoother and edges are more clear. Below equation is used to create BSpline() function. 

BSplineEquation.png

BSplineCurve.png

float BSpline( float x )
{
	float f = x;
	if( f < 0.0 )
	{
		f = -f;
	}

	if( f >= 0.0 && f <= 1.0 )
	{
		return ( 2.0 / 3.0 ) + ( 0.5 ) * ( f* f * f ) - (f*f);
	}
	else if( f > 1.0 && f <= 2.0 )
	{
		return 1.0 / 6.0 * pow( ( 2.0 - f  ), 3.0 );
	}
	return 1.0;
}

 BSplineZoom.jpg

Interpolation with BiCubic BSpline interpolation type. 

About ZoomInterpolation Application: 

ZoomInterpolation is a sample application created to demonstrate different interpolation methods. On startup it creates a texture with a bitmap [Flower.bmp] available in resource of this application.  

This application displays two images, zoomed image is in left, and actual image is at right side. A red rectangle indicates the zoomed image. Small area of image is selected for texture mapping and displayed to screen.  

Pan operation:   

When mouse clicks on zoomed image and pans, the texture mapping region changes with respect to mouse move and it creates a pan effect. 

Zoom and UnZoom: 

When Mouse scroll, the zoom/unzoom is implemented by increasing or decreasing the texture mapping area. CZoomInterpolationDlg::HandleZoom() handles zoom and unzoom. Two buttons “Zoom+” and “Zoom-“ is also added to increase zoom or decrease zoom. I need these buttons to zoom or unzoom in my laptop.

Loading new Image: 

A button “Load Image” is available to load an image file from your machine. This image area is created in an aspect ratio of 4:3 and therefore input image is expected in an aspect ratio of 4:3 for better output image. Otherwise stretched/skewed image will be displayed. BMPLoader class is used to retrieve RGB data from bitmap with the help of Gdi+ library. This class supports different image extensions such as .bmp, .jpg, .png, .tga etc.

Plotting of Interpolation Curve: 

A simple class is created to plot the curve indicating weights applied in current Bi-Cubic interpolation function. Triangular, Bell, and BSpline are plotted with the same code of glsl shader code.  

Limitations:   

1) The input image is expected in an aspect ratio of 4:3 for better output image. Otherwise stretched/skewed image will be displayed. 
2) For GLSL shader implementation, Some opengl following extensions are required in your machine.   
a. GL_ARB_fragment_shader 
b. GL_ARB_vertex_shader  
If your machine do-not have supporting graphics device, this application will display interpolation with openGL fixed function pipeline(Nearest and Linear).

3) The shaders for different bi-cubic and Bi-linear interpolation is prepared with the help some equations, I expect some issues in this code. 

References: 

History 

  1. 07-Aug-2011: Initial Version.   

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Santhosh G_

India India
No Biography provided

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
GeneralMessage Automatically Removed PinmemberMember 103334182-Nov-13 23:44 
Questionthanls Pinmemberarefqq17-Aug-13 6:30 
SuggestionFew remarks PinmemberDanny Ruijters28-Jul-13 23:44 
QuestionWindow Level and Window Width PinmemberHay Hoang Van1-Jun-13 6:42 
QuestionHi Can't Make it work with Texture Rectangle Pinmemberabhishek_bansal14-Apr-13 1:00 
GeneralMy vote of 5 PinmemberBartlomiej Filipek22-Mar-13 4:19 
GeneralRe: My vote of 5 PinmemberSanthosh G_22-Mar-13 5:00 
GeneralMy vote of 5 PinmemberFrans Vander Meiren7-Nov-12 23:57 
GeneralRe: My vote of 5 PinmemberSanthosh G_8-Nov-12 13:54 
QuestionCould this project have Windows Forms Csharp version? urgent PinmemberMichael Lev31-Oct-12 16:34 
AnswerRe: Could this project have Windows Forms Csharp version? urgent PinmemberSanthosh_G31-Oct-12 18:53 
AnswerRe: Could this project have Windows Forms Csharp version? urgent PinmemberKarstenK25-Jul-14 8:27 
GeneralMy vote of 5 Pinmembergndnet8-Oct-12 5:06 
GeneralRe: My vote of 5 PinmemberSanthosh_G8-Oct-12 5:10 
GeneralOptimizing calculations Pinmemberaquiles.geo10-Aug-12 19:49 
Questionnegative and grayscale PinmemberHay Hoang Van16-Jul-12 0:34 
AnswerRe: negative and grayscale PinmemberSanthosh_G23-Jul-12 7:24 
GeneralMy vote of 5 Pinmembermanoj kumar choubey20-Feb-12 20:56 
QuestionMy vote of 4 PinmemberGazoo10130-Jan-12 5:17 
AnswerRe: My vote of 4 PinmemberSanthosh_G30-Jan-12 7:59 
GeneralMy vote of 5 PinmemberMatonga11-Jan-12 19:00 
GeneralRe: My vote of 5 PinmemberSanthosh_G30-Jan-12 8:00 
Questionvery nice PinmemberCIDev20-Sep-11 4:01 
AnswerRe: very nice PinmemberSanthosh G_8-Nov-12 13:55 
GeneralMy vote of 5 PingroupSaraf Talukder6-Sep-11 10:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 7 Aug 2011
Article Copyright 2011 by Santhosh G_
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid