/* $Header$ */
/* $NoKeywords: $ */
/*
//
// Copyright (c) 1993-2001 Robert McNeel & Associates. All rights reserved.
// Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/

////////////////////////////////////////////////////////////////
//
//  Defines ON_WindowsBITMAPINFO class that is used to provide OS independent
//  serialization of Windows device independent bitmaps (BITMAPINFO) used
//  to store preview images.
//
////////////////////////////////////////////////////////////////

#if !defined(OPENNURBS_BITMAP_INC_)
#define OPENNURBS_BITMAP_INC_

class ON_CLASS ON_Bitmap : public ON_Object
{
  // virtual base class for bitmap objects
  ON_OBJECT_DECLARE(ON_Bitmap);
public:
  ON_Bitmap();
  ~ON_Bitmap();

  // C++ defaults work fine
  //ON_Bitmap(const ON_Bitmap&);
  //ON_Bitmap& operator=(const ON_Bitmap&);

  // virtual
  ON_UUID ModelObjectId() const;


  void Dump( ON_TextLog& ) const; // for debugging

  void EmergencyDestroy();
  void Destroy();

  void Defaults();

  virtual
  int Width() const = 0;
  virtual
  int Height() const = 0; // >0 means it's a bottom-up bitmap with origin at lower right
                          // <0 means it's a top-down bitmap with origin at upper left
  virtual
  int BitsPerPixel() const = 0; // bits per pixel
  virtual
  int SizeofScan() const = 0;  // number of bytes per scan line
  virtual
  int SizeofImage() const = 0; // size of current map in bytes

  virtual
  unsigned char* Bits(
    int // index of scan line
    ) = 0;
  virtual
  const unsigned char* Bits(
    int // index of scan line
    ) const = 0;

  ON_UUID    m_bitmap_id;
  int        m_bitmap_index;
  ON_wString m_bitmap_name;     // descriptive name
  ON_wString m_bitmap_filename; // full path to file
};


#if !defined(ON_OS_WINDOWS_GDI)

// These are the values of the Windows defines mentioned
// in the comment below.  If you're running on Windows,
// they get defined by Windows system header files.
// If you aren't running on Windows, then you don't
// need them.
//#define BI_RGB        0L
//#define BI_RLE8       1L
//#define BI_RLE4       2L
//#define BI_BITFIELDS  3L

// Mimics Windows BITMAPINFOHEADER structure.
// For details searh for "BITMAPINFOHEADER" at http://msdn.microsoft.com/default.asp
struct ON_WindowsBITMAPINFOHEADER
{
  unsigned int   biSize;          // DWORD = sizeof(BITMAPINFOHEADER)
  int            biWidth;         // LONG  = width (in pixels) of (decompressed) bitmap
  int            biHeight;        // LONG  = height (in pixels) of (decompressed) bitmap
                                  //         >0 means it's a bottom-up bitmap with origin
                                  //            in the lower left corner.
                                  //         <0 means it's a top-down bitmap with origin
                                  //            in the upper left corner.
  unsigned short biPlanes;        // WORD  = number of planes
                                  //         (always 1 in current Windows versions)
  unsigned short biBitCount;      // WORD  = bits per pixel (0,1,4,8,16,24,32 are valid)
                                  //         1 See http://msdn.microsoft.com/default.asp
                                  //         4 See http://msdn.microsoft.com/default.asp
                                  //         8 The bitmap has a maximum of 256 colors,
                                  //           and the bmiColors member contains up
                                  //           to 256 entries. In this case, each byte
                                  //           in the array represents a single pixel.
                                  //        16 See http://msdn.microsoft.com/default.asp
                                  //        24 If biClrUsed=0 and biCompression=BI_RGB(0),
                                  //           then each 3-byte triplet in the bitmap
                                  //           array represents the relative intensities
                                  //           of blue, green, and red, respectively, for
                                  //           a pixel. For other possibilities, see
                                  //           http://msdn.microsoft.com/default.asp
                                  //        32 If biClrUsed=0 and biCompression=BI_RGB(0),
                                  //           then each 4-byte DWORD in the bitmap
                                  //           array represents the relative intensities
                                  //           of blue, green, and red, respectively, for
                                  //           a pixel. The high byte in each DWORD is not
                                  //           used.
                                  //           If biClrUsed=3, biCompression=BITFIELDS(3),
                                  //           biColors[0] = red mask (0x00FF0000),
                                  //           biColors[1] = green mask (0x0000FF00), and
                                  //           biColors[2] = blue mask (0x000000FF),
                                  //           then tese masks are used with each 4-byte
                                  //           DWORD in the bitmap array to determine
                                  //           the pixel's relative intensities.                                 //
                                  //           For other possibilities, see
                                  //           http://msdn.microsoft.com/default.asp
  unsigned int   biCompression;   // DWORD   Currently, Windows defines the following
                                  //         types of compression.
                                  //         =0  BI_RGB (no compression)
                                  //         =1  BI_RLE8 (run length encoded used for 8 bpp)
                                  //         =2  BI_RLE4 (run length encoded used for 4 bpp)
                                  //         =3  BI_BITFIELDS  Specifies that the bitmap is
                                  //             not compressed and that the color table
                                  //             consists of three DWORD color masks that
                                  //             specify the red, green, and blue components,
                                  //             respectively, of each pixel. This is valid
                                  //             when used with 16- and 32-bit-per-pixel
                                  //             bitmaps.
                                  //         =4  BI_JPEG (not supported in Win 95/NT4)
                                  //
  unsigned int   biSizeImage;     // DWORD = bytes in image
  int            biXPelsPerMeter; // LONG
  int            biYPelsPerMeter; // LONG
  unsigned int   biClrUsed;       // DWORD = 0 or true length of bmiColors[] array.  If 0,
                                  //           then the value of biBitCount determines the
                                  //           length of the bmiColors[] array.
  unsigned int   biClrImportant;  // DWORD
};

struct ON_WindowsRGBQUAD {
  // Mimics Windows RGBQUAD structure.
  // For details searh for "RGBQUAD" at http://msdn.microsoft.com/default.asp
  unsigned char rgbBlue;      // BYTE
  unsigned char rgbGreen;     // BYTE
  unsigned char rgbRed;       // BYTE
  unsigned char rgbReserved;  // BYTE
};

struct ON_WindowsBITMAPINFO
{
  // Mimics Windows BITMAPINFO structure.
  // For details searh for "BITMAPINFO" at http://msdn.microsoft.com/default.asp
  ON_WindowsBITMAPINFOHEADER bmiHeader;
  ON_WindowsRGBQUAD bmiColors[1]; // The "[1]" is for the compiler.  In
                                  // practice this array commonly has
                                  // length 0, 3, or 256 and a BITMAPINFO*
                                  // points to a contiguous piece of memory
                                  // that contains
                                  //
                                  //          BITMAPINFOHEADER
                                  //          RGBQUAD[length determined by flags]
                                  //          unsigned char[biSizeImage]
                                  //
                                  // See the ON_WindowsBITMAPINFOHEADER comments
                                  // and http://msdn.microsoft.com/default.asp
                                  // for more details.
};

#endif

// OBSOLETE // class ON_OpenGLBitmap;

class ON_CLASS ON_WindowsBitmap : public ON_Bitmap
{
  ON_OBJECT_DECLARE(ON_WindowsBitmap);
  // Uncompressed 8 bpp, 24 bpp, or 32 bpp Windows device
  // independent bitmaps (DIB)
public:

  ON_WindowsBitmap();
  ON_WindowsBitmap( const ON_WindowsBitmap& );
  ~ON_WindowsBitmap();

  ON_WindowsBitmap& operator=( const ON_WindowsBitmap& );

  void EmergencyDestroy();
  void Destroy();

  bool Create(
         int, // width
         int, // height
         int  // bits per pixel ( 1, 2, 4, 8, 16, 24, or 32 )
         );

  /*
  Description:
    Tests an object to see if its data members are correctly
    initialized.
  Parameters:
    text_log - [in] if the object is not valid and text_log
        is not NULL, then a brief englis description of the
        reason the object is not valid is appened to the log.
        The information appended to text_log is suitable for
        low-level debugging purposes by programmers and is
        not intended to be useful as a high level user
        interface tool.
  Returns:
    @untitled table
    TRUE     object is valid
    FALSE    object is invalid, uninitialized, etc.
  Remarks:
    Overrides virtual ON_Object::IsValid
  */
  BOOL IsValid( ON_TextLog* text_log = NULL ) const;

  BOOL Write( ON_BinaryArchive& ) const; // writes compressed image
  BOOL Read( ON_BinaryArchive& );        // reads compressed image
  bool WriteCompressed( ON_BinaryArchive& ) const;
  bool ReadCompressed( ON_BinaryArchive& );
  bool WriteUncompressed( ON_BinaryArchive& ) const;
  bool ReadUncompressed( ON_BinaryArchive& );

  int Width() const;
  int Height() const; // >0 means it's a bottom-up bitmap with origin at lower right
                      // <0 means it's a top-down bitmap with origin at upper left

  int PaletteColorCount() const; // number of colors in palette
  int SizeofPalette() const;     // number of bytes in palette
  int BitsPerPixel() const;
  //int SizeofPixel() const;       // number of bytes per pixel
  int SizeofScan() const;        // number of bytes per scan line
  int SizeofImage() const;       // number of bytes in image

  unsigned char* Bits(
    int // index of scan line
    );
  const unsigned char* Bits(
    int // index of scan line
    ) const;

  //int PaletteIndex( ON_Color ) const; // for 8bpp bitmaps

  ON_Color Pixel(
    int, // 0 <= i < width
    int  // 0 <= j < height
    ) const;
  ON_Color Pixel(
    int,  // 0 <= i < width
    const unsigned char* // value of Bits( j )
    ) const;

  //BOOL SetColor( // sets entire map to specified color
  //       ON_Color
  //       );

