I'm trying to downscale an image from a large size (as large as 960x960) to possibly as small as 32x32. I have the following code I use to get the raw pixels:
Image* img = new Image();
img->initWithImageFile(fileNameWithPath);
int x=3;
if(img->hasAlpha()){
x=4;
}
unsigned char *data = new unsigned char[img->getDataLen()*x];
data = img->getData();
// [0][0] => Left-Top Pixel !
// But cocos2d Location Y-axis is Bottom(0) to Top(max)
//This is for changing pixels in the original image
//Skip this loop if there are no changes to be made (converting to grayscale etc).
for(int i=0;i<img->getWidth();i++)
{
for(int j=0;j<img->getHeight();j++)
{
unsigned char *pixel = data + (i + j * img->getWidth()) * x;
// You can see/change pixels' RGBA value(0-255) here !
unsigned char r = *pixel;
unsigned char g = *(pixel + 1);
unsigned char b = *(pixel + 2) ;
unsigned char a = *(pixel + 3);
//pixel[2] = 255; //Example: Setting the blue component to 255
}
}
I can create an output image by doing:
int width = scale*img->getWidth();
int height = scale*img->getHeight();
Image* scaledImage = new Image();
auto dataLen = width * height * x * sizeof(unsigned char);
auto data2 = static_cast<unsigned char*>(malloc(dataLen));
scaledImage->initWithRawData(data2, dataLen, width, height, 8);
And I can set the individual pixels of the output image by doing:
unsigned char *pixel2 = data2 + (i + j * width) * x;
The question is how to average / interpolate the pixels from the original image efficiently (using minimum cpu and memory, with the preference to use more cpu if necessary and less memory).
Challenges:
- The downscaled image and the original image may not be perfect multiples.
- The downscaled image can be as small as 0.1 of the original image size.
- most images will be downscaled to 0.4 to 0.1 of the original image, so these are the most important ranges.
EDIT: If you think some other interpolation algorithm would be better suited (instead of bilinear) then I am open to it. The challenge is writing an efficient algorithm to average / interpolate the individual pixels..
How do I interpolate the individual pixels of the original image ?