You are on page 1of 9

12/6/2014

RasterDataTutorial

RasterDataTutorial
Author:BillGreen(2002)
HOMEEMAIL

INTRODUCTION
ABMPcomputerimageistheeasiesttounderstandbecauseitdoesnotusecompression,making
pixeldataretrievalmucheasier.Thetablebelowshowshowthepixeldataisstoredfromthefirstbyte
tothelast.
TABLE1:BMPFileStructure
Byte#tofseekfilepointer Information
0

Signature

Filesize

18

Width(numberofcolumns)

22

Height(numberofrows)

28

Bits/pixel

46

Numberofcolorsused

54

Startofcolortable

54+4*(numberofcolors) Startofrasterdata
Thefirst14bytesarededicatedtotheheaderinformationoftheBMP.Thenext40bytesare
dedicatedtowardstheinfoheader,whereonecanretrievesuchcharacteristicsaswidth,height,file
size,andnumberofcolorsused.Next,isthecolortable,whichis4x(numberofcolorsused)bytes
long.Soforan8bitgrayscaleimage(numberofcolorsis256),thecolortablewouldbe4x256bytes
longor1024bytes.AndthelastbitofdatainaBMPfileisthepixeldata,orrasterdata.Theraster
datastartsatbyte54(header+infoheader)+4xnumberofcolors(colortable).Foran8bit
grayscaleimage,therasterdatawouldstartatbyte54+1024=1078.Thesizeoftherasterdatais
(widthxheight)1bytes.Therefore,a100rowby100column8bitgrayscaleimagewouldhave
(100x100)1=9,999bytesofrasterdatastartingatbyte1078andcontinuingtotheendofthe
BMP.
Intermsofimageprocessing,themostimportantinformationisthefollowing:
(1)Numberofcolumnsbyte#18
(2)Numberofrowsbyte#22
(3)Rasterdatabyte#(4xnumberofcolors)tobyte#1078+(numberofcolumnsxnumberofrows)
1
InC,themostefficientwayofdeclaringthisimportantinformationisthatofstruct.

typedefstruct{introws;

/*numberofrows*/

intcols;

/*numberofcolumns*/

unsignedchar*data;/*rasterdata*/

}sImage;

http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

1/9

12/6/2014

RasterDataTutorial

READINGBMPRASTERDATA
TEST.bmpisa20rowby20columnBMPimagewhichwewillusetoreadrasterdatafrom.Inan8
bitBMPimage,blackis0andwhiteis255.ThetopleftcornerofTEST.bmpstartsatapixelvalueof
0(black)andprogressivelyworksitswaydownthediagonaltopixelvalueof255(white).Thinking
ofrowsandcolumnsinaBMPisnotthesameasthinkingofrowsandcolumnsinamatrix.Ina
matrixrow0andcolumn0wouldstartyouatthetopleftcornerofthematrix.However,inaBMP,
therowsincreasefrombottomtotop.Therefore,row0andcolumn0inaBMPwouldcorrespondto
thebottomleftcorner.

(TEST.bmpisscaledupheretoa100by100BMP,
sobesureanddownloadthezipfiletotestoutyourrasterdataprogram.)
TEST.bmpcontains20rowsand20columns,soweknowwewillhave400bytesofrasterdata.We
alsoknowtherasterdatawillstartatbyte#(54+4xnumberofcolors).Thenumberofcolorsof
TEST.bmpis256becauseitisagrayscaleimagewithcolorsrangingfrom0to255.Therefore,the
rasterdatawillstartatbyte#1078andthefilesizewillbe1078+400=1478bytes.Knowingthis,
letstryourfirstprogramtoreadrasterdataandprintittoatextfile.

