Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

MicrosoftBMP_RT.cpp

00001 /*****************************************************************************
00002  *
00003  * File :       MicrosoftBMP_RT.cc
00004  *
00005  * Module :     ImageLib.a
00006  *
00007  * Author :     Derek Magee, School of Computer Science, Leeds University.
00008  *
00009  * Created :    31 October 1997
00010  *
00011  *****************************************************************************
00012  *
00013  * Source code for Image Library MkII
00014  *
00015  * The author, Derek Magee, gives permission for this code to be copied,
00016  * modified and distributed within the University of Leeds subject to the
00017  * following conditions:-
00018  *
00019  * - The code is not to be used for commercial gain.
00020  * - The code and use thereof will be attributed to the author where
00021  *   appropriate (inluding demonstrations which rely on it's use).
00022  * - All modified, distributions of the source files will retain this header.
00023  *
00024  *****************************************************************************
00025  *
00026  * Description:
00027  *
00028  * Methods for reading and writing 24 bit Microsoft v3 bitmap files.
00029  *
00030  *****************************************************************************
00031  *
00032  * Revision History:
00033  *
00034  * Date         By              Revision
00035  *
00036  * 31/10/97     DRM             Created.
00037  *
00038  ****************************************************************************/
00039 
00040 #include "MicrosoftBMP_RT.h"
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 
00044 MicrosoftBMP_RT::MicrosoftBMP_RT(const char *filename)
00045 {
00046 /* 
00047  * This is the constructor method for the MicrosoftBMP_RT class. It copies the
00048  * string pointed to by filename into the file_name buffer, truncating if
00049  * it is greater than this buffer and initialises other parameters to sensible
00050  * values.
00051  */
00052 
00053     set_filename(filename);
00054     FileSize = IMAGE_DATA_OFFSET;
00055     ImageWidth = 0;
00056     ImageHeight = 0;
00057     HorizResolution = 0;
00058     VertResolution = 0;
00059     file_pnt = NULL;
00060     raw_data = NULL;
00061 }
00062 
00063 MicrosoftBMP_RT::~MicrosoftBMP_RT()
00064 {
00065 /*
00066  * This is the destructor for the class MicrosoftBMP_RT. It frees allocated 
00067  * memory.
00068  */
00069 
00070     delete []raw_data;
00071 }
00072 
00073 void MicrosoftBMP_RT::set_filename(const char *filename)
00074 {
00075 /* 
00076  * copy string pointed to by filename into buffer file_name truncating if
00077  * length is greater than MAX_FILENAME_LEN.
00078  */
00079 
00080     if(file_name!=NULL){
00081         strncpy(file_name, filename, MAX_FILENAME_LEN);
00082 
00083         /* Ensure string is terminated if length = MAX_FILENAME_LEN */
00084         file_name[MAX_FILENAME_LEN] = '\0';
00085     }
00086 }
00087 
00088 bool MicrosoftBMP_RT::set_size(unsigned int width, unsigned int height)
00089 {
00090 /*
00091  * Method sets the parameters ImageWidth and ImageHeight to width and height
00092  * and ensures that the memory allocated to raw_data is large enough to contain
00093  * this ammount of data. The method returns false if memory allocation is
00094  * unsuccessful and true otherwise.
00095  */
00096 
00097     bool ret_val ;
00098 
00099     /* First free memory currently associated with raw_data (if any) */ 
00100     delete raw_data ;    
00101 
00102     ImageWidth = width ;
00103     ImageHeight = height ;
00104 
00105     if(allocate_storage()){
00106     /* memory allocation was sucessful */
00107         ret_val = true ;
00108     }
00109     else{
00110         ret_val = false ;
00111     }
00112 
00113     calculate_filesize();
00114  
00115     return ret_val ;
00116 }
00117 
00118 bool MicrosoftBMP_RT::read_byte(unsigned char *inp_chr)
00119 {
00120 /*
00121  * Reads a byte from stream pointed to by file_pnt into *inp_chr. Returns
00122  * false if cannot
00123  * read or invalid file pointer.
00124  */
00125 
00126     bool ret_val = true ;
00127     int char_read;
00128     if(file_pnt == NULL){
00129     /* Invalid file pointer */
00130         ret_val = false ;
00131     }
00132     else if( (char_read = fgetc(file_pnt)) == EOF){
00133     /* Could not read character from file */
00134         ret_val = false ;
00135     }
00136     else{
00137     /* Character read Ok */
00138         *inp_chr = (unsigned char) char_read ;
00139     }
00140     return ret_val ; 
00141 }
00142 
00143 bool MicrosoftBMP_RT::read_word(unsigned int *inp_word)
00144 {
00145 /*
00146  * Reads a little endian word from stream pointed to by file_pnt into
00147  * *inp_word. Returns false if cannot read or invalid file pointer.
00148  */
00149 
00150     unsigned char inp1;
00151     unsigned char inp2;
00152     bool ret_val = true ;
00153 
00154     ret_val = read_byte(&inp1);
00155     
00156     if(ret_val){
00157     /* First byte read OK */
00158         ret_val = read_byte(&inp2);
00159     }
00160 
00161     if(ret_val){
00162     /* Both bytes read OK */
00163         *inp_word = inp1 + (((unsigned int)(inp2))<<8) ;
00164     }
00165 
00166     return ret_val ; 
00167 }
00168 
00169 bool MicrosoftBMP_RT::read_dword(unsigned int *inp_word)
00170 {
00171 /*
00172  * Reads a little endian double word from stream pointed to by file_pnt into
00173  * *inp_word. Returns false if cannot read or invalid file pointer.
00174  */
00175 
00176     unsigned char inp1;
00177     unsigned char inp2;
00178     unsigned char inp3;
00179     unsigned char inp4;
00180     bool ret_val = true ;
00181 
00182     ret_val = read_byte(&inp1);
00183     
00184     if(ret_val){
00185     /* First byte read OK */
00186         ret_val = read_byte(&inp2);
00187     }
00188 
00189     if(ret_val){
00190     /* Second byte read OK */
00191         ret_val = read_byte(&inp3);
00192     }
00193 
00194     if(ret_val){
00195     /* Third byte read OK */
00196         ret_val = read_byte(&inp4);
00197     }
00198 
00199     if(ret_val){
00200     /* All 4 bytes read OK */
00201         *inp_word = (unsigned int)inp1 +
00202                     (((unsigned int)(inp2))<<8) +
00203                     (((unsigned int)(inp3))<<16) +
00204                     (((unsigned int)(inp4))<<24) ;
00205     }
00206 
00207     return ret_val ; 
00208 }
00209 
00210 
00211 
00212 bool MicrosoftBMP_RT::write_byte(char chr)
00213 {
00214 /*
00215  * Writes a byte (chr) to stream pointed to by file_pnt. Returns
00216  * false if cannot write or invalid file pointer.
00217  */
00218 
00219     bool ret_val = true ;
00220 
00221     if(file_pnt == NULL){
00222     /* Invalid file pointer */
00223         ret_val = false ;
00224     }
00225     else if( fputc((int)chr, file_pnt) == EOF){
00226     /* Could not write character to file */
00227         ret_val = false ;
00228     }
00229     else{
00230     /* Character written Ok */
00231         ret_val = true ; 
00232     }
00233 
00234     return ret_val ; 
00235 }
00236 
00237 bool MicrosoftBMP_RT::write_word(unsigned int wrd)
00238 {
00239 /*
00240  *  Writes a little endian word (wrd) to stream pointed to by file_pnt. 
00241  *  Returns false if cannot write or invalid file pointer.
00242  */
00243 
00244     unsigned int low_b;
00245     unsigned int hi_b;
00246     bool ret_val = true ;
00247 
00248     low_b = wrd&0xFF ;
00249     hi_b  = ( wrd >> 8 ) & 0xFF ;
00250 
00251     ret_val = write_byte((int)low_b);
00252     
00253     if(ret_val){
00254     /* First byte written OK */
00255         ret_val = write_byte((int)hi_b);
00256     }
00257 
00258     return ret_val ; 
00259 }
00260 
00261 bool MicrosoftBMP_RT::write_dword(unsigned int wrd)
00262 {
00263 /*
00264  * Writes a little endian double word to stream pointed to by file_pnt. 
00265  * *inp_word. Returns false if cannot write or invalid file pointer.
00266  */
00267 
00268     char by1;
00269     char by2;
00270     char by3;
00271     char by4;
00272     bool ret_val = true ;
00273 
00274     by1 = wrd&0xFF ;
00275     by2 = ( wrd >> 8 ) & 0xFF ;
00276     by3 = ( wrd >> 16 ) & 0xFF ;
00277     by4 = ( wrd >> 24 ) & 0xFF ;
00278     ret_val = write_byte(by1);
00279     
00280     if(ret_val){
00281     /* First byte writtten OK */
00282         ret_val = write_byte(by2);
00283     }
00284 
00285     if(ret_val){
00286     /* Second byte written OK */
00287         ret_val = write_byte(by3);
00288     }
00289 
00290     if(ret_val){
00291     /* Third byte written OK */
00292         ret_val = write_byte(by4);
00293     }
00294 
00295     return ret_val ; 
00296 }
00297 
00298 
00299 bool MicrosoftBMP_RT::allocate_storage()
00300 {
00301 /*
00302  * Allocates memory for raw_data based on ImageWidth and ImageHeight.
00303  */
00304 
00305     raw_data = new unsigned char[ImageWidth * ImageHeight * 3];
00306 
00307     if(raw_data==NULL) return false;
00308     else               return true;
00309 }
00310 
00311 void MicrosoftBMP_RT::calculate_filesize()
00312 {
00313 /*
00314  * Calculates the filesize from ImageWidth and ImageHeight and stores this in 
00315  * FileSize.
00316  */
00317 
00318     unsigned int bytes_per_row;
00319 
00320     bytes_per_row = ImageWidth * 3 ;
00321 
00322     while( bytes_per_row & 0x03 ){
00323     /* Bytes per row is not divisible by 4 */
00324         bytes_per_row++ ;
00325     }
00326 
00327     FileSize = bytes_per_row * ImageHeight + IMAGE_DATA_OFFSET ;
00328 }
00329 
00330 bool MicrosoftBMP_RT::read()
00331 {
00332 /*
00333  * Method to read file data from file into the object 
00334  */
00335 
00336     bool ret_val = true ;
00337     unsigned int bytes_in=0;
00338     unsigned char *d_pointer;
00339     unsigned char pad;
00340     unsigned int line;
00341     unsigned int pixel;
00342 
00343     if((file_pnt = fopen(file_name,"rb"))==NULL){
00344     /* Could not open file */
00345         ret_val = false;
00346     }
00347     else{
00348     /* Read in header info */
00349         ret_val &= read_byte(&type1);
00350         ret_val &= read_byte(&type2);
00351         ret_val &= read_dword(&FileSize);
00352         ret_val &= read_dword(&reserved);
00353         ret_val &= read_dword(&data_off);
00354         ret_val &= read_dword(&head_size);
00355         ret_val &= read_dword(&ImageWidth);
00356         ret_val &= read_dword(&ImageHeight);
00357         ret_val &= read_word(&no_planes);
00358         ret_val &= read_word(&bits_per_pixel);
00359         ret_val &= read_dword(&comp_method);
00360         ret_val &= read_dword(&bitmap_size);
00361         ret_val &= read_dword(&HorizResolution);
00362         ret_val &= read_dword(&VertResolution);
00363         ret_val &= read_dword(&no_cols);
00364         ret_val &= read_dword(&no_sig_cols);
00365     }
00366     ret_val &= check_header_valid();
00367     if(ret_val){
00368     /* No problems so far */
00369        ret_val = allocate_storage();
00370     }
00371     if(ret_val){
00372     /* Read in data */
00373     
00374         d_pointer = raw_data ;
00375 
00376         for(line=0 ; line<ImageHeight && ret_val ; line ++){
00377  
00378             bytes_in = 0;
00379             for(pixel=0 ; pixel<ImageWidth*3 && ret_val ; pixel ++){
00380                 ret_val &= read_byte(d_pointer++);
00381                 bytes_in++;
00382             }
00383 
00384             while(bytes_in & (unsigned int)(0x03)){
00385             /* Discard padding */
00386                 ret_val &= read_byte(&pad);
00387                 bytes_in++;
00388             }
00389         }  
00390     }
00391 
00392     if( file_pnt == NULL ||
00393         fclose(file_pnt) == EOF ){
00394     /* Error closing file */
00395         ret_val = false ;
00396     }
00397 
00398     return ret_val;
00399 }
00400          
00401 bool MicrosoftBMP_RT::check_header_valid()
00402 {
00403 /* 
00404  * Checks header of file is valid.
00405  */
00406 
00407     bool ret_val ;
00408 
00409     if( type1           != 'B'                 ||
00410         type2           != 'M'                 ||
00411         data_off        != IMAGE_DATA_OFFSET   ||
00412         head_size       != HEADER_SIZE         ||
00413         no_planes       != NO_OF_IMAGE_PLANES  ||
00414         bits_per_pixel  != BITS_PER_PIXEL      ||           
00415         comp_method     != COMPRESSION_METHOD    ){
00416     /* Bitmap file header is invalid */
00417         ret_val = false ;
00418     }
00419     else{
00420         ret_val = true ;
00421     }
00422  
00423     return ret_val ;
00424 }
00425                
00426 void MicrosoftBMP_RT::extract_data(int *rgb)
00427 {
00428 /*
00429  * Converts raw data from raw_data to RGB in the buffer rgb.
00430  * Note: Also flips the image vertically as bitmaps are stored upsidedown.
00431  */
00432 
00433     unsigned int lines;
00434     unsigned int pixels;
00435     unsigned char *buff_pnt = raw_data;
00436     int          *rgb_ptr ;
00437 
00438 
00439     rgb_ptr = rgb ;
00440     buff_pnt = raw_data ;
00441     for(lines=0 ; lines<ImageHeight ; lines ++){
00442         buff_pnt = raw_data + ImageWidth*(ImageHeight-lines-1)*3 ;
00443         for(pixels=0; pixels<ImageWidth ; pixels++, rgb_ptr+=3){
00444 
00445             *(rgb_ptr+2)  = *(buff_pnt++);   // B
00446             *(rgb_ptr+1) = *(buff_pnt++);    // G
00447             *(rgb_ptr) = *(buff_pnt++);      // R
00448 
00449         }
00450     }
00451 } 
00452 
00453 void MicrosoftBMP_RT::extract_data_grey(int *grey)
00458 {
00459 
00460     unsigned int lines;
00461     unsigned int pixels;
00462     unsigned char *buff_pnt = raw_data;
00463     int          *grey_ptr ;
00464 
00465 
00466     grey_ptr = grey ;
00467     buff_pnt = raw_data ;
00468     for(lines=0 ; lines<ImageHeight ; lines ++){
00469         buff_pnt = raw_data + ImageWidth*(ImageHeight-lines-1)*3 ;
00470         for(pixels=0; pixels<ImageWidth ; pixels++, grey_ptr++){
00471 
00472             *grey_ptr  = *(buff_pnt++);   // B
00473             *grey_ptr += *(buff_pnt++);   // G
00474             *grey_ptr += *(buff_pnt++);   // R
00475             *grey_ptr /= 3 ;
00476         }
00477     }
00478 }
00479 
00480 
00481                
00482 void MicrosoftBMP_RT::put_data(int *rgb)
00483 {
00484 /*
00485  * Converts RGB data from the buffers red, green & blue to raw bitmap data 
00486  * which is stored in the buffer raw_data.
00487  * Note: Also flips the image vertically as bitmaps are stored upsidedown.
00488  */
00489 
00490     unsigned int   lines;
00491     unsigned int   pixels;
00492     unsigned char  *buff_pnt ;
00493     unsigned int   p_off;
00494     int            *rgb_ptr ;
00495 
00496     rgb_ptr = rgb ;
00497 
00498     buff_pnt = raw_data ;  
00499  
00500     p_off = (ImageWidth*ImageHeight*3);
00501  
00502     for(lines=0 ; lines<ImageHeight ; lines ++){
00503     /* For each line in the image */
00504 
00505         /* Set pointer to beginning of previous line */
00506         p_off -= ImageWidth*3 ;
00507 
00508         buff_pnt = raw_data + p_off ;
00509 
00510         /* Loop through pixels in the line */
00511         for(pixels=0; pixels<ImageWidth ; pixels++,rgb_ptr+=3){
00512             *(buff_pnt++) = *(rgb_ptr+2) ;
00513             *(buff_pnt++) = *(rgb_ptr+1); 
00514             *(buff_pnt++) = *rgb_ptr;
00515         }
00516     }
00517 } 
00518 
00519 void MicrosoftBMP_RT::put_data_grey(int *brightness)
00520 {
00521 /*
00522  * Converts RGB data from the buffers red, green & blue to raw bitmap data 
00523  * which is stored in the buffer raw_data.
00524  * Note: Also flips the image vertically as bitmaps are stored upsidedown.
00525  */
00526 
00527     unsigned int   lines;
00528     unsigned int   pixels;
00529     unsigned char  *buff_pnt ;
00530     unsigned int   p_off;
00531     int            *g_ptr ;
00532 
00533     g_ptr = brightness ;
00534 
00535     buff_pnt = raw_data ;  
00536  
00537     p_off = (ImageWidth*ImageHeight*3);
00538  
00539     for(lines=0 ; lines<ImageHeight ; lines ++){
00540     /* For each line in the image */
00541 
00542         /* Set pointer to beginning of previous line */
00543         p_off -= ImageWidth*3 ;
00544 
00545         buff_pnt = raw_data + p_off ;
00546 
00547         /* Loop through pixels in the line */
00548         for(pixels=0; pixels<ImageWidth ; pixels++,g_ptr++){
00549             *(buff_pnt++) = *g_ptr ;
00550             *(buff_pnt++) = *g_ptr ; 
00551             *(buff_pnt++) = *g_ptr ;
00552         }
00553     }
00554 } 
00555 
00556 bool MicrosoftBMP_RT::write()
00557 {
00558 /*
00559  * Method to write file data to file from the object 
00560  */
00561 
00562     bool ret_val = true ;
00563     unsigned int bytes_in=0;
00564     unsigned char *d_pointer;
00565     unsigned int line;
00566     unsigned int pixel;
00567     if((file_pnt = fopen(file_name,"wb"))==NULL){
00568     /* Could not open file */
00569         ret_val = false;
00570     }
00571     else{
00572     /* Read in header info */
00573         ret_val &= write_byte('B');
00574         ret_val &= write_byte('M');
00575         ret_val &= write_dword(FileSize);
00576         ret_val &= write_dword(0);
00577         ret_val &= write_dword(IMAGE_DATA_OFFSET);
00578         ret_val &= write_dword(HEADER_SIZE);
00579         ret_val &= write_dword(ImageWidth);
00580         ret_val &= write_dword(ImageHeight);
00581         ret_val &= write_word(NO_OF_IMAGE_PLANES);
00582         ret_val &= write_word(BITS_PER_PIXEL);
00583         ret_val &= write_dword(COMPRESSION_METHOD);
00584         ret_val &= write_dword(SIZE_OF_BITMAP);
00585         ret_val &= write_dword(HorizResolution);
00586         ret_val &= write_dword(VertResolution);
00587         ret_val &= write_dword(NO_COLOURS_USED);
00588         ret_val &= write_dword(NO_SIGNIFICANT_COLS);
00589     }
00590 
00591     if(ret_val){
00592     /* Write data */
00593     
00594         d_pointer = raw_data ;
00595 
00596         for(line=0 ; line<ImageHeight && ret_val ; line ++){
00597  
00598             bytes_in = 0;
00599             for(pixel=0 ; pixel<ImageWidth*3 && ret_val ; pixel ++){
00600                 ret_val &= write_byte(*(d_pointer++));
00601                 bytes_in++;
00602             }
00603 
00604             while(bytes_in & 0x03){
00605             /* Pad with zeros */
00606                 ret_val &= write_byte(0);
00607                 bytes_in++;
00608             }
00609         }  
00610     }
00611 
00612     if( file_pnt == NULL ||
00613         fclose(file_pnt) == EOF ){
00614     /* Error closing file */
00615         ret_val = false ;
00616     }
00617 
00618     return ret_val;
00619 }
00620          

Generated at Fri Aug 13 17:29:21 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001