second halt of Chris' wxImage ICO patch
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12733 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
4f41713093
commit
37b83ca639
@ -81,6 +81,7 @@ All (GUI):
|
||||
- wxDirSelector() added (Paul A. Thiessen)
|
||||
- wxGrid cell editing veto support (Roger Gammans)
|
||||
- wxListCtrl ITEM_FOCUSED event added
|
||||
- support for ICO files in wxImage added (Chris Elliott)
|
||||
|
||||
wxMSW:
|
||||
|
||||
|
@ -32,6 +32,7 @@ handler with \helpref{wxImage::AddHandler}{wximageaddhandler} or
|
||||
\twocolitem{\indexit{wxPNMHandler}}{For loading and saving (see below).}
|
||||
\twocolitem{\indexit{wxTIFFHandler}}{For loading and saving.}
|
||||
\twocolitem{\indexit{wxXPMHandler}}{For loading and saving.}
|
||||
\twocolitem{\indexit{wxICOHandler}}{For loading and saving.}
|
||||
\end{twocollist}
|
||||
|
||||
When saving in PCX format, {\bf wxPCXHandler} will count the number of
|
||||
@ -118,6 +119,7 @@ Loads an image from an input stream.
|
||||
\twocolitem{\indexit{wxBITMAP\_TYPE\_PNM}}{Load a PNM bitmap file.}
|
||||
\twocolitem{\indexit{wxBITMAP\_TYPE\_TIF}}{Load a TIFF bitmap file.}
|
||||
\twocolitem{\indexit{wxBITMAP\_TYPE\_XPM}}{Load a XPM bitmap file.}
|
||||
\twocolitem{\indexit{wxBITMAP\_TYPE\_ICO}}{Load a ICO Icon file.}
|
||||
\twocolitem{\indexit{wxBITMAP\_TYPE\_ANY}}{Will try to autodetect the format.}
|
||||
\end{twocollist}}
|
||||
|
||||
@ -229,6 +231,30 @@ TRUE if the call succeeded, FALSE otherwise.
|
||||
|
||||
Destroys the image data.
|
||||
|
||||
\membersection{wxImage::FindFirstUnusedColour}\label{wximagefindfirstunusedcolour}
|
||||
|
||||
\func{bool}{FindFirstUnusedColour}{\param{unsigned char *}{ r}, \param{unsigned char *}{ g}, \param{unsigned char *}{ b}, \param{unsigned char}{ startR = 1}, \param{unsigned char}{ startG = 0}, \param{unsigned char}{ startB = 0}}
|
||||
|
||||
\wxheading{Parameters}
|
||||
|
||||
\docparam{r,g,b}{Pointers to variables to save the colour.}
|
||||
|
||||
\docparam{startR,startG,startB}{Initial values of the colour. Returned colour
|
||||
will have RGB values equal to or greater than these.}
|
||||
|
||||
Finds the first colour that is never used in the image. The search begins at
|
||||
given initial colour and continues by increasing R, G and B components (in this
|
||||
order) by 1 until an unused colour is found or the colour space exhausted.
|
||||
|
||||
\wxheading{Return value}
|
||||
|
||||
Returns FALSE if there is no unused colour left, TRUE on success.
|
||||
|
||||
\wxheading{Notes}
|
||||
|
||||
Note that this method involves computing the histogram, which is
|
||||
computationally intensive operation.
|
||||
|
||||
\membersection{wxImage::FindHandler}
|
||||
|
||||
\func{static wxImageHandler*}{FindHandler}{\param{const wxString\& }{name}}
|
||||
@ -455,6 +481,7 @@ Loads an image from an input stream.
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_PNM}}{Load a PNM image file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_TIF}}{Load a TIFF image file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_XPM}}{Load a XPM image file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_ICO}}{Load a ICO icon file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_ANY}}{Will try to autodetect the format.}
|
||||
\end{twocollist}}
|
||||
|
||||
@ -464,6 +491,8 @@ Loads an image from an input stream.
|
||||
|
||||
Depending on how wxWindows has been configured, not all formats may be available.
|
||||
|
||||
wxBITMAP\_TYPE\_ICO will laod the largest image found, with the most colours
|
||||
|
||||
\wxheading{Return value}
|
||||
|
||||
TRUE if the operation succeeded, FALSE otherwise.
|
||||
@ -543,6 +572,7 @@ Saves a image in the given stream.
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_PNM}}{Save a PNM image file (as raw RGB always).}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_TIFF}}{Save a TIFF image file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_XPM}}{Save a XPM image file.}
|
||||
\twocolitem{{\bf wxBITMAP\_TYPE\_ICO}}{Save a ICO image file. (The size may be up to 255 wide by 127 high. A single image is saved in 8 colors at the size supplied.)}
|
||||
\end{twocollist}}
|
||||
|
||||
\docparam{mimetype}{MIME type.}
|
||||
@ -676,6 +706,33 @@ Specifies whether there is a mask or not. The area of the mask is determined by
|
||||
|
||||
Sets the mask colour for this image (and tells the image to use the mask).
|
||||
|
||||
\membersection{wxImage::SetMaskFromImage}\label{wximagesetmaskfromimage}
|
||||
|
||||
\func{bool}{SetMaskFromImage}{\param{const wxImage\&}{ mask}, \param{unsigned char}{ mr}, \param{unsigned char}{ mg}, \param{unsigned char}{ mb}}
|
||||
|
||||
\wxheading{Parameters}
|
||||
|
||||
\docparam{mask}{The mask image to extract mask shape from. Must have same dimensions as the image.}
|
||||
|
||||
\docparam{mr,mg,mb}{RGB value of pixels in {\it mask} that will be used to create the mask.}
|
||||
|
||||
Sets image's mask so that the pixels that have RGB value of {\it mr,mg,mb}
|
||||
in {\it mask} will be masked in the image. This is done by first finding an
|
||||
unused colour in the image, setting this colour as the mask colour and then
|
||||
using this colour to draw all pixels in the image who corresponding pixel
|
||||
in {\it mask} has given RGB value.
|
||||
|
||||
\wxheading{Return value}
|
||||
|
||||
Returns FALSE if {\it mask} does not have same dimensions as the image or if
|
||||
there is no unused colour left. Returns TRUE if the mask was successfully
|
||||
applied.
|
||||
|
||||
\wxheading{Notes}
|
||||
|
||||
Note that this method involves computing the histogram, which is
|
||||
computationally intensive operation.
|
||||
|
||||
\membersection{wxImage::SetOption}\label{wximagesetoption}
|
||||
|
||||
\func{void}{SetOption}{\param{const wxString\&}{ name}, \param{const wxString\&}{ value}}
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
virtual bool DoCanRead( wxInputStream& stream );
|
||||
|
||||
protected:
|
||||
bool SaveDib(wxImage *image, wxOutputStream& stream, bool verbose, bool IsBmp, bool IsMask);
|
||||
bool DoLoadDib (wxImage * image, int width, int height, int bpp, int ncolors, int comp,
|
||||
off_t bmpOffset, wxInputStream& stream,
|
||||
bool verbose, bool IsBmp, bool hasPalette ) ;
|
||||
|
@ -47,7 +47,7 @@
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxBMPHandler
|
||||
// wxBMPHandler & wxICOHandler
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
|
||||
@ -56,9 +56,219 @@ 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();
|
||||
if (!cStream.Ok())
|
||||
{
|
||||
if (verbose)
|
||||
wxLogError( _("ICO: Error calculating size of DIB .") );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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") );
|
||||
|
||||
@ -145,7 +355,14 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
|
||||
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
|
||||
@ -154,13 +371,25 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
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) ||
|
||||
@ -175,9 +404,10 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
)
|
||||
{
|
||||
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
|
||||
@ -243,6 +473,8 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
// if the colormap was made, then it needs to be written
|
||||
if (rgbquad)
|
||||
{
|
||||
if (!IsMask)
|
||||
{
|
||||
if (!stream.Write(rgbquad, palette_size*4))
|
||||
{
|
||||
if (verbose)
|
||||
@ -254,6 +486,7 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
delete q_image;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
delete []rgbquad;
|
||||
}
|
||||
|
||||
@ -397,40 +630,6 @@ bool wxBMPHandler::SaveFile(wxImage *image,
|
||||
|
||||
|
||||
|
||||
#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,
|
||||
@ -911,16 +1110,9 @@ bool wxICOHandler::LoadFile ( wxImage *image, wxInputStream& stream, bool verbos
|
||||
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 )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user