TobecompiledwithTurboC
Note:downloadraster.zipratherthancuttingandpastingfrombelow.
#include(stdio.h)
#include(stdlib.h)
#include(math.h)
/*STRUCTURES*/
typedefstruct{introws;intcols;unsignedchar*data;}sImage;
/*PROTOTYPES*/
longgetImageInfo(FILE*,long,int);
intmain(intargc,char*argv[])
{
FILE

*bmpInput,*rasterOutput;
sImage

originalImage;
unsignedchar
someChar;
unsignedchar*
pChar;
int

nColors;/*BMPnumberofcolors*/
long

fileSize;/*BMPfilesize*/
int

vectorSize;/*BMPvectorsize*/
int

r,c;/*r=rows,c=cols*/
/*initializepointer*/
someChar='0';
pChar=&someChar;
if(argc<2)
{
printf("Usage:%sbmpInput.bmp\n",argv[0]);
exit(0);
http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

2/9

12/6/2014

RasterDataTutorial

}
printf("Readingfilename%s\n",argv[1]);
/*READINPUTFILE*/
bmpInput=fopen(argv[1],"rb");
fseek(bmpInput,0L,SEEK_END);
/*DECLAREOUTPUTTEXTFILE*/
rasterOutput=fopen("data.html","w");
/*GETBMPDATA*/
originalImage.cols=(int)getImageInfo(bmpInput,18,4);
originalImage.rows=(int)getImageInfo(bmpInput,22,4);
fileSize=getImageInfo(bmpInput,2,4);
nColors=getImageInfo(bmpInput,46,4);
vectorSize=fileSize(14+40+4*nColors);
/*PRINTDATATOSCREEN*/
printf("Width:%d\n",originalImage.cols);
printf("Height:%d\n",originalImage.rows);
printf("Filesize:%ld\n",fileSize);
printf("#Colors:%d\n",nColors);
printf("Vectorsize:%d\n",vectorSize);
/*STARTATBEGINNINGOFRASTERDATA*/
fseek(bmpInput,(54+4*nColors),SEEK_SET);
/*READRASTERDATA*/
for(r=0;r<=originalImage.rows1;r++)
{
for(c=0;c<=originalImage.cols1;c++)
{
/*readdataandprintin(row,column)form*/
fread(pChar,sizeof(char),1,bmpInput);
fprintf(rasterOutput,"(%d,%d)=%d\n",r,c,*pChar);
}
}
fclose(bmpInput);
fclose(rasterOutput);
}
/*GETIMAGEINFOSUBPROGRAM*/
longgetImageInfo(FILE*inputFile,longoffset,intnumberOfChars)
{
unsignedchar
*ptrC;
long

value=0L;
unsignedchar
dummy;
int

i;
dummy='0';
ptrC=&dummy;
fseek(inputFile,offset,SEEK_SET);
for(i=1;i<=numberOfChars;i++)
{
fread(ptrC,sizeof(char),1,inputFile);
/*calculatevaluebasedonaddingbytes*/
value=(long)(value+(*ptrC)*(pow(256,(i1))));
}
return(value);
http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

3/9

12/6/2014

RasterDataTutorial

}/*endofgetImageInfo*/

Runningyourrasterdataprogram,youwillgetanASCIIfilecalleddata.txtwithsomeentrieslooking
likethefollowing:
(0,0)=255
(0,1)=255
(0,2)=255
(0,3)=255
:
(1,0)=255
(1,1)=255
(1,2)=255
(1,3)=255
:
(2,0)=255
(2,1)=255
(2,2)=255
(2,3)=255
:
(3,0)=255
(3,1)=255
(3,2)=255
(3,3)=255
:
(4,0)=255
(4,1)=255
(4,2)=255
:
(4,14)=207
(4,15)=207
(4,16)=255
(4,17)=255
(4,18)=255
(4,19)=255
:
(5,0)=255
(5,1)=255
(5,2)=255
(5,3)=255
:
(5,14)=207
(5,15)=207
:
(6,0)=255
(6,1)=255
(6,2)=255
(6,3)=255
:
(6,12)=159
(6,13)=159
:
(7,0)=255
(7,1)=255
(7,2)=255
(7,3)=255
:
(7,12)=159
(7,13)=159
http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

4/9

12/6/2014

RasterDataTutorial

(7,14)=255
:
(8,0)=255
(8,1)=255
(8,2)=255
:
(8,10)=111
(8,11)=111
(8,12)=255
:
(9,0)=255
(9,1)=255
(9,2)=255
(9,3)=255
:
(9,10)=111
(9,11)=111
(9,12)=255
:
(10,0)=255
(10,1)=255
(10,2)=255
(10,3)=255
:
(10,8)=79
(10,9)=79
(10,10)=255
:

