Click here to Skip to main content
13,090,730 members (44,344 online)
Click here to Skip to main content
Add your own
alternative version


106 bookmarked
Posted 6 Aug 2011

Zoom an image with different interpolation types.

, 6 Aug 2011
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 


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


Screenshot of ZoomInterpolation Application. 


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. 



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. 


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


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. 


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’). 


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


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. 



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


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].<o:p /> 



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;


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. 



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;


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.  


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. <span class="Apple-style-span" style="font-weight: normal; ">GL_ARB_vertex_shader</span>  
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. 



  1. 07-Aug-2011: Initial Version.   


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


About the Author

Santhosh G_
India India
No Biography provided

You may also be interested in...


Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.
QuestionBiCubic() works in OpenGL 3.3 but not in 4.4 Pin
Member 1322899929-May-17 4:06
memberMember 1322899929-May-17 4:06 
AnswerRe: BiCubic() works in OpenGL 3.3 but not in 4.4 Pin
Member 1322899930-May-17 11:42
memberMember 1322899930-May-17 11:42 
Questiongreat code and tutorial. Thanks! Pin
gilad bu14-Jun-16 2:17
membergilad bu14-Jun-16 2:17 
QuestionShift issue Pin
josejonasj17-Mar-15 4:54
memberjosejonasj17-Mar-15 4:54 
AnswerRe: Shift issue Pin
Julia Breger9-Jun-15 22:43
memberJulia Breger9-Jun-15 22:43 
GeneralRe: Shift issue Pin
gilad bu14-Jun-16 2:18
membergilad bu14-Jun-16 2:18 
GeneralMessage Closed Pin
2-Nov-13 22:44
memberMember 103334182-Nov-13 22:44 
Questionthanls Pin
arefqq17-Aug-13 5:30
memberarefqq17-Aug-13 5:30 
SuggestionFew remarks Pin
Danny Ruijters28-Jul-13 22:44
memberDanny Ruijters28-Jul-13 22:44 
QuestionWindow Level and Window Width Pin
Hay Hoang Van1-Jun-13 5:42
memberHay Hoang Van1-Jun-13 5:42 
QuestionHi Can't Make it work with Texture Rectangle Pin
abhishek_bansal14-Apr-13 0:00
memberabhishek_bansal14-Apr-13 0:00 
GeneralMy vote of 5 Pin
Bartlomiej Filipek22-Mar-13 3:19
memberBartlomiej Filipek22-Mar-13 3:19 
GeneralRe: My vote of 5 Pin
Santhosh G_22-Mar-13 4:00
memberSanthosh G_22-Mar-13 4:00 
GeneralMy vote of 5 Pin
Frans Vander Meiren7-Nov-12 22:57
memberFrans Vander Meiren7-Nov-12 22:57 
GeneralRe: My vote of 5 Pin
Santhosh G_8-Nov-12 12:54
memberSanthosh G_8-Nov-12 12:54 
QuestionCould this project have Windows Forms Csharp version? urgent Pin
Michael Lev31-Oct-12 15:34
memberMichael Lev31-Oct-12 15:34 
AnswerRe: Could this project have Windows Forms Csharp version? urgent Pin
Santhosh_G31-Oct-12 17:53
memberSanthosh_G31-Oct-12 17:53 
AnswerRe: Could this project have Windows Forms Csharp version? urgent Pin
KarstenK25-Jul-14 7:27
memberKarstenK25-Jul-14 7:27 
GeneralMy vote of 5 Pin
gndnet8-Oct-12 4:06
membergndnet8-Oct-12 4:06 
GeneralRe: My vote of 5 Pin
Santhosh_G8-Oct-12 4:10
memberSanthosh_G8-Oct-12 4:10 
GeneralOptimizing calculations Pin
aquiles.geo10-Aug-12 18:49
memberaquiles.geo10-Aug-12 18:49 
Questionnegative and grayscale Pin
Hay Hoang Van15-Jul-12 23:34
memberHay Hoang Van15-Jul-12 23:34 
AnswerRe: negative and grayscale Pin
Santhosh_G23-Jul-12 6:24
memberSanthosh_G23-Jul-12 6:24 
GeneralMy vote of 5 Pin
manoj kumar choubey20-Feb-12 19:56
membermanoj kumar choubey20-Feb-12 19:56 
QuestionMy vote of 4 Pin
Gazoo10130-Jan-12 4:17
memberGazoo10130-Jan-12 4:17 

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

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

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