Click to See Complete Forum and Search --> : problem displaying a bitmap width not divisible by 4


swetha.bsharma
September 7th, 2008, 03:42 AM
Hello,


I am trying to display a bitmap truecolor image with a width not divisible by 4.


#include <iostream.h>
#include <stdio.h>
#include<stdlib.h>

class ImageBMP
{
public:
int Height;
int Width;
unsigned char *Rinputimage;
unsigned char *Ginputimage;
unsigned char *Binputimage;
unsigned char *Yimage;
unsigned char *Cbimage;
unsigned char *Crimage;
~ImageBMP();
void getimageinfo(FILE*);
void rgb2ycbcr();
void displayycbcrimage(FILE*);

};

ImageBMP::~ImageBMP()
{
delete[]Rinputimage;
delete[]Ginputimage;
delete[]Binputimage;
delete[]Yimage;
delete[]Cbimage;
delete[]Crimage;

}
***************************************************
Reading the image and getting the R,G,B values
***************************************************

void ImageBMP::getimageinfo(FILE* fptr)
{
int fpos , size,fileindex=0,len,rem;
fseek(fptr,18,SEEK_SET);

fpos= ftell(fptr);
fread(&Width,1,4,fptr);
cout<<"The Width is"<<Width<<endl;
fpos = ftell(fptr);
fread(&Height,1,4,fptr);
cout<<"The Height is "<<Height<<endl;

fseek(fptr,28,SEEK_CUR);
fpos=ftell(fptr);

size = Height*Width;



Rinputimage = new unsigned char[size];
Ginputimage = new unsigned char[size];
Binputimage = new unsigned char[size];

while(fileindex<size)
{
fread((Binputimage+fileindex),1,1,fptr);
fpos=ftell(fptr);
fread((Ginputimage+fileindex),1,1,fptr);
fread((Rinputimage+fileindex),1,1,fptr);
fileindex++;

}

fpos=ftell(fptr);

}

**********************************************
Conversion to RGB to ycbcr
**********************************************
void ImageBMP::rgb2ycbcr()
{
int size,fileindex;
size = Height*Width;

Yimage = new unsigned char[size];
Cbimage = new unsigned char[size];
Crimage = new unsigned char[size];

for(fileindex=0;fileindex<size;fileindex++)
{
Yimage[fileindex]= (0.257 *Rinputimage[fileindex]+0.504*Ginputimage[fileindex]+0.098*Binputimage[fileindex]+16);
Cbimage[fileindex]= (-0.148*Rinputimage[fileindex]-0.291*Ginputimage[fileindex]+0.439*Binputimage[fileindex]+128);
Crimage[fileindex]= (0.439*Rinputimage[fileindex]-0.368*Ginputimage[fileindex]-0.071*Binputimage[fileindex]+128);
}


}

**********************************************
display the image in ycbcr format
**********************************************
void ImageBMP::displayycbcrimage(FILE* fptr)
{
int size,fpos,rem=0,row,col,ycbcrindex,addwidth,index,componentsize,filesize;
char *buffer;
unsigned char ycbcr;

FILE *fout = fopen("out.bmp","wb");

;

fseek(fptr,0,SEEK_SET);
buffer = new char[1];
*************************************
Reading and writing the header.
*************************************
for (index=0;index<54;index++)
{
fread(buffer,1,1,fptr);
fwrite(buffer,1,1,fout);

}

fpos=ftell(fout);
****************************
Checking for divisibility by 4.
****************************
if((Width)%4!=0)
{
rem=4-((Width)%4);
}

if(rem!=0)
{
size=Height*Width*3+Width*rem;
}
else
{
size=Height*Width*3;
}

//ycbcr = new unsigned char[1];
ycbcrindex=0;

componentsize=Height*Width;

for (index=0;index<componentsize;index++)
{

ycbcr=Crimage[index];
fwrite(&ycbcr,1,1,fout);
ycbcr=Cbimage[index];
fwrite(&ycbcr,1,1,fout);
ycbcr=Yimage[index];
fwrite(&ycbcr,1,1,fout);

}

if(rem!=0)
{
addwidth=1;

while(addwidth<=rem*Height)
{
ycbcr=0;
fwrite(&ycbcr,1,1,fout);
addwidth++;

}

}


fpos=ftell(fout);
fclose(fout);

// delete[]ycbcr;

}
void main()
{
FILE *fp = fopen("D:\\images\\images\\gun.bmp","rb");



ImageBMP testimage;

testimage.getimageinfo(fp);
testimage.rgb2ycbcr();
testimage.displayycbcrimage(fp);

fclose(fp);
}




The image is displayed with scanlines. I do not know where the mistake is,can someone help me?
-swetha

TheMelter
September 9th, 2008, 03:00 PM
Hi

I must admit I have not look deep into your code , but could your problem
be this extra bytes :

"The number of bytes in a scanline ( that is, a horizontal line in the image ) is always a multiple of four. This is for speed of processing, I believe. If you have a 32 bit image, then that's fine, each pixel has four bytes anyhow. But if your image is 24 or 16 bit, then it's possible that the number of bytes USED is not a multiple of 4. In that case, the system adds bytes to pad it out to the nearest multiple of 4. The offset is any extra bytes on the end of a scanline that are not part of the image. In C++, GDI+ throws an exception if you access those extra bytes. I don't know if C# does the same, I've never tried"

found take from this link (down in comments to article)
http://64.233.183.104/search?q=cache:CQejCpDwNowJ:69.10.233.10/KB/GDI-plus/displacementfilters.aspx%3Ffid%3D13929%26df%3D90%26mpp%3D25%26noise%3D3%26sort%3DPosition%26view%3DQuick%26select%3D2551540%26fr%3D101+scanlines+24bit+C%23+extra&hl=da&ct=clnk&cd=6&gl=dk

It a wild shoot , but maybe it helps ;)

Best Regards

TheMelter