EXPLANATION
Noticehowentry(4,14)is207meaningthatthepixelintherow4,column14isveryclosetowhite.
Thisisnotthecaseifyouarethinkingintermsofmatrices.JustrememberthatinBMPs,theraster
dataisstoredfromlefttorightandbottomtotop.
TheprogrambeginsbyopeningtheBMPfileenteredatthecommandprompt.Forexampleifyour
programiscalledraster.c,atthecommandpromptyouwouldenter:
rastertest.bmp
WewanttoreadabinaryBMPfilewhichrequiredustoaddrbinourfopenstatementforread
binary.WealsohavetosetthefilepointertothebeginningoftheBMPfilebyte#0.Weaccomplish
these2taskswiththefollowinglinesofcode:
bmpInput=fopen(argv[1],"rb");
fseek(bmpInput,0L,SEEK_END);

Fromthepixeldatatableweseethatbyte#18containsthewidthoftheBMPfile.Sotogetthe
correspondingnumberofcolumnswehavetosetthefilepointertobytenumber18.Wealsohaveto
setthepointertoreadtheheight,numberofcolors,filesize,vectorsize,etc.Insteadoftediously
performingthistaskrepeatedly,itwouldbemucheasiertowriteasubprogramthatdoesitforyou
eachtimeitiscalledinmain.Thesubprogramisafunctionwhichmeansitreturnsavaluetomain.
Forexample,togetthewidthofaBMP,allyouwouldhavetotypeis:
originalImage.rows=(int)getImageInfo(bmpInput,18,4);

The18correspondstowhereyouwanttostartreadingdatafromandthe4correspondstohowmany
bytesyouwanttoread.

http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

5/9

12/6/2014

RasterDataTutorial

MANIPULATINGABMPFILE
Asourfirstimageprocessingtask,wewanttotaketheTEST.bmpandreflectit.Inotherwords,
insteadofhavingdecreasefromblacktowhitedownthediagonal,wewantittodecreasefromwhite
toblack.Ifthepixelvaluewasblack,wewantittobewhite.
reflect(k,k)=255TEST(k,k)
Asidefromthissimplealgorithm,reflect.bmpandTEST.bmpareidentical,sowewouldliketocopy
theheaderinformationandthecolortablefromTEST.bmptoreflect.bmp.Thiscanbedonewiththe
following2procedures.Aprocedureisasubprogramthatdoesnotreturnavalue.
/*COPIESHEADERANDINFOHEADER*/
voidcopyImageInfo(FILE*inputFile,FILE*outputFile)
{
unsignedchar
*ptrC;
unsignedchar
dummy;
int

i;
dummy=0;
ptrC=&dummy;
fseek(inputFile,0L,SEEK_SET);
fseek(outputFile,0L,SEEK_SET);
for(i=0;i<=50;i++)
{
fread(ptrC,sizeof(char),1,inputFile);
fwrite(ptrC,sizeof(char),1,outputFile);
}
}

/*COPIESCOLORTABLE*/
voidcopyColorTable(FILE*inputFile,FILE*outputFile,intnColors)
{
unsignedchar
*ptrC;
unsignedchar
dummy;
int

i;
dummy=0;
ptrC=&dummy;
fseek(inputFile,54L,SEEK_SET);
fseek(outputFile,54L,SEEK_SET);
for(i=0;i<=(4*nColors);i++)/*thereare(4*nColors)bytesincolortable*/
{
fread(ptrC,sizeof(char),1,inputFile);
fwrite(ptrC,sizeof(char),1,outputFile);
}
}

http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

6/9

12/6/2014

RasterDataTutorial

ThefollowingcodereflectsaBMPfile.Thedifferencesfromraster.careinred:

