Reputation: 63
"Using CImg, write a program that constructs a square image and assigns a color to each corner. Using linear interpolation, fill in and color each pixel in the square so that there is a smooth coloring across the entire area of the square"
I have a hard time to understand how to pick a color for each corner, and fill in color for the square. Below is the code that I have, but it seems randomly place the color, and I cannot pick my own color. Below the code I have right now.
#include <iostream>
#include "CImg/CImg.h"
using namespace cimg_library;
using namespace std;
int main() {
//Create an empty image
CImg<unsigned char> square(255, 255, 1, 3, 0);
for (int i = 0; i < 255; i++){
for(int j = 0; j < 255; j++){
//Red
square(i,j,0,0) = i;
//Green
square(i,j,0,1) = j;
//Blue
square(i,j,0,2) = i;
}
}
//Display and save filtered image
CImgDisplay disp(square);
while (!disp.is_closed())
disp.wait();
square.save("squareInterpolation.bmp");
}
Result from my code:
Result I wanted (ignore the white border):
Thank you so much!
Upvotes: 2
Views: 1727
Reputation: 207455
At the moment, your code isn't doing any interpolation - it is just assigning. Interpolation is where you know some values at the limits of an image and calculate the values in-between those known values (using a formula) to fill in the unknown values.
Actually, CImg
will do interpolation for you and, IMHO, good engineers re-use and recycle well-tested code as it keeps costs down. So, the simplest solution is to create a 2x2 image of the red, green, blue and white corner points (the known values in the interpolation) and let CImg
resize your image up to 255x255 using interpolation.
That could look like this:
#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;
using namespace std;
#define INTERPOLATION_LINEAR 3
#define INTERPOLATION_CUBIC 5
#define BOUNDARY_DIRICHLET 0
#define BOUNDARY_NEUMANN 1
int main() {
// Create 2x2 image with Red, Green, Blue and White pixels
CImg<unsigned char> image(2,2,1,3,0);
image(0,0,0,0)=255; // top-left is Red
image(1,0,0,1)=255; // top-right is Green
image(0,1,0,2)=255; // bottom-left is Blue
image(1,1,0,0)=255; // bottom-right is white
image(1,1,0,1)=255; // bottom-right is white
image(1,1,0,2)=255; // bottom-right is white
// Let CImg do the interpolation for us - because smart engineers re-use well tested code
CImg<unsigned char> result=image.resize(255,255,-100,-100,INTERPOLATION_LINEAR,BOUNDARY_DIRICHLET);
// Save result image as NetPBM PNM - no libraries required
result.save_pnm("result.pnm");
}
I guess that is not the way you are expected to do it, so I would combine that solution with a further one where I implemented the interpolation myself. Here is a formula you might use from the Wikipedia article on Bilinear Interpolation.
That could be implemented to like this:
#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;
using namespace std;
int main() {
// Create 256x256 image with Red, Green, Blue and White pixels
CImg<unsigned char> image(256,256,1,3,0);
image(0,0,0,0)=255; // top-left is Red
image(255,0,0,1)=255; // top-right is Green
image(0,255,0,2)=255; // bottom-left is Blue
image(255,255,0,0)=255; // bottom-right is white
image(255,255,0,1)=255; // bottom-right is white
image(255,255,0,2)=255; // bottom-right is white
// Fill inner area by interpolation
for(int r=0;r<256;r++){ // "r" for "row"
for(int c=0;c<256;c++){ // "c" for "column"
for(int b=0;b<3;b++){ // "b" for "band" in my head
float oneMinusX=(255-r)/255.0;
float oneMinusY=(255-c)/255.0;
image(r,c,0,b)=image(0,0,0,b)*oneMinusX*oneMinusY +
image(255,0,0,b)*oneMinusY*r/255.0 +
image(0,255,0,b)*oneMinusX*c/255.0 +
image(255,255,0,b)*r*c/(255.0*255.0);
}
}
}
// Save result image as NetPBM PNM - no libraries required
image.save_pnm("result.pnm");
}
Upvotes: 1