I'm writing a program that creates a mosaic using filler images. I'm having an issue with accessing the private data for the pixels for each filler image. I can get the pixels from the source image (image* displayed) but when I try to get the filler image to size down specific to the block size entered, I lose the data. The filler images need to be resized to the blockheight and blockwidth so that they can properly fit the source image height and width, that is the goal of the resizeFillerImage function. I am using linked links when loading the folder with all the filler images, and I do get the averages right when I load them into the program. The pixel** array is private data within a main Image class that contains the fillerImage class, and I cannot change this, so I need to be able to get the pixels for the filler images and set them to the temporary copy image I create.
Here is my code:
Globals:
image* displayed;
fillerNode* head = NULL;
fillerNode* head2 = NULL;
fillerNode* temp1;
fillerNode* shrinkedList;
//This function will resize each filler image based on the block size
void resizeFillerImage(int blockWidth, int blockHeight)
{
int blockSize = blockWidth * blockHeight;
int avgRed = 0, avgGreen = 0, avgBlue = 0;
image* temp = new image;
temp->createNewImage(displayed->getWidth() / blockWidth, displayed->getHeight() / blockHeight);
pixel** shrinkPix = temp->getPixels(); //THIS IS WHERE I GET THE ERROR
//The pixel numbers get reset instead of being assigned to temp
for (int i = 0; i < displayed->getHeight() / blockHeight; i++)
{
for (int j = 0; j < displayed->getWidth() / blockWidth; j++)
{
for (int k = 0; k < blockHeight; k++)
{
for (int m = 0; m < blockWidth; m++)
{
avgRed = avgRed + shrinkPix[i * blockHeight + k][j * blockWidth + m].red;
avgGreen = avgGreen + shrinkPix[i * blockHeight + k][j * blockWidth + m].green;
avgBlue = avgBlue + shrinkPix[i * blockHeight + k][j * blockWidth + m].blue;
}
}
avgRed = avgRed / blockSize;
avgGreen = avgGreen / blockSize;
avgBlue = avgBlue / blockSize;
shrinkPix[i][j].red = avgRed;
shrinkPix[i][j].green = avgGreen;
shrinkPix[i][j].blue = avgBlue;
avgRed = 0;
avgGreen = 0;
avgBlue = 0;
}
}
for (int i = 0; i < displayed->getHeight(); i++)
{
for (int j = 0; j < displayed->getWidth(); j++)
{
if ((i > displayed->getHeight() / blockHeight) || (j > displayed->getWidth() / blockWidth))
{
shrinkPix[i][j].red = 0;
shrinkPix[i][j].green = 0;
shrinkPix[i][j].blue = 0;
}
}
}
displayed = temp;
return;
}
//This function should generate the photomosaic from the loaded image. Each filler image should represent a section of the original image
//that is blockWidth by blockHeight big.
void generateMosaic(int blockWidth, int blockHeight)
{
for (int i = FIRST_FILLER_NUMBER; i <= LAST_FILLER_NUMBER; i++)
{
shrinkedList = new fillerNode;
fillerImage* tempImage = new fillerImage();
resizeFillerImage(blockHeight, blockHeight);
}
}
Here is the fillerImage class:
fillerImage::fillerImage() //constructor
{
this->timesUsed = 0;
this->averageColor.red = 0;
this->averageColor.green = 0;
this->averageColor.blue = 0;
}
fillerImage::fillerImage(string filename) : image(filename)
{
timesUsed = 0;
}
fillerImage::~fillerImage() //destructor
{
timesUsed = NULL;
averageColor.red = NULL;
averageColor.green = NULL;
averageColor.blue = NULL;
}
void fillerImage::calculateAverageColor() //calcuate the average color assign that color to private member averageColor
{
pixel** pix = getPixels();
int area = FILLER_IMAGE_HEIGHT * FILLER_IMAGE_WIDTH;
int totRed = 0, totGreen = 0, totBlue = 0;
for (int i = 0; i < FILLER_IMAGE_HEIGHT; i++)
{
for (int j = 0; j < FILLER_IMAGE_WIDTH; j++)
{
totRed += pix[i][j].red;
totGreen += pix[i][j].green;
totBlue += pix[i][j].blue;
}
}
averageColor.red = totRed / area;
averageColor.green = totGreen / area;
averageColor.blue = totBlue / area;
}
pixel fillerImage::getAverageColor() //return the average color
{
return this->averageColor;
}
int fillerImage::getTimesUsed() //return how many times this fillerimage has been used
{
return this->timesUsed;
}
void fillerImage::setTimesUsed(int used) //assign "used" to timesUsed
{
this->timesUsed = used;
}
FillerNode struct:
struct fillerNode{
fillerImage *data;
fillerNode *pre;
fillerNode *next;
};
Image Class header:
class image {
public:
image(); //the image constructor (initializes everything)
image(string filename); //a image constructor that directly loads an image from disk
~image(); //the image destructor (deletes the dynamically created pixel array)
void createNewImage(int width, int height); //this function deletes any current image data and creates a new blank image
//with the specified width/height and allocates the needed number of pixels
//dynamically.
bool loadImage(string filename); //load an image from the specified file path. Return true if it works, false if it is not a valid image.
//Note that we only accept images of the RGB 8bit colorspace!
void saveImage(string filename); //Save an image to the specified path
pixel** getPixels(); //return the 2-dimensional pixels array
int getWidth(); //return the width of the image
int getHeight(); //return the height of the image
void viewImage(CImage* myImage); //This function is called by the windows GUI. It returns the image in format the GUI understands.
private:
void pixelsToCImage(CImage* myImage); //this function is called internally by the image class.
//it converts our pixel object array to a standard BGR uchar array with word spacing.
//(Don't worry about what this does)
pixel** pixels; // pixel data array for image
int width, height; // stores the image dimensions
};