Reputation: 43
I am writing a code to convert an Image that is in the format of RGB
RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB
trying to convert to a gray scale img,but Its not working. i get a picture which is not coloured, but not as expected. more like black-white and not gray.
struct Img {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
void convernt(Img *image)
{
int x,y,i, iRow;
char* p = image->data;
int width=image->sizeX;
int height=image->sizeY;
int rowSize = width*3; // number of bytes in one row
int iPix;
for ( y = 0; y < height; ++y)
{
iRow = y*rowSize ; // index of first pixel in row y
for ( x = 0; x < rowSize; x+=3)
{
iPix = iRow + x*3; // index of pixel
double con=0.2989*p[iPix]+ 0.5870*p[iPix+1]+0.1140*p[iPix+2];
p[iPix] = con;
p[iPix+1] = con;
p[iPix+2] = con;
}
}
}
I want the code to be equal to this one but to be shorter Should do exactly the same I guess i missed something
#define NUM_OF_COLORS 256
// perform histogram equalization algorithm on an image
void convert(Img *image)
{
int i,j;
double* orgHist = (double*)malloc(NUM_OF_COLORS*sizeof(double));
unsigned char* conversionVector = (unsigned char*)malloc(NUM_OF_COLORS);
//clear the vector
for (i=0; i<NUM_OF_COLORS; i++) {
orgHist[i] = 0;
}
//get the histogram of the image
for (j=0; j<image->sizeY; j++) {
for (i=0; i<image->sizeX; i++) {
orgHist[(unsigned char)image->data[3*i + 3*j*image->sizeX + 1]]++;
}
}
//calculate the accumulated histogram of the image
for (i=1; i<NUM_OF_COLORS; i++) {
orgHist[i] = orgHist[i] + orgHist[i-1];
}
//normalize the histogram
for (i=0; i<NUM_OF_COLORS; i++) {
orgHist[i] = orgHist[i]/(image->sizeX*image->sizeY);
conversionVector[i] = 0;
}
// preform the histogram equalization algorithm
i = 0;
j = 0;
while (i<NUM_OF_COLORS) {
if ((((double)j+1)/256) < orgHist[i]) {
j++;
} else {
conversionVector[i] = j;
i++;
}
}
// apply the conversion vector on the image
for (i=0; i<image->sizeX; i++) {
for (j=0; j<image->sizeY; j++) {
image->data[3*i + 3*j*image->sizeX + 1] =
conversionVector[(unsigned char)image->data[3*i + 3*j*image->sizeX + 1]];
}
}
// copy G values to R&B
for (i = 0; i < image->sizeX*image->sizeY; i++) {
image->data[3*i] = image->data[3*i+1];
image->data[3*i+2]= image->data[3*i+1];
}
free(orgHist);
free(conversionVector);
}
Upvotes: 0
Views: 149
Reputation: 211219
Either you increment x
by 3
in your for
loop, or you add x*3
to the index. But do not both.:
for ( x = 0; x < rowSize; x+=3)
// ^^^ either x++ ...
{
iPix = iRow + x*3; // index of pixel
// ^^ ... or iRow + x;
...
}
Because rowSize
is number of bytes and not number number of pixels, adapt your code like this:
for ( x = 0; x < rowSize; x+=3 )
{
iPix = iRow + x; // index of pixel
double con = 0.2989*p[iPix] + 0.5870*p[iPix+1] + 0.1140*p[iPix+2];
p[iPix] = (char)con;
p[iPix+1] = (char)con;
p[iPix+2] = (char)con;
}
Here a solution for large images:
#define NUM_OF_COLORS 256
unsigned char rTable[NUM_OF_COLORS];
unsigned char gTable[NUM_OF_COLORS];
unsigned char bTable[NUM_OF_COLORS];
void initTables()
{
for ( int c = 0; c < NUM_OF_COLORS; c ++ )
{
rTable[c] = (unsigned char)(0.2989*c);
gTable[c] = (unsigned char)(0.5870*c);
bTable[c] = (unsigned char)(0.1140*c);
}
}
void convernt(struct Img *image)
{
unsigned char* p = (unsigned char*)image->data;
int width=image->sizeX;
int height=image->sizeY;
int rowSize = width*3; // number of bytes in one row
for ( int y = 0; y < height; ++y)
{
int iRow = y*rowSize ; // index of first pixel in row y
for ( int x = 0; x < rowSize; x+=3 )
{
int iPix = iRow + x; // index of pixel
unsigned char col = rTable[p[iPix]] + gTable[p[iPix+1]] + bTable[p[iPix+2]];
p[iPix] = col;
p[iPix+1] = col;
p[iPix+2] = col;
}
}
}
Upvotes: 3