libcvd-members
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libcvd-members] libcvd cvd/internal/io/bmp.h pnm_src/bmp.cxx


From: Edward Rosten
Subject: [libcvd-members] libcvd cvd/internal/io/bmp.h pnm_src/bmp.cxx
Date: Thu, 15 May 2008 22:54:13 +0000

CVSROOT:        /cvsroot/libcvd
Module name:    libcvd
Changes by:     Edward Rosten <edrosten>        08/05/15 22:54:13

Modified files:
        cvd/internal/io: bmp.h 
        pnm_src        : bmp.cxx 

Log message:
        Fix .bmp loading and saving on 64 bit platforms

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/cvd/internal/io/bmp.h?cvsroot=libcvd&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/libcvd/pnm_src/bmp.cxx?cvsroot=libcvd&r1=1.1&r2=1.2

Patches:
Index: cvd/internal/io/bmp.h
===================================================================
RCS file: /cvsroot/libcvd/libcvd/cvd/internal/io/bmp.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- cvd/internal/io/bmp.h       29 Sep 2006 21:59:45 -0000      1.5
+++ cvd/internal/io/bmp.h       15 May 2008 22:54:11 -0000      1.6
@@ -96,7 +96,10 @@
       unsigned int w,h,ch, comp;
       readBMPHeader(w,h,ch,comp,in);
       if (comp || (ch != 3 && ch != 1)) 
+      {
+       std::cerr << comp << " " << ch << "\n";
        throw CVD::Exceptions::Image_IO::UnsupportedImageType();
+       }
       im.resize(ImageRef(w,h));
       if (ch == 1)
        BMPReader<T,1>::read(im, in);

Index: pnm_src/bmp.cxx
===================================================================
RCS file: /cvsroot/libcvd/libcvd/pnm_src/bmp.cxx,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- pnm_src/bmp.cxx     28 Nov 2005 19:07:40 -0000      1.1
+++ pnm_src/bmp.cxx     15 May 2008 22:54:12 -0000      1.2
@@ -22,6 +22,7 @@
 
 using namespace std;
 #include <iostream>
+#include <sstream>
 #include <iomanip>
 #include <setjmp.h>
 