TobecompiledwithTurboC
Note:downloadreflect.zipratherthancuttingandpastingfrombelow.
#include(stdio.h)
#include(stdlib.h)
#include(math.h)
/*STRUCTURES*/
typedefstruct{introws;intcols;unsignedchar*data;}sImage;
/*PROTOTYPES*/
longgetImageInfo(FILE*,long,int);
voidcopyImageInfo(FILE*inputFile,FILE*outputFile);
voidcopyColorTable(FILE*inputFile,FILE*outputFile,intnColors);
intmain(intargc,char*argv[])
{
FILE

*bmpInput,*bmpOutput;
sImage

originalImage;
unsignedchar
someChar;
unsignedchar*
pChar;
int

nColors;/*BMPnumberofcolors*/
long

fileSize;/*BMPfilesize*/
int

vectorSize;/*BMPvectorsize*/
int

r,c;/*r=rows,c=cols*/
/*initializepointer*/
someChar='0';
pChar=&someChar;
if(argc<2)
{
printf("Usage:%sbmpInput.bmp\n",argv[0]);
exit(0);
}
printf("Readingfilename%s\n",argv[1]);
/*READINPUTFILE*/
bmpInput=fopen(argv[1],"rb");
fseek(bmpInput,0L,SEEK_END);
/*DECLAREOUTPUTFILE*/
bmpOutput=fopen("reflect.bmp","wb");
/*GETBMPDATA*/
originalImage.cols=(int)getImageInfo(bmpInput,18,4);
originalImage.rows=(int)getImageInfo(bmpInput,22,4);
fileSize=getImageInfo(bmpInput,2,4);
nColors=getImageInfo(bmpInput,46,4);
vectorSize=fileSize(14+40+4*nColors);
/*PRINTDATATOSCREEN*/
printf("Width:%d\n",originalImage.cols);
printf("Height:%d\n",originalImage.rows);
printf("Filesize:%ld\n",fileSize);
printf("#Colors:%d\n",nColors);
printf("Vectorsize:%d\n",vectorSize);
http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

7/9

12/6/2014

RasterDataTutorial

copyImageInfo(bmpInput,bmpOutput);
copyColorTable(bmpInput,bmpOutput,nColors);
/*STARTATBEGINNINGOFRASTERDATA*/
fseek(bmpInput,(54+4*nColors),SEEK_SET);
/*READRASTERDATA*/
for(r=0;r<=originalImage.rows1;r++)
{
for(c=0;c<=originalImage.cols1;c++)
{
/*readdata,reflectandwritetooutputfile*/
fread(pChar,sizeof(char),1,bmpInput);
if(*pChar==255)*pChar=255;
else*pChar=255*pChar;
fwrite(pChar,sizeof(char),1,bmpOutput);
}
}
fclose(bmpInput);
fclose(bmpOutput);
}
/*GETIMAGEINFOSUBPROGRAM*/
longgetImageInfo(FILE*inputFile,longoffset,intnumberOfChars)
{
unsignedchar

*ptrC;
long

value=0L;
unsignedchar

dummy;
int

i;
dummy='0';
ptrC=&dummy;
fseek(inputFile,offset,SEEK_SET);
for(i=1;i<=numberOfChars;i++)
{
fread(ptrC,sizeof(char),1,inputFile);
/*calculatevaluebasedonaddingbytes*/
value=(long)(value+(*ptrC)*(pow(256,(i1))));
}
return(value);
}/*endofgetImageInfo*/
/*COPIESHEADERANDINFOHEADER*/
voidcopyImageInfo(FILE*inputFile,FILE*outputFile)
{
unsignedchar
*ptrC;
unsignedchar
dummy;
int

i;
dummy='0';
ptrC=&dummy;
fseek(inputFile,0L,SEEK_SET);
fseek(outputFile,0L,SEEK_SET);
for(i=0;i<=50;i++)
{
fread(ptrC,sizeof(char),1,inputFile);
fwrite(ptrC,sizeof(char),1,outputFile);
http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

8/9

12/6/2014

RasterDataTutorial

}
}
/*COPIESCOLORTABLE*/
voidcopyColorTable(FILE*inputFile,FILE*outputFile,intnColors)
{
unsignedchar
*ptrC;
unsignedchar
dummy;
int

i;
dummy='0';
ptrC=&dummy;
fseek(inputFile,54L,SEEK_SET);
fseek(outputFile,54L,SEEK_SET);
for(i=0;i<=(4*nColors);i++)/*thereare(4*nColors)bytesincolortable*/
{
fread(ptrC,sizeof(char),1,inputFile);
fwrite(ptrC,sizeof(char),1,outputFile);
}
}
Youarevisitornumber:

http://dasl.mem.drexel.edu/alumni/bGreen/www.pages.drexel.edu/_weg22/raster.html

9/9

You might also like