#if defined(ON_OS_WINDOWS_GDI)

  /*
  Description:
    Create an ON_WindowsBitmap from a contiguous bitmap.
    Copies src.
  Parameters:
    src - [in] contiguous Windows device independent bitmap.
  Remarks:
    If the current Windows BITMAPINFO is identical to ON_WindowsBITMAPINFO,
    then the result of this call is identical to

         int color_count = number of colors in bitmap's palette;
         ON_WindowsBitmap::Create( &src, &src.bmiColors[color_count], true ).

  See Also:
    ON_WindowsBitmap::Create
  */
  ON_WindowsBitmap( const BITMAPINFO& src );

  /*
  Description:
    Create an ON_WindowsBitmap from a contiguous bitmap.
    Shares bitmap memory with src.
  Parameters:
    src - [in] contiguous Windows device independent bitmap.
  See Also:
    ON_WindowsBitmap::Create
  Remarks:
    ~ON_WindowsBitmap will not delete src.
  */
  ON_WindowsBitmap( const BITMAPINFO* src );

  /*
  Description:
    Create an ON_WindowsBitmap from a contiguous bitmap.
    Copies src.
  Parameters:
    src - [in] contiguous Windows device independent bitmap.
  See Also:
    ON_WindowsBitmap::Create
  */
  ON_WindowsBitmap& operator=( const BITMAPINFO& src );


  // OBSOLETE - just use the m_bmi pointer
  //__declspec(deprecated) BITMAPINFO* Convert();

  /*
  Description:
    Create and ON_WindowsBitmap from a Windows BITMAPINFO pointer
    and a pointer to the bits.

    This is intended to make it easy to write compressed bimaps.
    For ON_WindowsBitmap classes created with ON_WindowsBitmap::Share,
    ON_WindowsBitmap::Destroy and ~ON_WindowsBitmap will
    not free the bmi and bits memory.

  Parameters:
    bmi  - [in] valid BITMAPINFO
    bits - [in] bits for BITMAPINFO
    bCopy - [in] If true, the bmi and bits are copied into a contiguous
                 bitmap that will be deleted by ~ON_WindowsBitmap.
                 If false, the m_bmi and m_bits pointers on this class
                 are simply set to bmi and bits.  In this case,
                 ~ON_WindowsBitmap will not free the bmi or bits
                 memory.

  Example:

          ON_BinaryArchive archive = ...;
          BITMAPINFO* bmi = 0;
          unsigned char* bits = 0;
          int color_count = ...; // number of colors in palette

          int sizeof_palette = sizeof(bmi->bmiColors[0]) * color_count;

          BITMAPINFO* bmi = (LPBITMAPINFO)calloc( 1, sizeof(*bmi) + sizeof_palette );

          bmi->bmiHeader.biSize          = sizeof(bmi->bmiHeader);
          bmi->bmiHeader.biWidth         = width;
          bmi->bmiHeader.biHeight        = height;
          bmi->bmiHeader.biPlanes        = 1;
          bmi->bmiHeader.biBitCount      = (USHORT)color_depth;
          bmi->bmiHeader.biCompression   = BI_RGB;
          bmi->bmiHeader.biXPelsPerMeter = 0;
          bmi->bmiHeader.biYPelsPerMeter = 0;
          bmi->bmiHeader.biClrUsed       = 0;
          bmi->bmiHeader.biClrImportant  = 0;
          bmi->bmiHeader.biSizeImage     = GetStorageSize();

          // initialize palette
          ...

          HBITMAP hbm = ::CreateDIBSection( NULL, bmi, ..., (LPVOID*)&bits, NULL, 0);

          {
            // Use ON_WindowsBitmap to write a compressed bitmap to
            // archive.  Does not modify bmi or bits.
            ON_WindowsBitmap onbm;
            onbm.Create(bmi,bit,false);
            onbm.Write( arcive );
          }

  */
  bool Create( const BITMAPINFO* bmi,
               const unsigned char* bits,
               bool bCopy
             );