@@ -30,16 +31,16 @@
   namespace BMP
   {
 
-#pragma pack(4)
     struct BMPHeader
     {
       unsigned long size;            //!< header size
-      unsigned long reserved;        //!< reserved
+      unsigned short reserved[2];        //!< reserved
       unsigned long dataOffset;      //!< offset to beginning of data
       unsigned long infoSize;        //!< size of info
       unsigned long width;           //!< width of image
       unsigned long height;          //!< height of image
-      unsigned short planes_bpp[2];  //!< planes and color depth
+      unsigned short planes;         //!< planes
+      unsigned short bpp;            //!< colour depth
       unsigned long compression;     //!< compression type
       unsigned long dataSize;        //!< size of data
       unsigned long xPelsPerMeter;   //!< x resolution in pixels/meter
@@ -47,69 +48,145 @@
       unsigned long colors;          //!< number of specified colors in the map
       unsigned long importantColors; //!< number of important colors
     };
-#pragma pack()
 
-    inline bool isBigEndian()
+
+       void write_u4(ostream& o, unsigned long l)
+       {
+               o << (unsigned char)(0xff & (l))
+                 << (unsigned char)(0xff & (l >> 8))
+                 << (unsigned char)(0xff & (l >> 16))
+                 << (unsigned char)(0xff & (l >> 24));
+       }
+
+       void write_u1(ostream& o, unsigned long l)
     {
-      char buf[4]={'a','b','c','d'};
-      return (*(unsigned long*)buf & 0xFF) == 'd';
+               o << (unsigned char)(0xff & (l));
     }
 
-    //! Returns the byte reversal of a short.
-    inline unsigned short rev(unsigned short s)
+       void write_u2(ostream& o, unsigned long l)
     {
-      return ((s&0xFF)<<8)|(s>>8);
+               o << (unsigned char)(0xff & (l))
+                 << (unsigned char)(0xff & (l >> 8));
     }
 
-    //! Returns the byte reversal of a long.
-    inline unsigned long rev(unsigned long w)
+       inline  unsigned long  read_u4(istream& i)
     {
-      return 
((w&0xFF000000)>>24)|((w&0xFF0000)>>8)|((w&0xFF00)<<8)|((w&0xFF)<<24);
+               //Data is little endian:
+               unsigned long r =  i.get() | (i.get() << 8) | (i.get() << 16) | 
(i.get() << 12);
+               if(i.eof())
+                       throw(Exceptions::Image_IO::MalformedImage("EOF in 
header."));
+
+                       return r;
     }
 
-    void correctByteOrder(BMPHeader& header)
+       inline  unsigned long  read_u2(istream& i)
+       {
+               //Data is little endian:
+               unsigned long r =  i.get() | (i.get() << 8);
+               if(i.eof())
+                       throw(Exceptions::Image_IO::MalformedImage("EOF in 
header."));
+
+               return r;
+       }
+
+       BMPHeader read_header(istream& i)
+       {
+               //Read the header
+               BMPHeader h;
+               h.size = read_u4(i);
+               h.reserved[0] = read_u2(i);
+               h.reserved[1] = read_u2(i);
+               h.dataOffset = read_u4(i);
+
+               //Read the info block
+               h.infoSize = read_u4(i);
+
+               if(h.infoSize != 40)
+               {
+
+                       string type;
+
+                       switch(h.infoSize)
     {
-      if (!isBigEndian())
-       return;
-      header.size = rev(header.size);
-      header.dataOffset = rev(header.dataOffset);
-      header.infoSize = rev(header.infoSize);
-      header.width = rev(header.width);
-      header.height = rev(header.height);
-      header.planes_bpp[0] = rev(header.planes_bpp[0]);
-      header.planes_bpp[1] = rev(header.planes_bpp[1]);
-      header.compression = rev(header.compression);
-      header.dataSize = rev(header.dataSize);
-      header.xPelsPerMeter = rev(header.xPelsPerMeter);
-      header.yPelsPerMeter = rev(header.yPelsPerMeter);
-      header.colors = rev(header.colors);
-      header.importantColors = rev(header.importantColors);
+                               case 40:
+                                       type = "Windows 3.x style bitmap 
unsupported.";
+                                       break;
+                               case 12:
+                                       type = "OS/2 1.x style bitmap 
unsupported.";
+                                       break;
+                               case 64:
+                                       type = "OS/2 2.x style bitmap 
unsupported.";
+                                       break;
+                               case 108:
+                                       type = "Windows V4 (95/NT) style bitmap 
unsupported.";
+                                       break;
+                               case 124:
+                                       type = "Windows V5 (98/2000) style 
bitmap unsupported.";
+                                       break;
+                               default:
+                               {
+                                       ostringstream ts;
+                                       ts << "unknown bitmap type (info size = 
" << h.infoSize << ")";
+                                       type = ts.str();
+                               }
+                       }
+
+                       
throw(Exceptions::Image_IO::UnsupportedImageSubType("Windows BMP/DIB", type));
     }
+               h.width = read_u4(i);
+               h.height = read_u4(i);
+               h.planes = read_u2(i);
+               h.bpp = read_u2(i);
+               h.compression = read_u4(i);
+               h.dataSize = read_u4(i);
+               h.xPelsPerMeter = read_u4(i);
+               h.yPelsPerMeter = read_u4(i);
+               h.colors = read_u4(i);
+               h.importantColors = read_u4(i);
+
+               return h;
+       }
+
 
     void writeBMPHeader(unsigned int width, unsigned int height, unsigned int 
channels, ostream& out)
     {
       unsigned int rowSize = channels*width;
       if (rowSize%4)
        rowSize += 4-(rowSize%4);
-      out.write("BM",2);
-      struct BMPHeader header;
-      memset(&header,0,sizeof(header));
-      header.dataOffset=2+sizeof(header) + (channels == 1 ? 1024 : 0);
-      header.dataSize=rowSize*height;
-      header.size=header.dataOffset+header.dataSize;
-      header.width = width;
-      header.height = height;
-      header.compression = 0;
-      header.planes_bpp[0] = 1;
-      header.planes_bpp[1] = channels*8;
-      header.infoSize=40;
-      correctByteOrder(header);
-      out.write((const char*)&header,sizeof(header));
-      if (channels == 1) {
-       unsigned long val = 0;
-       unsigned long step = 0x01010101;
-       for (unsigned int i=0; i<256;i++, val+=step)
-         out.write((const char*)&val, 4);
+               
+               unsigned long dataSize = rowSize * height;
+               unsigned long offset  =  14 + 40 +  (channels == 1 ? 1024 : 0);
+
+               //Output header
+               /*   0  */ out << "BM";
+               /*   2  */ write_u4(out, offset + dataSize);  //File size
+               /*   6  */ write_u2(out, 0); //Reserved
+               /*   8  */ write_u2(out, 0); //Reserved
+               /*  10  */ write_u4(out, offset); //Data offset
+
+               //Output info
+               /*  14  */ write_u4(out, 40);    //3.x style header size
+               /*  18  */ write_u4(out, width); 
+               /*  22  */ write_u4(out, height);
+               /*  26  */ write_u2(out, 1);    //Planes (always 1);
+               /*  28  */ write_u2(out, channels*8); //Bpp
+               /*  30  */ write_u4(out, 0); //Compression method
+               /*  34  */ write_u4(out, dataSize);
+               /*  38  */ write_u4(out, 0); //Pixels per meter (x)
+               /*  42  */ write_u4(out, 0); //Pixels per meter (y)
+               /*  46  */ write_u4(out, 0); //Number of colours (0 == 2^N)
+               /*  50  */ write_u4(out, 0); //Number of important colora
+               
+               //Write the palette
+               if (channels == 1)
+               {
+                       for (unsigned int i=0; i<256;i++)
+                       {
+                               write_u1(out, i); //Blue
+                               write_u1(out, i); //Green
+                               write_u1(out, i); //Red
+                               write_u1(out, 0); //Reserved
+                       }
       }
     }
 
@@ -119,15 +196,21 @@
       in.read(tag,2);
       if (strcmp(tag, "BM") != 0)
        throw CVD::Exceptions::Image_IO::MalformedImage("BMP files must start 
with 'BM'");
-      struct BMPHeader header;
-      in.read((char*)&header, sizeof(header));
-      correctByteOrder(header);
-      channels = (unsigned int)header.planes_bpp[1]/8;
+               struct BMPHeader header = read_header(in);
+               
+               if(header.bpp == 8)
+                       channels = 1;
+               else if(header.bpp == 24)
+                       channels = 3;
+               else
+                       
throw(Exceptions::Image_IO::UnsupportedImageSubType("Windows BMP/DIB", "image 
is not 8 or 24 bits per pixel."));
+               
       compression = header.compression;
+               if(compression != 0)
+                       
throw(Exceptions::Image_IO::UnsupportedImageSubType("Windows BMP/DIB", 
"compressed images not supported."));
+                       
       width = header.width;
       height = header.height;
     }
-
-
   }
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]