patterncMinor
Bilinear interpolation
Viewed 0 times
bilinearinterpolationstackoverflow
Problem
The following code is to enlarge pictures using bilinear interpolation. What can be modified in the function of
```
unsigned char slow_rescale(unsigned char src, int src_x, int src_y, int dest_x, int dest_y)
{
double step_x,step_y; // Step increase as per instructions above
unsigned char R1,R2,R3,R4; // Colours at the four neighbours
unsigned char G1,G2,G3,G4;
unsigned char B1,B2,B3,B4;
double RT1, GT1, BT1; // Interpolated colours at T1 and T2
double RT2, GT2, BT2;
unsigned char R,G,B; // Final colour at a destination pixel
unsigned char *dst; // Destination image - must be allocated here!
int x,y; // Coordinates on destination image
double fx,fy; // Corresponding coordinates on source image
double dx,dy; // Fractional component of source image coordinates
dst=(unsigned char )calloc(dest_xdest_y*3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
step_x=(double)(src_x-1)/(double)(dest_x-1);
step_y=(double)(src_y-1)/(double)(dest_y-1);
for (x=0;x<dest_x;x++) // Loop over destination image
for (y=0;y<dest_y;y++)
{
fx=x*step_x;
fy=y*step_y;
dx=fx-(int)fx;
dy=fy-(int)fy;
getPixel(src,floor(fx),floor(fy),src_x,&R1,&G1,&B1); // get N1 colours
getPixel(src,ceil(fx),floor(fy),src_x,&R2,&G2,&B2); // get N2 colours
getPixel(src,floor(fx),ceil(fy),src_x,&R3,&G3,&B3); // get N3 colours
getPixel(src,ceil(fx),ceil(fy),src_x,&R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
RT1=(dxR2)+(1-dx)R1;
GT1=(dxG2)+(1-dx)G1;
BT1=(dxB2)+(1-dx)B1;
RT2=(dxR4)+(1-dx)R3;
GT2=(dxG4)+(1-dx)G3;
BT2=(dxB4)+(1-dx)B3;
// Obtain final colour by interpolating between T1 and T2
R=(unsigned char)((dy*RT2)+
slow_rescale to make it more efficient? I expect to modify it from the view of Principles of Computer Organization.```
unsigned char slow_rescale(unsigned char src, int src_x, int src_y, int dest_x, int dest_y)
{
double step_x,step_y; // Step increase as per instructions above
unsigned char R1,R2,R3,R4; // Colours at the four neighbours
unsigned char G1,G2,G3,G4;
unsigned char B1,B2,B3,B4;
double RT1, GT1, BT1; // Interpolated colours at T1 and T2
double RT2, GT2, BT2;
unsigned char R,G,B; // Final colour at a destination pixel
unsigned char *dst; // Destination image - must be allocated here!
int x,y; // Coordinates on destination image
double fx,fy; // Corresponding coordinates on source image
double dx,dy; // Fractional component of source image coordinates
dst=(unsigned char )calloc(dest_xdest_y*3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
step_x=(double)(src_x-1)/(double)(dest_x-1);
step_y=(double)(src_y-1)/(double)(dest_y-1);
for (x=0;x<dest_x;x++) // Loop over destination image
for (y=0;y<dest_y;y++)
{
fx=x*step_x;
fy=y*step_y;
dx=fx-(int)fx;
dy=fy-(int)fy;
getPixel(src,floor(fx),floor(fy),src_x,&R1,&G1,&B1); // get N1 colours
getPixel(src,ceil(fx),floor(fy),src_x,&R2,&G2,&B2); // get N2 colours
getPixel(src,floor(fx),ceil(fy),src_x,&R3,&G3,&B3); // get N3 colours
getPixel(src,ceil(fx),ceil(fy),src_x,&R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
RT1=(dxR2)+(1-dx)R1;
GT1=(dxG2)+(1-dx)G1;
BT1=(dxB2)+(1-dx)B1;
RT2=(dxR4)+(1-dx)R3;
GT2=(dxG4)+(1-dx)G3;
BT2=(dxB4)+(1-dx)B3;
// Obtain final colour by interpolating between T1 and T2
R=(unsigned char)((dy*RT2)+
Solution
Please make everyone (including yourself) a favor :
Then you'd get something like :
Then, try to compute things once and only once when possible and you'll get something like :
```
unsigned char slow_rescale(unsigned char src, int src_x, int src_y, int dest_x, int dest_y)
{
unsigned char dst=(unsigned char )calloc(dest_xdest_y3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
double step_x=(double)(src_x-1)/(double)(dest_x-1);
double step_y=(double)(src_y-1)/(double)(dest_y-1);
for (int x=0;x<dest_x;x++) // Loop over destination image
{
double fx=x*step_x;
double dx=fx-(int)fx;
int ffx = floor(fx);
int cfx = ceil(fx);
for (int y=0;y<dest_y;y++)
{
double fy=y*step_y;
double dy=fy-(int)fy;
int ffy = floor(fy);
int cfy = ceil(fy);
unsigned char R1,R2,R3,R4,G1,G2,G3,G4,B1,B2,B3,B4;
getPixel(src, (ffx + ffysrc_x)3, &R1,&G1,&B1); // get N1 colours
getPixel(src, (cfx + ffysrc_x)3, &R2,&G2,&B2); // get N2 colours
getPixel(src, (ffx + cfysrc_x)3, &R3,&G3,&B3); // get N3 colours
getPixel(src, (cfx + cfysrc_x)3, &R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
double RT1 = dxR2 + (1-dx)R1;
double GT1 = dxG2 + (1-dx)G1;
double BT1 = dxB2 + (1-dx)B1;
double RT2 = dxR4 + (1-dx)R3;
double GT2 = dxG4 + (1-dx)G3;
double BT2 = dxB4 + (1-dx)B3;
// Obtain final colour by interpolating between T1 and T2
unsigned char R = dyRT2 + (1-dy)RT1;
unsigned char G = dyGT2 + (1-dy)GT1;
unsigned char B = dyBT2 + (1-dy)BT1;
// Store the final colour
setPixel(dst, (x + ydest_x)3,R,G,B);
}
}
return(dst);
}
inline void getPixel(unsigned char image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
*R=image[offset+0];
*G=image[offset+1];
*B=image[offset+2];
}
inline void setPixel(unsigned char *image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
image[offset+0]=R
- Declare your variable in the smallest possible scope. Also define them as your declare them if you can (and you usually can).
- Indent your code properly.
Then you'd get something like :
unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y)
{
unsigned char* dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
double step_x=(double)(src_x-1)/(double)(dest_x-1);
double step_y=(double)(src_y-1)/(double)(dest_y-1);
for (int x=0;x<dest_x;x++) // Loop over destination image
{
for (int y=0;y<dest_y;y++)
{
double fx=x*step_x;
double fy=y*step_y;
double dx=fx-(int)fx;
double dy=fy-(int)fy;
unsigned char R1,R2,R3,R4; // Colours at the four neighbours
unsigned char G1,G2,G3,G4;
unsigned char B1,B2,B3,B4;
getPixel(src,floor(fx),floor(fy),src_x,&R1,&G1,&B1); // get N1 colours
getPixel(src,ceil(fx),floor(fy),src_x,&R2,&G2,&B2); // get N2 colours
getPixel(src,floor(fx),ceil(fy),src_x,&R3,&G3,&B3); // get N3 colours
getPixel(src,ceil(fx),ceil(fy),src_x,&R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
double RT1=(dx*R2)+(1-dx)*R1;
double GT1=(dx*G2)+(1-dx)*G1;
double BT1=(dx*B2)+(1-dx)*B1;
double RT2=(dx*R4)+(1-dx)*R3;
double GT2=(dx*G4)+(1-dx)*G3;
double BT2=(dx*B4)+(1-dx)*B3;
// Obtain final colour by interpolating between T1 and T2
unsigned char R=(unsigned char)((dy*RT2)+((1-dy)*RT1));
unsigned char G=(unsigned char)((dy*GT2)+((1-dy)*GT1));
unsigned char B=(unsigned char)((dy*BT2)+((1-dy)*BT1));
// Store the final colour
setPixel(dst,x,y,dest_x,R,G,B);
}
}
return(dst);
}
void getPixel(unsigned char *image, int x, int y, int sx, unsigned char *R, unsigned char *G, unsigned char *B)
{
// Get the colour at pixel x,y in the image and return it using the provided RGB pointers
// Requires the image size along the x direction!
*(R)=*(image+((x+(y*sx))*3)+0);
*(G)=*(image+((x+(y*sx))*3)+1);
*(B)=*(image+((x+(y*sx))*3)+2);
}
void setPixel(unsigned char *image, int x, int y, int sx, unsigned char R, unsigned char G, unsigned char B)
{
// Set the colour of the pixel at x,y in the image to the specified R,G,B
// Requires the image size along the x direction!
*(image+((x+(y*sx))*3)+0)=R;
*(image+((x+(y*sx))*3)+1)=G;
*(image+((x+(y*sx))*3)+2)=B;
}Then, try to compute things once and only once when possible and you'll get something like :
```
unsigned char slow_rescale(unsigned char src, int src_x, int src_y, int dest_x, int dest_y)
{
unsigned char dst=(unsigned char )calloc(dest_xdest_y3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
double step_x=(double)(src_x-1)/(double)(dest_x-1);
double step_y=(double)(src_y-1)/(double)(dest_y-1);
for (int x=0;x<dest_x;x++) // Loop over destination image
{
double fx=x*step_x;
double dx=fx-(int)fx;
int ffx = floor(fx);
int cfx = ceil(fx);
for (int y=0;y<dest_y;y++)
{
double fy=y*step_y;
double dy=fy-(int)fy;
int ffy = floor(fy);
int cfy = ceil(fy);
unsigned char R1,R2,R3,R4,G1,G2,G3,G4,B1,B2,B3,B4;
getPixel(src, (ffx + ffysrc_x)3, &R1,&G1,&B1); // get N1 colours
getPixel(src, (cfx + ffysrc_x)3, &R2,&G2,&B2); // get N2 colours
getPixel(src, (ffx + cfysrc_x)3, &R3,&G3,&B3); // get N3 colours
getPixel(src, (cfx + cfysrc_x)3, &R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
double RT1 = dxR2 + (1-dx)R1;
double GT1 = dxG2 + (1-dx)G1;
double BT1 = dxB2 + (1-dx)B1;
double RT2 = dxR4 + (1-dx)R3;
double GT2 = dxG4 + (1-dx)G3;
double BT2 = dxB4 + (1-dx)B3;
// Obtain final colour by interpolating between T1 and T2
unsigned char R = dyRT2 + (1-dy)RT1;
unsigned char G = dyGT2 + (1-dy)GT1;
unsigned char B = dyBT2 + (1-dy)BT1;
// Store the final colour
setPixel(dst, (x + ydest_x)3,R,G,B);
}
}
return(dst);
}
inline void getPixel(unsigned char image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
*R=image[offset+0];
*G=image[offset+1];
*B=image[offset+2];
}
inline void setPixel(unsigned char *image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
image[offset+0]=R
Code Snippets
unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y)
{
unsigned char* dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
double step_x=(double)(src_x-1)/(double)(dest_x-1);
double step_y=(double)(src_y-1)/(double)(dest_y-1);
for (int x=0;x<dest_x;x++) // Loop over destination image
{
for (int y=0;y<dest_y;y++)
{
double fx=x*step_x;
double fy=y*step_y;
double dx=fx-(int)fx;
double dy=fy-(int)fy;
unsigned char R1,R2,R3,R4; // Colours at the four neighbours
unsigned char G1,G2,G3,G4;
unsigned char B1,B2,B3,B4;
getPixel(src,floor(fx),floor(fy),src_x,&R1,&G1,&B1); // get N1 colours
getPixel(src,ceil(fx),floor(fy),src_x,&R2,&G2,&B2); // get N2 colours
getPixel(src,floor(fx),ceil(fy),src_x,&R3,&G3,&B3); // get N3 colours
getPixel(src,ceil(fx),ceil(fy),src_x,&R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
double RT1=(dx*R2)+(1-dx)*R1;
double GT1=(dx*G2)+(1-dx)*G1;
double BT1=(dx*B2)+(1-dx)*B1;
double RT2=(dx*R4)+(1-dx)*R3;
double GT2=(dx*G4)+(1-dx)*G3;
double BT2=(dx*B4)+(1-dx)*B3;
// Obtain final colour by interpolating between T1 and T2
unsigned char R=(unsigned char)((dy*RT2)+((1-dy)*RT1));
unsigned char G=(unsigned char)((dy*GT2)+((1-dy)*GT1));
unsigned char B=(unsigned char)((dy*BT2)+((1-dy)*BT1));
// Store the final colour
setPixel(dst,x,y,dest_x,R,G,B);
}
}
return(dst);
}
void getPixel(unsigned char *image, int x, int y, int sx, unsigned char *R, unsigned char *G, unsigned char *B)
{
// Get the colour at pixel x,y in the image and return it using the provided RGB pointers
// Requires the image size along the x direction!
*(R)=*(image+((x+(y*sx))*3)+0);
*(G)=*(image+((x+(y*sx))*3)+1);
*(B)=*(image+((x+(y*sx))*3)+2);
}
void setPixel(unsigned char *image, int x, int y, int sx, unsigned char R, unsigned char G, unsigned char B)
{
// Set the colour of the pixel at x,y in the image to the specified R,G,B
// Requires the image size along the x direction!
*(image+((x+(y*sx))*3)+0)=R;
*(image+((x+(y*sx))*3)+1)=G;
*(image+((x+(y*sx))*3)+2)=B;
}unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y)
{
unsigned char* dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char)); // Allocate and clear destination image
if (!dst) return(NULL); // Unable to allocate image
double step_x=(double)(src_x-1)/(double)(dest_x-1);
double step_y=(double)(src_y-1)/(double)(dest_y-1);
for (int x=0;x<dest_x;x++) // Loop over destination image
{
double fx=x*step_x;
double dx=fx-(int)fx;
int ffx = floor(fx);
int cfx = ceil(fx);
for (int y=0;y<dest_y;y++)
{
double fy=y*step_y;
double dy=fy-(int)fy;
int ffy = floor(fy);
int cfy = ceil(fy);
unsigned char R1,R2,R3,R4,G1,G2,G3,G4,B1,B2,B3,B4;
getPixel(src, (ffx + ffy*src_x)*3, &R1,&G1,&B1); // get N1 colours
getPixel(src, (cfx + ffy*src_x)*3, &R2,&G2,&B2); // get N2 colours
getPixel(src, (ffx + cfy*src_x)*3, &R3,&G3,&B3); // get N3 colours
getPixel(src, (cfx + cfy*src_x)*3, &R4,&G4,&B4); // get N4 colours
// Interpolate to get T1 and T2 colours
double RT1 = dx*R2 + (1-dx)*R1;
double GT1 = dx*G2 + (1-dx)*G1;
double BT1 = dx*B2 + (1-dx)*B1;
double RT2 = dx*R4 + (1-dx)*R3;
double GT2 = dx*G4 + (1-dx)*G3;
double BT2 = dx*B4 + (1-dx)*B3;
// Obtain final colour by interpolating between T1 and T2
unsigned char R = dy*RT2 + (1-dy)*RT1;
unsigned char G = dy*GT2 + (1-dy)*GT1;
unsigned char B = dy*BT2 + (1-dy)*BT1;
// Store the final colour
setPixel(dst, (x + y*dest_x)*3,R,G,B);
}
}
return(dst);
}
inline void getPixel(unsigned char *image, int offset, unsigned char *R, unsigned char *G, unsigned char *B)
{
*R=image[offset+0];
*G=image[offset+1];
*B=image[offset+2];
}
inline void setPixel(unsigned char *image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
image[offset+0]=R;
image[offset+1]=G;
image[offset+2]=B;
}Context
StackExchange Code Review Q#38423, answer score: 4
Revisions (0)
No revisions yet.