#endif

  /*
  Returns:
    True if m_bmi and m_bits are in a single contiguous
    block of memory.
    False if m_bmi and m_bits are in two blocks of memory.
  */
  bool IsContiguous() const;

#if defined(ON_OS_WINDOWS_GDI)
  BITMAPINFO*                  m_bmi;
#else
  struct ON_WindowsBITMAPINFO* m_bmi;
#endif

  unsigned char*               m_bits;

private:
  int m_bFreeBMI; // 0 m_bmi and m_bits are not freed by ON_WindowsBitmap::Destroy
                  // 1 m_bmi  memory is freed by ON_WindowsBitmap::Destroy
                  // 2 m_bits memory is freed by ON_WindowsBitmap::Destroy
                  // 3 m_bmi and m_bits memory is freed by ON_WindowsBitmap::Destroy
};

/*
Description:
  ON_WindowsBitmapEx is identical to ON_WindowsBitmap except that
  it's Read/Write functions save bitmap names.
*/
class ON_CLASS ON_WindowsBitmapEx : public ON_WindowsBitmap
{
  ON_OBJECT_DECLARE(ON_WindowsBitmapEx);
public:
  ON_WindowsBitmapEx();
  ~ON_WindowsBitmapEx();
  BOOL Write( ON_BinaryArchive& ) const; // writes compressed image
  BOOL Read( ON_BinaryArchive& );        // reads compressed image
};

class ON_CLASS ON_EmbeddedBitmap : public ON_Bitmap
{
  ON_OBJECT_DECLARE(ON_EmbeddedBitmap);
public:
  ON_EmbeddedBitmap();
  ~ON_EmbeddedBitmap();
  void EmergencyDestroy();
  void Destroy();
  void Create( int sizeof_buffer );

  BOOL IsValid( ON_TextLog* text_log = NULL ) const;

  BOOL Write( ON_BinaryArchive& ) const;
  BOOL Read( ON_BinaryArchive& );

  int Width() const;
  int Height() const;
  int BitsPerPixel() const;
  int SizeofScan() const;
  int SizeofImage() const;
  unsigned char* Bits(int);
  const unsigned char* Bits(int) const;

  void* m_buffer;
  size_t m_sizeof_buffer;
  int m_free_buffer; // 1 = ~ON_EmbeddedBitmap will onfree m_buffer.
  ON__UINT32 m_biffer_crc32; // 32 bit crc from ON_CRC32
};

// class ON_CLASS ON_OpenGLBitmap ...
// OBSOLETE - See SourceSafe version 6 for old definition


#endif
