#endif
//-----------------------------------------------------------------------------
-// wxBMPHandler
+// wxBMPHandler & wxICOHandler
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
#if wxUSE_STREAMS
+#ifndef BI_RGB
+#define BI_RGB 0
+#define BI_RLE8 1
+#define BI_RLE4 2
+#endif
+
+#ifndef BI_BITFIELDS
+#define BI_BITFIELDS 3
+#endif
+
+#define poffset (line * width * 3 + column * 3)
+
+
+
+struct ICONDIRENTRY
+ {
+ wxUint8 bWidth; // Width of the image
+ wxUint8 bHeight; // Height of the image (times 2)
+ wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp)
+ wxUint8 bReserved; // Reserved
+ wxUint16 wPlanes; // Color Planes
+ wxUint16 wBitCount; // Bits per pixel
+ wxUint32 dwBytesInRes; // how many bytes in this resource?
+ wxUint32 dwImageOffset; // where in the file is this image
+} ;
+
+
+struct ICONDIR
+{
+ wxUint16 idReserved; // Reserved
+ wxUint16 idType; // resource type (1 for icons)
+ wxUint16 idCount; // how many images?
+} ;
+
+bool wxICOHandler::SaveFile(wxImage *image,
+ wxOutputStream& stream,
+ bool verbose)
+
+{
+ bool bResult = FALSE ;
+ //sanity check; icon must be less than 127 pixels high and 255 wide
+ if (image -> GetHeight () > 127 )
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error Image too tall for an icon.") );
+ return FALSE;
+ }
+ if (image -> GetWidth () > 255 )
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error Image too wide for an icon.") );
+ return FALSE;
+ }
+
+ // only generate one image
+ int m_images = 1 ;
+
+ // write a header, (ICONDIR)
+ // Calculate the header size
+ wxUint32 m_offset = 3 * sizeof(wxUint16);
+
+ ICONDIR m_IconDir ;
+ m_IconDir.idReserved = 0 ;
+ m_IconDir.idType = wxUINT16_SWAP_ON_BE (1);
+ m_IconDir.idCount = wxUINT16_SWAP_ON_BE (m_images);
+ stream.Write(&m_IconDir.idReserved, sizeof(m_IconDir.idReserved));
+ stream.Write(&m_IconDir.idType, sizeof(m_IconDir.idType));
+ stream.Write(&m_IconDir.idCount, sizeof(m_IconDir.idCount));
+ if ( !stream.IsOk () )
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error writing ICONDIR header.") );
+ return FALSE;
+ }
+
+ // for each iamage write a description ICONDIRENTRY
+ ICONDIRENTRY m_icondirentry ;
+ int i ;
+ for ( i = 0; i < m_images; i++ )
+ {
+ wxImage mask ;
+ if (image->HasMask())
+ {
+ //make another image with black/white
+ mask = image -> ConvertToMono (image->GetMaskRed(), image->GetMaskGreen(), image->GetMaskBlue() );
+ //now we need to change the masked regions to black
+ unsigned char r = image -> GetMaskRed() ;
+ unsigned char g = image -> GetMaskGreen() ;
+ unsigned char b = image -> GetMaskBlue() ;
+ if ((r != 0) || (g != 0) || (b != 0) )
+ {
+ //Go round and apply black to the masked bits
+ int i,j;
+ for (i=0; i < mask.GetWidth(); i++)
+ for (j=0; j < mask.GetHeight(); j++)
+ {
+ if ((r == mask.GetRed(i, j)) &&
+ (g == mask.GetGreen(i, j) ) &&
+ (b == mask.GetBlue(i, j)) )
+ image -> SetRGB ( i, j, 0, 0, 0 );
+ }
+
+ }
+ }
+ else
+ {
+ // just make a black mask all over
+ mask = image -> Copy ();
+ int i,j;
+ for (i=0; i < mask.GetWidth(); i++)
+ for (j=0; j < mask.GetHeight(); j++)
+ mask.SetRGB ( i, j, 0, 0, 0 );
+ }
+ //Set the formats for image and mask
+ // windows never saves with more than 8 colors
+ image -> SetOption (wxBMP_FORMAT, wxBMP_8BPP);
+ // monochome bitmap
+ mask . SetOption (wxBMP_FORMAT, wxBMP_1BPP_BW);
+ bool IsBmp = FALSE ;
+ bool IsMask = FALSE ;
+
+ //calculate size and offset of image and mask
+ wxCountingOutputStream cStream ;
+ bResult = SaveDib ( image, cStream, verbose, IsBmp, IsMask ) ;
+ if (!bResult)
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error calculating size of XOR DIB .") );
+ return FALSE;
+ }
+ IsMask = TRUE ;
+ bResult = SaveDib ( &mask, cStream, verbose, IsBmp, IsMask ) ;
+ if (!bResult)
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error calculating size of Mask DIB .") );
+ return FALSE;
+ }
+ wxUint32 m_Size = cStream.GetSize();
+
+ // wxCountingOutputStream::Ok() always returns TRUE for now and this
+ // "if" provokes VC++ warnings in optimized build
+#if 0
+ if (!cStream.Ok())
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error calculating size of DIB .") );
+ return FALSE;
+ }
+#endif // 0
+
+ m_offset = m_offset + sizeof(ICONDIRENTRY) ;
+
+ m_icondirentry. bWidth = image -> GetWidth () ;
+ m_icondirentry. bHeight = 2 * image -> GetHeight () ;
+ m_icondirentry. bColorCount = 0 ;
+ m_icondirentry. bReserved = 0 ;
+ m_icondirentry. wPlanes = wxUINT16_SWAP_ON_BE(1);
+ m_icondirentry. wBitCount = wxUINT16_SWAP_ON_BE(wxBMP_8BPP) ;
+ m_icondirentry. dwBytesInRes = wxUINT32_SWAP_ON_BE(m_Size);
+ m_icondirentry. dwImageOffset = wxUINT32_SWAP_ON_BE(m_offset);
+
+ //increase size to allow for the data wriitten
+ m_offset = m_offset + m_Size ;
+
+ //write to stream
+ stream.Write(&m_icondirentry. bWidth, sizeof(m_icondirentry. bWidth) );
+ stream.Write(&m_icondirentry. bHeight, sizeof(m_icondirentry. bHeight) );
+ stream.Write(&m_icondirentry. bColorCount, sizeof(m_icondirentry. bColorCount) );
+ stream.Write(&m_icondirentry. bReserved, sizeof(m_icondirentry. bReserved) );
+ stream.Write(&m_icondirentry. wPlanes, sizeof(m_icondirentry. wPlanes) );
+ stream.Write(&m_icondirentry. wBitCount, sizeof(m_icondirentry. wBitCount) );
+ stream.Write(&m_icondirentry. dwBytesInRes, sizeof(m_icondirentry. dwBytesInRes) );
+ stream.Write(&m_icondirentry. dwImageOffset, sizeof(m_icondirentry. dwImageOffset) );
+ if ( !stream.IsOk () )
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error writing ICONDIRENTRY header.") );
+ return FALSE;
+ }
+ //actually save it
+ IsMask = FALSE ;
+ bResult = SaveDib ( image, stream, verbose, IsBmp, IsMask ) ;
+ if (!bResult)
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error writing XOR DIB .") );
+ return FALSE;
+ }
+ IsMask = TRUE ;
+ bResult = SaveDib ( &mask, stream, verbose, IsBmp, IsMask ) ;
+ if (!bResult)
+ {
+ if (verbose)
+ wxLogError( _("ICO: Error writing Mask DIB .") );
+ return FALSE;
+ }
+
+ } // end of for loop
+ return TRUE ;
+}
+
+
bool wxBMPHandler::SaveFile(wxImage *image,
wxOutputStream& stream,
bool verbose)
+{
+ bool IsBmp = TRUE;
+ bool IsMask = FALSE ;
+ return SaveDib( image, stream, verbose, IsBmp, IsMask ) ;
+}
+
+bool wxBMPHandler::SaveDib(wxImage *image,
+ wxOutputStream& stream,
+ bool verbose,
+ bool IsBmp,
+ bool IsMask)
+
{
wxCHECK_MSG( image, FALSE, _T("invalid pointer in wxBMPHandler::SaveFile") );
hdr.bih_size = wxUINT32_SWAP_ON_BE(hdr_size - 14);
hdr.width = wxUINT32_SWAP_ON_BE(image->GetWidth());
+ if (IsBmp)
+ {
hdr.height = wxUINT32_SWAP_ON_BE(image->GetHeight());
+ }
+ else
+ {
+ hdr.height = wxUINT32_SWAP_ON_BE(2 * image->GetHeight());
+ }
hdr.planes = wxUINT16_SWAP_ON_BE(1); // always 1 plane
hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
hdr.compression = 0; // RGB uncompressed
hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap
hdr.num_signif_clrs = 0; // all colors are significant
+ if (IsBmp)
+ {
if (// VS: looks ugly but compilers tend to do ugly things with structs,
// like aligning hdr.filesize's ofset to dword :(
// VZ: we should add padding then...
!stream.Write(&hdr.magic, 2) ||
!stream.Write(&hdr.filesize, 4) ||
!stream.Write(&hdr.reserved, 4) ||
- !stream.Write(&hdr.data_offset, 4) ||
+ !stream.Write(&hdr.data_offset, 4)
+ )
+ {
+ if (verbose)
+ wxLogError(_("BMP: Couldn't write the file (Bitmap) header."));
+ return FALSE;
+ }
+ }
+ if (!IsMask)
+ {
+ if (
!stream.Write(&hdr.bih_size, 4) ||
!stream.Write(&hdr.width, 4) ||
!stream.Write(&hdr.height, 4) ||
)
{
if (verbose)
- wxLogError(_("BMP: Couldn't write the file header."));
+ wxLogError(_("BMP: Couldn't write the file (BitmapInfo) header."));
return FALSE;
}
+ }
wxPalette *palette = NULL; // entries for quantized images
wxUint8 *rgbquad = NULL; // for the RGBQUAD bytes for the colormap
// if the colormap was made, then it needs to be written
if (rgbquad)
{
+ if (!IsMask)
+ {
if (!stream.Write(rgbquad, palette_size*4))
{
if (verbose)
delete q_image;
return FALSE;
}
+ }
delete []rgbquad;
}
-#ifndef BI_RGB
-#define BI_RGB 0
-#define BI_RLE8 1
-#define BI_RLE4 2
-#endif
-
-#ifndef BI_BITFIELDS
-#define BI_BITFIELDS 3
-#endif
-
-#define poffset (line * width * 3 + column * 3)
-
-
-
-struct ICONDIRENTRY
- {
- wxUint8 bWidth; // Width of the image
- wxUint8 bHeight; // Height of the image (times 2)
- wxUint8 bColorCount; // Number of colors in image (0 if >=8bpp)
- wxUint8 bReserved; // Reserved
- wxUint16 wPlanes; // Color Planes
- wxUint16 wBitCount; // Bits per pixel
- wxUint32 dwBytesInRes; // how many bytes in this resource?
- wxUint32 dwImageOffset; // where in the file is this image
-} ;
-
-
-struct ICONDIR
-{
- wxUint16 idReserved; // Reserved
- wxUint16 idType; // resource type (1 for icons)
- wxUint16 idCount; // how many images?
-} ;
-
bool wxBMPHandler::DoLoadDib (wxImage * image, int width, int height, int bpp, int ncolors, int comp,
off_t bmpOffset, wxInputStream& stream,
bool wxBMPHandler::LoadDib( wxImage *image, wxInputStream& stream, bool verbose, bool IsBmp )
{
-
- wxUint8 aByte;
wxUint16 aWord;
wxInt32 dbuf[4];
wxInt8 bbuf[4];
{
//read Icon mask which is monochrome
//there is no palette, so we will create one
- wxImage mask ;
+ wxImage mask;
if (!DoLoadDib (&mask, width, height, 1, 2, BI_RGB, offset, stream,
verbose, IsBmp, FALSE ) )
{
wxLogError( _("ICO: Error in reading mask DIB.") );
return FALSE;
}
- image -> ApplyMask ( &mask );
+ image->SetMaskFromImage(mask, 255, 255, 255);
}
return TRUE;
bResult = LoadDib ( image, stream, TRUE, IsBmp );
}
delete [] pIconDirEntry ;
- return bResult
- ;
+ return bResult ;
}
-bool wxICOHandler::SaveFile(wxImage *image,
- wxOutputStream& stream,
- bool verbose)
-{
- return FALSE ;
-}
bool wxBMPHandler::DoCanRead( wxInputStream& stream )
{