opennurbs_bitmap.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003  //
00004  // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005  // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006  // McNeel & Associates.
00007  //
00008  // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009  // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010  // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011  //
00012  // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013  //
00015  */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 ON_VIRTUAL_OBJECT_IMPLEMENT( ON_Bitmap, ON_Object, "390465E9-3721-11d4-800B-0010830122F0")
00020 ;
00021 
00022 ON_OBJECT_IMPLEMENT( ON_WindowsBitmap, ON_Bitmap, "390465EB-3721-11d4-800B-0010830122F0")
00023 ;
00024 
00025 ON_OBJECT_IMPLEMENT( ON_EmbeddedBitmap, ON_Bitmap, "772E6FC1-B17B-4fc4-8F54-5FDA511D76D2")
00026 ;
00027 
00028 ON_OBJECT_IMPLEMENT( ON_WindowsBitmapEx, ON_WindowsBitmap, "203AFC17-BCC9-44fb-A07B-7F5C31BD5ED9")
00029 ;
00030 
00031 void
00032 ON_Bitmap::EmergencyDestroy ()
00033 {
00034   memset (&m_bitmap_id, 0, sizeof(m_bitmap_id));
00035   m_bitmap_index = -1;
00036   m_bitmap_name.EmergencyDestroy ();
00037   m_bitmap_filename.EmergencyDestroy ();
00038 }
00039 
00040 void
00041 ON_Bitmap::Destroy ()
00042 {
00043   m_bitmap_name.Destroy ();
00044   m_bitmap_filename.Destroy ();
00045   ON_Bitmap::EmergencyDestroy ();
00046 }
00047 
00048 void
00049 ON_Bitmap::Defaults ()
00050 {
00051   memset (&m_bitmap_id, 0, sizeof(m_bitmap_id));
00052   m_bitmap_index = -1;
00053   m_bitmap_name.Destroy ();
00054   m_bitmap_filename.Destroy ();
00055 }
00056 
00057 ON_Bitmap::ON_Bitmap ()
00058 {
00059   memset (&m_bitmap_id, 0, sizeof(m_bitmap_id));
00060   m_bitmap_index = -1;
00061 }
00062 
00063 ON_Bitmap::~ON_Bitmap ()
00064 {
00065 }
00066 
00067 void
00068 ON_Bitmap::Dump (ON_TextLog& dump) const
00069 {
00070   dump.Print ("width = %d pixels\n", Width ());
00071   dump.Print ("height = %d pixels\n", Height ());
00072   dump.Print ("bits per pixel = %d\n", BitsPerPixel ());
00073   dump.Print ("size of image = %d bytes\n", SizeofImage ());
00074 }
00075 
00076 static
00077 int
00078 ON_WindowsBitmapHelper_PaletteColorCount (int bmiHeader_biClrUsed, int bmiHeader_biBitCount)
00079 {
00080   int color_count = 0;
00081 
00082   if (bmiHeader_biClrUsed)
00083   {
00084     color_count = bmiHeader_biClrUsed;
00085   }
00086   else
00087   {
00088     switch (bmiHeader_biBitCount)
00089     {
00090       case 1:
00091         color_count = 2;
00092         break;
00093       case 4:
00094         color_count = 16;
00095         break;
00096       case 8:
00097         color_count = 256;
00098         break;
00099       default:
00100         color_count = 0;
00101         break;
00102     }
00103   }
00104   return color_count;
00105 }
00106 
00107 static size_t
00108 ON_WindowsBitmapHelper_SizeofPalette (int bmiHeader_biClrUsed, int bmiHeader_biBitCount)
00109 {
00110 #if defined(ON_OS_WINDOWS_GDI)
00111   return ( ON_WindowsBitmapHelper_PaletteColorCount(bmiHeader_biClrUsed,bmiHeader_biBitCount) * sizeof(RGBQUAD) );
00112 #else
00113   return (ON_WindowsBitmapHelper_PaletteColorCount (bmiHeader_biClrUsed, bmiHeader_biBitCount)
00114       * sizeof(ON_WindowsRGBQUAD));
00115 #endif
00116 }
00117 
00118 ON_WindowsBitmap::ON_WindowsBitmap () :
00119   m_bmi (0), m_bits (0), m_bFreeBMI (0)
00120 {
00121 }
00122 
00123 ON_WindowsBitmap::ON_WindowsBitmap (const ON_WindowsBitmap& src) :
00124   m_bmi (0), m_bits (0), m_bFreeBMI (0)
00125 {
00126   *this = src;
00127 }
00128 
00129 void
00130 ON_WindowsBitmap::EmergencyDestroy ()
00131 {
00132   m_bmi = 0;
00133   m_bits = 0;
00134   m_bFreeBMI = 0;
00135   ON_Bitmap::EmergencyDestroy ();
00136 }
00137 
00138 void
00139 ON_WindowsBitmap::Destroy ()
00140 {
00141   if (m_bmi)
00142   {
00143     if (1 == m_bFreeBMI || 3 == m_bFreeBMI)
00144       onfree (m_bmi);
00145     m_bmi = 0;
00146   }
00147   if (m_bits)
00148   {
00149     if (2 == m_bFreeBMI || 3 == m_bFreeBMI)
00150       onfree (m_bits);
00151     m_bits = 0;
00152   }
00153   m_bFreeBMI = 0;
00154   ON_Bitmap::Destroy ();
00155 }
00156 
00157 ON_BOOL32
00158 ON_WindowsBitmap::IsValid (ON_TextLog* text_log) const
00159 {
00160   bool rc = (m_bmi != NULL && m_bits != NULL && Width () > 0 && Height () > 0) ? true : false;
00161 
00162   if (!rc && 0 != text_log)
00163   {
00164     // TODO:  add a detailed diagnostic message
00165     text_log->Print ("ON_WindowsBitmap is not valid\n");
00166   }
00167   return rc;
00168 }
00169 
00170 #if defined(ON_OS_WINDOWS_GDI)
00171 
00172 static BITMAPINFO*
00173 ON_WindowsBitmapHelper_AllocBMI(size_t sizeof_palette, size_t sizeof_image)
00174 {
00175   // In theory,
00176   //    sz = sizeof(BITMAPINFOHEADER) + sizeof_palette + sizeof_image;
00177   // should work, but BITMAPINFO is only 4 bytes bigger than BITMAPINFOHEADER
00178   // and the allocation below will certainly work.
00179   size_t sz = sizeof(BITMAPINFO) + sizeof_palette + sizeof_image;
00180   BITMAPINFO* bmi = (BITMAPINFO*)onmalloc(sz);
00181   if ( bmi )
00182   {
00183     memset(bmi,0,sizeof(*bmi));
00184     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
00185   }
00186   return bmi;
00187 }
00188 
00189 #else
00190 
00191 static ON_WindowsBITMAPINFO*
00192 ON_WindowsBitmapHelper_AllocBMI (size_t sizeof_palette, size_t sizeof_image)
00193 {
00194   size_t sz = sizeof(ON_WindowsBITMAPINFO) + sizeof_palette + sizeof_image;
00195   ON_WindowsBITMAPINFO* bmi = (ON_WindowsBITMAPINFO*)onmalloc (sz);
00196   if (bmi)
00197   {
00198     memset (bmi, 0, sizeof(*bmi));
00199     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
00200   }
00201   return bmi;
00202 }
00203 
00204 #endif
00205 
00206 bool
00207 ON_WindowsBitmap::Create (int width, int height, int bits_per_pixel // 1, 2, 4, 8, 16, 24, or 32
00208 )
00209 {
00210   Destroy ();
00211 
00212   if (width < 1 || height < 1)
00213   {
00214     return false;
00215   }
00216   if (bits_per_pixel != 1 && bits_per_pixel != 2 && bits_per_pixel != 4 && bits_per_pixel != 8 && bits_per_pixel != 16
00217       && bits_per_pixel != 24 && bits_per_pixel != 32)
00218   {
00219     return false;
00220   }
00221 
00222 #if defined(ON_OS_WINDOWS_GDI)
00223   BITMAPINFOHEADER bh;
00224   const DWORD sizeof_RGBQUAD = sizeof(RGBQUAD);
00225 #else
00226   ON_WindowsBITMAPINFOHEADER bh;
00227   const unsigned int sizeof_RGBQUAD = sizeof(ON_WindowsRGBQUAD);
00228 #endif
00229   memset (&bh, 0, sizeof(bh));
00230   bh.biSize = sizeof(bh);
00231   bh.biWidth = width;
00232   bh.biHeight = height;
00233   bh.biPlanes = 1;
00234   bh.biBitCount = (unsigned short)bits_per_pixel; // cast is safe
00235   bh.biCompression = 0; // BI_RGB
00236   const int sizeof_scan = (((bits_per_pixel * width) + 31) / 32) * 4;
00237   bh.biSizeImage = height * sizeof_scan;
00238   bh.biXPelsPerMeter = 0;
00239   bh.biYPelsPerMeter = 0;
00240   bh.biClrUsed = 0;
00241   bh.biClrImportant = 0;
00242 
00243   int palette_color_count = 0;
00244   switch (bits_per_pixel)
00245   {
00246     case 1:
00247       palette_color_count = 2;
00248       break;
00249     case 4:
00250       palette_color_count = 16;
00251       break;
00252     case 8:
00253       palette_color_count = 256;
00254       break;
00255   }
00256   const int sizeof_palette = palette_color_count * sizeof_RGBQUAD;
00257 
00258   m_bmi = ON_WindowsBitmapHelper_AllocBMI (sizeof_palette, bh.biSizeImage);
00259 
00260   bool rc = false;
00261 
00262   if (m_bmi /*&& palette_color_count > 0*/)
00263   {
00264     m_bmi->bmiHeader = bh;
00265     m_bits = (unsigned char*)&m_bmi->bmiColors[palette_color_count];
00266 
00267     // default palette is gray scale
00268     if (palette_color_count > 0)
00269     {
00270       const int rgb_delta = 256 / palette_color_count;
00271       int i, rgb;
00272       for (i = 0, rgb = 0; i < palette_color_count; i++, rgb += rgb_delta)
00273       {
00274         if (rgb >= 256)
00275           rgb = 255;
00276         m_bmi->bmiColors[i].rgbBlue = (unsigned char)rgb;
00277         m_bmi->bmiColors[i].rgbGreen = (unsigned char)rgb;
00278         m_bmi->bmiColors[i].rgbRed = (unsigned char)rgb;
00279         m_bmi->bmiColors[i].rgbReserved = 0;
00280       }
00281     }
00282     rc = true;
00283   }
00284 
00285   return rc;
00286 }
00287 
00288 ON_WindowsBitmap::~ON_WindowsBitmap ()
00289 {
00290   Destroy ();
00291 }
00292 
00293 ON_WindowsBitmap&
00294 ON_WindowsBitmap::operator= (const ON_WindowsBitmap& src)
00295 {
00296   if (this != &src)
00297   {
00298     Destroy ();
00299     ON_Bitmap::operator= (src);
00300     if (src.m_bmi)
00301     {
00302       const int sizeof_palette = src.SizeofPalette ();
00303       const int sizeof_image = src.SizeofImage ();
00304       m_bmi = ON_WindowsBitmapHelper_AllocBMI (sizeof_palette, sizeof_image);
00305       if (m_bmi)
00306       {
00307         m_bFreeBMI = 1;
00308         m_bmi->bmiHeader = src.m_bmi->bmiHeader;
00309         if (sizeof_palette > 0)
00310         {
00311           memcpy (&m_bmi->bmiColors[0], &src.m_bmi->bmiColors[0], sizeof_palette);
00312         }
00313         if (sizeof_image > 0)
00314         {
00315           m_bits = (unsigned char*)&m_bmi->bmiColors[PaletteColorCount ()];
00316           if (src.m_bits)
00317             memcpy (m_bits, src.m_bits, sizeof_image);
00318           else
00319             memset (m_bits, 0, sizeof_image);
00320         }
00321         else
00322           m_bits = 0;
00323       }
00324     }
00325   }
00326   return *this;
00327 }
00328 
00329 int
00330 ON_WindowsBitmap::Width () const
00331 {
00332   return (m_bmi) ? m_bmi->bmiHeader.biWidth : 0;
00333 }
00334 
00335 int
00336 ON_WindowsBitmap::Height () const
00337 {
00338   return (m_bmi) ? m_bmi->bmiHeader.biHeight : 0;
00339 }
00340 
00341 int
00342 ON_WindowsBitmap::PaletteColorCount () const
00343 {
00344   return m_bmi ? ON_WindowsBitmapHelper_PaletteColorCount (m_bmi->bmiHeader.biClrUsed, m_bmi->bmiHeader.biBitCount) : 0;
00345 }
00346 
00347 int
00348 ON_WindowsBitmap::SizeofPalette () const
00349 {
00350   return m_bmi ? ((int)ON_WindowsBitmapHelper_SizeofPalette (m_bmi->bmiHeader.biClrUsed, m_bmi->bmiHeader.biBitCount))
00351       : 0;
00352 }
00353 
00354 int
00355 ON_WindowsBitmap::SizeofScan () const
00356 {
00357   int scan_width = 0;
00358   if (m_bmi)
00359   {
00360     int bitcount = m_bmi->bmiHeader.biBitCount;
00361     int width = Width ();
00362     scan_width = (((bitcount * width) + 31) / 32) * 4;
00363   }
00364   return scan_width;
00365 }
00366 
00367 int
00368 ON_WindowsBitmap::BitsPerPixel () const
00369 {
00370   return m_bmi ? m_bmi->bmiHeader.biBitCount : 0;
00371 }
00372 
00373 int
00374 ON_WindowsBitmap::SizeofImage () const
00375 {
00376   return m_bmi ? m_bmi->bmiHeader.biSizeImage : 0;
00377 }
00378 
00379 unsigned char*
00380 ON_WindowsBitmap::Bits (int scan_index)
00381 {
00382   const int sizeof_scan = SizeofScan ();
00383   unsigned char* bits = m_bmi ? (unsigned char*)&m_bmi->bmiColors[PaletteColorCount ()] : 0;
00384   if (bits && sizeof_scan && scan_index >= 0 && scan_index < Height ())
00385   {
00386     bits += (sizeof_scan * scan_index);
00387   }
00388   else
00389   {
00390     bits = 0;
00391   }
00392   return bits;
00393 }
00394 
00395 const unsigned char*
00396 ON_WindowsBitmap::Bits (int scan_index) const
00397 {
00398   const int sizeof_scan = SizeofScan ();
00399   const unsigned char* bits = m_bmi ? (const unsigned char*)&m_bmi->bmiColors[PaletteColorCount ()] : 0;
00400   if (bits && sizeof_scan && scan_index >= 0 && scan_index < Height ())
00401   {
00402     bits += (sizeof_scan * scan_index);
00403   }
00404   else
00405   {
00406     bits = 0;
00407   }
00408   return bits;
00409 }
00410 
00411 ON_Color
00412 ON_WindowsBitmap::Pixel (int column_index, int row_index) const
00413 {
00414   return Pixel (column_index, Bits (row_index));
00415 }
00416 
00417 ON_Color
00418 ON_WindowsBitmap::Pixel (int column_index, const unsigned char* scanbits) const
00419 {
00420   int r = 0, g = 0, b = 0, a = 0;
00421 
00422   unsigned int palindex;
00423 
00424   if (m_bmi && column_index >= 0 && column_index <= Width () && scanbits && !m_bmi->bmiHeader.biCompression)
00425   {
00426     switch (m_bmi->bmiHeader.biBitCount)
00427     {
00428       case 32:
00429         scanbits += (column_index * 4);
00430         b = *scanbits++;
00431         g = *scanbits++;
00432         r = *scanbits++;
00433         a = *scanbits;
00434         break;
00435 
00436       case 24:
00437         scanbits += (column_index * 3);
00438         b = *scanbits++;
00439         g = *scanbits++;
00440         r = *scanbits;
00441         break;
00442 
00443       case 8:
00444         // 256 color bitmap uses palette
00445         palindex = scanbits[column_index];
00446         b = m_bmi->bmiColors[palindex].rgbBlue;
00447         g = m_bmi->bmiColors[palindex].rgbGreen;
00448         r = m_bmi->bmiColors[palindex].rgbRed;
00449         a = m_bmi->bmiColors[palindex].rgbReserved;
00450         break;
00451 
00452       case 4:
00453       {
00454         // 16 color bitmap uses palette
00455         palindex = scanbits[column_index / 2];
00456         if (!(column_index % 2))
00457           palindex >>= 4;
00458         palindex &= 0x0F;
00459         b = m_bmi->bmiColors[palindex].rgbBlue;
00460         g = m_bmi->bmiColors[palindex].rgbGreen;
00461         r = m_bmi->bmiColors[palindex].rgbRed;
00462         a = m_bmi->bmiColors[palindex].rgbReserved;
00463       }
00464         break;
00465 
00466       case 1:
00467         // monochrome bitmap has 2 color palette
00468         palindex = (scanbits[column_index / 8] >> (7 - (column_index % 8))) & 0x01;
00469         b = m_bmi->bmiColors[palindex].rgbBlue;
00470         g = m_bmi->bmiColors[palindex].rgbGreen;
00471         r = m_bmi->bmiColors[palindex].rgbRed;
00472         a = m_bmi->bmiColors[palindex].rgbReserved;
00473         break;
00474     }
00475   }
00476 
00477   return ON_Color (r, g, b, a);
00478 }
00479 
00480 bool
00481 ON_WindowsBitmap::WriteUncompressed (ON_BinaryArchive& file) const
00482 {
00483 #if defined(ON_OS_WINDOWS_GDI)
00484   BITMAPINFOHEADER bmiHeader;
00485 #else
00486   ON_WindowsBITMAPINFOHEADER bmiHeader;
00487 #endif
00488 
00489   if (m_bmi)
00490   {
00491     bmiHeader = m_bmi->bmiHeader;
00492     bmiHeader.biSize = sizeof(bmiHeader);
00493   }
00494   else
00495   {
00496     memset (&bmiHeader, 0, sizeof(bmiHeader));
00497   }
00498   int i;
00499   short s;
00500   i = bmiHeader.biSize;
00501   bool rc = file.WriteInt (i);
00502   i = bmiHeader.biWidth;
00503   if (rc)
00504     rc = file.WriteInt (i);
00505   i = bmiHeader.biHeight;
00506   if (rc)
00507     rc = file.WriteInt (i);
00508   s = bmiHeader.biPlanes;
00509   if (rc)
00510     rc = file.WriteShort (s);
00511   s = bmiHeader.biBitCount;
00512   if (rc)
00513     rc = file.WriteShort (s);
00514   i = bmiHeader.biCompression;
00515   if (rc)
00516     rc = file.WriteInt (i);
00517   i = bmiHeader.biSizeImage;
00518   if (rc)
00519     rc = file.WriteInt (i);
00520   i = bmiHeader.biXPelsPerMeter;
00521   if (rc)
00522     rc = file.WriteInt (i);
00523   i = bmiHeader.biYPelsPerMeter;
00524   if (rc)
00525     rc = file.WriteInt (i);
00526   i = bmiHeader.biClrUsed;
00527   if (rc)
00528     rc = file.WriteInt (i);
00529   i = bmiHeader.biClrImportant;
00530   if (rc)
00531     rc = file.WriteInt (i);
00532 
00533   if (rc)
00534   {
00535     const int color_count = PaletteColorCount ();
00536     for (i = 0; i < color_count && rc; i++)
00537     {
00538       if (rc)
00539         rc = file.WriteChar (m_bmi->bmiColors[i].rgbBlue);
00540       if (rc)
00541         rc = file.WriteChar (m_bmi->bmiColors[i].rgbGreen);
00542       if (rc)
00543         rc = file.WriteChar (m_bmi->bmiColors[i].rgbRed);
00544       if (rc)
00545         rc = file.WriteChar (m_bmi->bmiColors[i].rgbReserved);
00546     }
00547     const int sizeof_image = SizeofImage ();
00548     if (sizeof_image > 0 && rc)
00549     {
00550       if (rc)
00551         rc = file.WriteByte (sizeof_image, &m_bmi->bmiColors[color_count]);
00552     }
00553   }
00554 
00555   return rc;
00556 }
00557 
00558 bool
00559 ON_WindowsBitmap::ReadUncompressed (ON_BinaryArchive& file)
00560 {
00561 #if defined(ON_OS_WINDOWS_GDI)
00562   BITMAPINFOHEADER bmiHeader;
00563 #else
00564   ON_WindowsBITMAPINFOHEADER bmiHeader;
00565 #endif
00566   memset (&bmiHeader, 0, sizeof(bmiHeader));
00567 
00568   Destroy ();
00569 
00570   int i;
00571   short s;
00572   bool rc;
00573 
00574   for (;;)
00575   {
00576     i = 0;
00577     s = 0;
00578     rc = file.ReadInt (&i);
00579     if (!rc)
00580       break;
00581     bmiHeader.biSize = i;
00582     rc = file.ReadInt (&i);
00583     if (!rc)
00584       break;
00585     bmiHeader.biWidth = i;
00586     rc = file.ReadInt (&i);
00587     if (!rc)
00588       break;
00589     bmiHeader.biHeight = i;
00590     rc = file.ReadShort (&s);
00591     if (!rc)
00592       break;
00593     bmiHeader.biPlanes = s;
00594     rc = file.ReadShort (&s);
00595     if (!rc)
00596       break;
00597     bmiHeader.biBitCount = s;
00598     rc = file.ReadInt (&i);
00599     if (!rc)
00600       break;
00601     bmiHeader.biCompression = i;
00602     rc = file.ReadInt (&i);
00603     if (!rc)
00604       break;
00605     bmiHeader.biSizeImage = i;
00606     rc = file.ReadInt (&i);
00607     if (!rc)
00608       break;
00609     bmiHeader.biXPelsPerMeter = i;
00610     rc = file.ReadInt (&i);
00611     if (!rc)
00612       break;
00613     bmiHeader.biYPelsPerMeter = i;
00614     rc = file.ReadInt (&i);
00615     if (!rc)
00616       break;
00617     bmiHeader.biClrUsed = i;
00618     rc = file.ReadInt (&i);
00619     if (!rc)
00620       break;
00621     bmiHeader.biClrImportant = i;
00622     break;
00623   }
00624 
00625   if (rc)
00626   {
00627     bmiHeader.biSize = sizeof(bmiHeader);
00628     const size_t sizeof_palette = ON_WindowsBitmapHelper_SizeofPalette (bmiHeader.biClrUsed, bmiHeader.biBitCount);
00629     const size_t sizeof_image = bmiHeader.biSizeImage;
00630 
00631     m_bmi = ON_WindowsBitmapHelper_AllocBMI (sizeof_palette, sizeof_image);
00632 
00633     if (!m_bmi)
00634     {
00635       rc = false;
00636     }
00637     else
00638     {
00639       m_bFreeBMI = 1;
00640       m_bmi->bmiHeader = bmiHeader;
00641       const int color_count = ON_WindowsBitmapHelper_PaletteColorCount (bmiHeader.biClrUsed, bmiHeader.biBitCount);
00642       int i;
00643       for (i = 0; i < color_count && rc; i++)
00644       {
00645         if (rc)
00646           rc = file.ReadChar (&m_bmi->bmiColors[i].rgbBlue);
00647         if (rc)
00648           rc = file.ReadChar (&m_bmi->bmiColors[i].rgbGreen);
00649         if (rc)
00650           rc = file.ReadChar (&m_bmi->bmiColors[i].rgbRed);
00651         if (rc)
00652           rc = file.ReadChar (&m_bmi->bmiColors[i].rgbReserved);
00653       }
00654       if (sizeof_image > 0 && rc)
00655       {
00656         m_bits = (unsigned char*)&m_bmi->bmiColors[color_count];
00657         if (rc)
00658           rc = file.ReadByte (sizeof_image, m_bits);
00659       }
00660     }
00661   }
00662   return rc;
00663 }
00664 
00665 ON_BOOL32
00666 ON_WindowsBitmap::Write (ON_BinaryArchive& file) const
00667 {
00668   return WriteCompressed (file);
00669 }
00670 
00671 ON_BOOL32
00672 ON_WindowsBitmap::Read (ON_BinaryArchive& file)
00673 {
00674   bool rc = false;
00675   if (file.Archive3dmVersion () == 1)
00676     rc = ReadUncompressed (file);
00677   else
00678     rc = ReadCompressed (file);
00679   return rc;
00680 }
00681 
00682 ON_WindowsBitmapEx::ON_WindowsBitmapEx ()
00683 {
00684 }
00685 
00686 ON_WindowsBitmapEx::~ON_WindowsBitmapEx ()
00687 {
00688 }
00689 
00690 ON_BOOL32
00691 ON_WindowsBitmapEx::Write (ON_BinaryArchive& file) const
00692 {
00693   ON_BOOL32 rc = file.Write3dmChunkVersion (1, 0);
00694   if (rc)
00695     rc = file.WriteString (m_bitmap_filename);
00696   if (rc)
00697     rc = ON_WindowsBitmap::WriteCompressed (file);
00698   return rc;
00699 }
00700 
00701 ON_BOOL32
00702 ON_WindowsBitmapEx::Read (ON_BinaryArchive& file)
00703 {
00704   int major_version = 0;
00705   int minor_version = 0;
00706   ON_BOOL32 rc = file.Read3dmChunkVersion (&major_version, &minor_version);
00707   if (rc && 1 == major_version)
00708   {
00709     // Calling ON_WindowsBitmap::ReadCompressed() destroys
00710     // m_bitmap_filename, so we have to read it into a local
00711     // string and make the assigment after calling 
00712     // ON_WindowsBitmap::ReadCompressed().
00713     ON_wString bitmap_filename;
00714     if (rc)
00715       rc = file.ReadString (bitmap_filename);
00716     if (!rc)
00717       bitmap_filename.Destroy ();
00718 
00719     if (rc)
00720       rc = ON_WindowsBitmap::ReadCompressed (file);
00721 
00722     m_bitmap_filename = bitmap_filename;
00723   }
00724   else
00725     rc = false;
00726   return rc;
00727 }
00728 
00729 bool
00730 ON_WindowsBitmap::WriteCompressed (ON_BinaryArchive& file) const
00731 {
00732   int color_count = 0;
00733   int sizeof_palette = 0;
00734   int sizeof_image = 0;
00735   bool bContiguousBitmap = IsContiguous ();
00736 #if defined(ON_OS_WINDOWS_GDI)
00737   BITMAPINFOHEADER bmiHeader;
00738 #else
00739   ON_WindowsBITMAPINFOHEADER bmiHeader;
00740 #endif
00741   if (m_bmi)
00742   {
00743     bmiHeader = m_bmi->bmiHeader;
00744     color_count = PaletteColorCount ();
00745     sizeof_palette = color_count * sizeof(*m_bmi->bmiColors);
00746     sizeof_image = SizeofImage ();
00747     if (0 == sizeof_image)
00748       bContiguousBitmap = true;
00749   }
00750   else
00751   {
00752     bContiguousBitmap = true;
00753     color_count = 0;
00754     sizeof_palette = 0;
00755     sizeof_image = 0;
00756     memset (&bmiHeader, 0, sizeof(bmiHeader));
00757   }
00758   int i;
00759   short s;
00760   i = bmiHeader.biSize;
00761   bool rc = file.WriteInt (i);
00762   i = bmiHeader.biWidth;
00763   if (rc)
00764     rc = file.WriteInt (i);
00765   i = bmiHeader.biHeight;
00766   if (rc)
00767     rc = file.WriteInt (i);
00768   s = bmiHeader.biPlanes;
00769   if (rc)
00770     rc = file.WriteShort (s);
00771   s = bmiHeader.biBitCount;
00772   if (rc)
00773     rc = file.WriteShort (s);
00774   i = bmiHeader.biCompression;
00775   if (rc)
00776     rc = file.WriteInt (i);
00777   i = bmiHeader.biSizeImage;
00778   if (rc)
00779     rc = file.WriteInt (i);
00780   i = bmiHeader.biXPelsPerMeter;
00781   if (rc)
00782     rc = file.WriteInt (i);
00783   i = bmiHeader.biYPelsPerMeter;
00784   if (rc)
00785     rc = file.WriteInt (i);
00786   i = bmiHeader.biClrUsed;
00787   if (rc)
00788     rc = file.WriteInt (i);
00789   i = bmiHeader.biClrImportant;
00790   if (rc)
00791     rc = file.WriteInt (i);
00792 
00793   if (rc)
00794   {
00795     if (bContiguousBitmap)
00796     {
00797       const int sizeof_buffer = sizeof_palette + sizeof_image;
00798       // palette and bits are compressed in a single chunk
00799       rc = file.WriteCompressedBuffer (sizeof_buffer, (0 != m_bmi) ? m_bmi->bmiColors : 0);
00800     }
00801     else
00802     {
00803       // 28 July 2003
00804       //     Added support for writing non-contiguous bitmaps
00805       // palette 
00806       rc = file.WriteCompressedBuffer (sizeof_palette, m_bmi->bmiColors);
00807       if (rc)
00808       {
00809         // image bits
00810         rc = file.WriteCompressedBuffer (sizeof_image, m_bits);
00811       }
00812     }
00813   }
00814 
00815   return rc;
00816 }
00817 
00818 bool
00819 ON_WindowsBitmap::ReadCompressed (ON_BinaryArchive& file)
00820 {
00821   ON_BOOL32 bFailedCRC = false;
00822   Destroy ();
00823 #if defined(ON_OS_WINDOWS_GDI)
00824   BITMAPINFOHEADER bmiHeader;
00825 #else
00826   ON_WindowsBITMAPINFOHEADER bmiHeader;
00827 #endif
00828   memset (&bmiHeader, 0, sizeof(bmiHeader));
00829   int i;
00830   short s;
00831   bool rc;
00832 
00833   for (;;)
00834   {
00835     i = 0;
00836     s = 0;
00837     rc = file.ReadInt (&i);
00838     if (!rc)
00839       break;
00840     bmiHeader.biSize = i;
00841     rc = file.ReadInt (&i);
00842     if (!rc)
00843       break;
00844     bmiHeader.biWidth = i;
00845     rc = file.ReadInt (&i);
00846     if (!rc)
00847       break;
00848     bmiHeader.biHeight = i;
00849     rc = file.ReadShort (&s);
00850     if (!rc)
00851       break;
00852     bmiHeader.biPlanes = s;
00853     rc = file.ReadShort (&s);
00854     if (!rc)
00855       break;
00856     bmiHeader.biBitCount = s;
00857     rc = file.ReadInt (&i);
00858     if (!rc)
00859       break;
00860     bmiHeader.biCompression = i;
00861     rc = file.ReadInt (&i);
00862     if (!rc)
00863       break;
00864     bmiHeader.biSizeImage = i;
00865     rc = file.ReadInt (&i);
00866     if (!rc)
00867       break;
00868     bmiHeader.biXPelsPerMeter = i;
00869     rc = file.ReadInt (&i);
00870     if (!rc)
00871       break;
00872     bmiHeader.biYPelsPerMeter = i;
00873     rc = file.ReadInt (&i);
00874     if (!rc)
00875       break;
00876     bmiHeader.biClrUsed = i;
00877     rc = file.ReadInt (&i);
00878     if (!rc)
00879       break;
00880     bmiHeader.biClrImportant = i;
00881     break;
00882   }
00883 
00884   if (rc)
00885   {
00886     bmiHeader.biSize = sizeof(bmiHeader);
00887     const size_t sizeof_palette = ON_WindowsBitmapHelper_SizeofPalette (bmiHeader.biClrUsed, bmiHeader.biBitCount);
00888     const size_t sizeof_image = bmiHeader.biSizeImage;
00889     m_bmi = ON_WindowsBitmapHelper_AllocBMI (sizeof_palette, sizeof_image);
00890     if (!m_bmi)
00891     {
00892       rc = false;
00893     }
00894     else
00895     {
00896       m_bFreeBMI = 1;
00897       m_bmi->bmiHeader = bmiHeader;
00898       m_bmi->bmiHeader.biSize = sizeof(m_bmi->bmiHeader);
00899       const int color_count = ON_WindowsBitmapHelper_PaletteColorCount (bmiHeader.biClrUsed, bmiHeader.biBitCount);
00900       if (sizeof_image > 0)
00901         m_bits = (unsigned char*)&m_bmi->bmiColors[color_count];
00902       size_t sizeof_buffer = 0;
00903       rc = file.ReadCompressedBufferSize (&sizeof_buffer);
00904       if (rc)
00905       {
00906         const size_t sizeof_colors = color_count * sizeof(*m_bmi->bmiColors);
00907         if (sizeof_buffer == sizeof_colors || sizeof_buffer == sizeof_colors + sizeof_image)
00908         {
00909           // palette and image bits are compressed into one or two chunks
00910           rc = file.ReadCompressedBuffer (sizeof_buffer, m_bmi->bmiColors, &bFailedCRC);
00911           if (rc && sizeof_image > 0 && sizeof_buffer == sizeof_colors)
00912           {
00913             // 28 July 2003
00914             //     Added support for reading non-contiguous bitmaps
00915             sizeof_buffer = 0;
00916             rc = file.ReadCompressedBufferSize (&sizeof_buffer);
00917             if (rc)
00918             {
00919               if (sizeof_buffer == sizeof_image)
00920               {
00921                 // image bits are compressed into a separatechunk
00922                 rc = file.ReadCompressedBuffer (sizeof_buffer, &m_bmi->bmiColors[color_count], &bFailedCRC);
00923               }
00924               else
00925               {
00926                 ON_ERROR("ON_WindowsBitmap::ReadCompressed() image bits buffer size mismatch\n");
00927                 rc = false;
00928               }
00929             }
00930           }
00931         }
00932         else
00933         {
00934           ON_ERROR("ON_WindowsBitmap::ReadCompressed() buffer size mismatch\n");
00935           rc = false;
00936         }
00937       }
00938     }
00939   }
00940   return rc;
00941 }
00942 
00943 bool
00944 ON_WindowsBitmap::IsContiguous () const
00945 {
00946   bool rc = false;
00947   if (0 != m_bmi && 0 != m_bits && m_bmi->bmiHeader.biSizeImage > 0)
00948   {
00949     // p1 points to the first byte after the color palette.
00950     unsigned char* p1 = (unsigned char*)&m_bmi->bmiColors[PaletteColorCount ()];
00951     rc = (m_bits == p1);
00952   }
00953   return rc;
00954 }
00955 
00956 #if defined(ON_OS_WINDOWS_GDI)
00957 
00958 #pragma message( " --- OpenNURBS including Windows BITMAPINFO support in ON_WindowsBitmap" )
00959 
00960 ON_WindowsBitmap::ON_WindowsBitmap( const BITMAPINFO& src )
00961 : m_bmi(0), m_bits(0), m_bFreeBMI(0)
00962 {
00963   *this = src;
00964 }
00965 
00966 ON_WindowsBitmap& ON_WindowsBitmap::operator=( const BITMAPINFO& src )
00967 {
00968   Destroy();
00969   int color_count = ON_WindowsBitmapHelper_PaletteColorCount(src.bmiHeader.biClrUsed, src.bmiHeader.biBitCount );
00970   Create(&src,(const unsigned char*)(&src.bmiColors[color_count]),true);
00971   return *this;
00972 }
00973 
00974 bool ON_WindowsBitmap::Create( const BITMAPINFO* bmi, const unsigned char* bits, bool bCopy )
00975 {
00976   bool rc = false;
00977   Destroy();
00978   m_bFreeBMI = 0;
00979   m_bmi = 0;
00980   m_bits = 0;
00981 
00982   if ( 0 != bmi )
00983   {
00984     if ( bCopy )
00985     {
00986       // allocate a contiguous Windows device independent bitmap
00987       const size_t sizeof_palette = ON_WindowsBitmapHelper_SizeofPalette(bmi->bmiHeader.biClrUsed, bmi->bmiHeader.biBitCount );
00988       const int sizeof_image = bmi->bmiHeader.biSizeImage;
00989       m_bmi = ON_WindowsBitmapHelper_AllocBMI( sizeof_palette, (bCopy?sizeof_image:0) );
00990       if ( 0 != m_bmi )
00991       {
00992         rc = true;
00993         m_bFreeBMI = 1; // ~ON_WindowsBitmap will free the m_bmi pointer
00994         m_bmi->bmiHeader = bmi->bmiHeader;
00995         m_bmi->bmiHeader.biSize = sizeof(m_bmi->bmiHeader);
00996         int color_count = ON_WindowsBitmapHelper_PaletteColorCount(bmi->bmiHeader.biClrUsed, bmi->bmiHeader.biBitCount );
00997         if ( color_count > 0 )
00998         {
00999           memcpy( &m_bmi->bmiColors[0], &bmi->bmiColors[0], color_count*sizeof(m_bmi->bmiColors[0]) );
01000         }
01001         if ( bCopy && sizeof_image > 0 )
01002         {
01003           m_bits = (unsigned char*)(&m_bmi->bmiColors[color_count]);
01004           if ( 0 != bits )
01005           memcpy( m_bits, bits, sizeof_image );
01006           else
01007           memset( m_bits, 0, sizeof_image );
01008         }
01009       }
01010     }
01011     else
01012     {
01013       // share BITMAPINFO memory
01014       rc = true;
01015       m_bmi = const_cast<BITMAPINFO*>(bmi);
01016       m_bits = const_cast<unsigned char*>(bits);
01017     }
01018   }
01019 
01020   return rc;
01021 }
01022 
01023 ON_WindowsBitmap::ON_WindowsBitmap( const BITMAPINFO* src )
01024 : m_bmi(0), m_bits(0), m_bFreeBMI(0)
01025 {
01026   if ( 0 != src )
01027   {
01028     int color_count = ON_WindowsBitmapHelper_PaletteColorCount(src->bmiHeader.biClrUsed, src->bmiHeader.biBitCount );
01029     Create(src,(const unsigned char*)(&src->bmiColors[color_count]),false);
01030   }
01031 }
01032 
01033 //BITMAPINFO* ON_WindowsBitmap::Convert()
01034 //{
01035 //  return m_bmi;
01036 //}
01037 
01038 #endif
01039 
01041 //
01042 // ON_EmbeddedBitmap - used to embed bitmaps in 3dm archives
01043 //
01044 
01045 ON_EmbeddedBitmap::ON_EmbeddedBitmap ()
01046 {
01047   m_buffer = 0;
01048   m_sizeof_buffer = 0;
01049   m_free_buffer = 0;
01050   m_biffer_crc32 = 0;
01051 }
01052 
01053 ON_EmbeddedBitmap::~ON_EmbeddedBitmap ()
01054 {
01055   Destroy ();
01056 }
01057 
01058 void
01059 ON_EmbeddedBitmap::EmergencyDestroy ()
01060 {
01061   m_buffer = 0;
01062   m_sizeof_buffer = 0;
01063   m_free_buffer = 0;
01064   m_biffer_crc32 = 0;
01065   ON_Bitmap::EmergencyDestroy ();
01066 }
01067 
01068 void
01069 ON_EmbeddedBitmap::Destroy ()
01070 {
01071   if (0 != m_buffer && 1 == m_free_buffer)
01072   {
01073     onfree (m_buffer);
01074     m_buffer = 0;
01075   }
01076   m_sizeof_buffer = 0;
01077   m_free_buffer = 0;
01078   m_biffer_crc32 = 0;
01079   ON_Bitmap::Destroy ();
01080 }
01081 
01082 void
01083 ON_EmbeddedBitmap::Create (int sizeof_buffer)
01084 {
01085   Destroy ();
01086   if (sizeof_buffer > 0)
01087   {
01088     m_buffer = onmalloc (sizeof_buffer);
01089     if (0 != m_buffer)
01090     {
01091       m_sizeof_buffer = sizeof_buffer;
01092       m_free_buffer = 1;
01093     }
01094   }
01095 }
01096 
01097 ON_BOOL32
01098 ON_EmbeddedBitmap::IsValid (ON_TextLog* text_log) const
01099 {
01100   if (0 == m_buffer)
01101   {
01102     if (0 != text_log)
01103       text_log->Print ("ON_EmbeddedBitmap m_buffer = 0\n");
01104     return false;
01105   }
01106   return true;
01107 }
01108 
01109 ON_BOOL32
01110 ON_EmbeddedBitmap::Write (ON_BinaryArchive& file) const
01111 {
01112   ON_BOOL32 rc = file.Write3dmChunkVersion (1, 0);
01113   if (rc)
01114     rc = file.WriteString (m_bitmap_filename);
01115   if (rc)
01116     rc = file.WriteInt (m_biffer_crc32);
01117   int i = 1; // 0 = uncompressed, 1 = compressed
01118   if (rc)
01119     rc = file.WriteInt (i); // 1 = compressed
01120   switch (i)
01121   {
01122     case 0:
01123       if (rc)
01124         rc = file.WriteSize (m_sizeof_buffer);
01125       if (rc)
01126         rc = file.WriteByte (m_sizeof_buffer, m_buffer);
01127       break;
01128     case 1:
01129       if (rc)
01130         rc = file.WriteCompressedBuffer (m_sizeof_buffer, m_buffer);
01131       break;
01132   }
01133   return rc;
01134 }
01135 
01136 ON_BOOL32
01137 ON_EmbeddedBitmap::Read (ON_BinaryArchive& file)
01138 {
01139   ON_BOOL32 bFailedCRC = false;
01140   Destroy ();
01141 
01142   int major_version = 0;
01143   int minor_version = 0;
01144   ON_BOOL32 rc = file.Read3dmChunkVersion (&major_version, &minor_version);
01145   if (rc && 1 == major_version)
01146   {
01147     int i = -1;
01148     if (rc)
01149       rc = file.ReadString (m_bitmap_filename);
01150     if (rc)
01151       rc = file.ReadInt (&m_biffer_crc32);
01152     rc = file.ReadInt (&i);
01153     if (rc)
01154     {
01155       switch (i)
01156       {
01157         case 0:
01158           if (rc)
01159           {
01160             if (rc)
01161               rc = file.ReadSize (&m_sizeof_buffer);
01162             if (rc && m_sizeof_buffer > 0)
01163             {
01164               m_buffer = onmalloc (m_sizeof_buffer);
01165               m_free_buffer = 1;
01166             }
01167             if (rc)
01168               rc = file.ReadByte (m_sizeof_buffer, m_buffer);
01169           }
01170           break;
01171         case 1:
01172           if (rc)
01173           {
01174             if (rc)
01175               rc = file.ReadCompressedBufferSize (&m_sizeof_buffer);
01176             if (rc && m_sizeof_buffer > 0)
01177             {
01178               m_buffer = onmalloc (m_sizeof_buffer);
01179               m_free_buffer = 1;
01180             }
01181             if (rc)
01182               rc = file.ReadCompressedBuffer (m_sizeof_buffer, m_buffer, &bFailedCRC);
01183           }
01184           break;
01185       }
01186     }
01187   }
01188   else
01189     rc = false;
01190 
01191   return rc;
01192 }
01193 
01194 int
01195 ON_EmbeddedBitmap::Width () const
01196 {
01197   return 0;
01198 }
01199 int
01200 ON_EmbeddedBitmap::Height () const
01201 {
01202   return 0;
01203 }
01204 int
01205 ON_EmbeddedBitmap::BitsPerPixel () const
01206 {
01207   return 0;
01208 }
01209 int
01210 ON_EmbeddedBitmap::SizeofScan () const
01211 {
01212   return 0;
01213 }
01214 int
01215 ON_EmbeddedBitmap::SizeofImage () const
01216 {
01217   return 0;
01218 }
01219 unsigned char*
01220 ON_EmbeddedBitmap::Bits (int)
01221 {
01222   return 0;
01223 }
01224 const unsigned char*
01225 ON_EmbeddedBitmap::Bits (int) const
01226 {
01227   return 0;
01228 }
01229 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:00