Added saving support to TGA image handler.
Supports saving 24-bit and 32-bit (RGB with alpha). Updated image unit test to verify the alpha channel of saved TGA images. Also removed a condition skipping a test which only was in place for TGA (formerly its saving handler would do nothing yet say saving was succesful). See also #7661. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66485 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -449,6 +449,7 @@ All (GUI):
|
|||||||
- Return bool, not void, from wxImage::ConvertAlphaToMask() (troelsk).
|
- Return bool, not void, from wxImage::ConvertAlphaToMask() (troelsk).
|
||||||
- Fixed resizing columns in wxGrid when they were reordered.
|
- Fixed resizing columns in wxGrid when they were reordered.
|
||||||
- Added wxImage::Rotate180() (Jeff Tupper).
|
- Added wxImage::Rotate180() (Jeff Tupper).
|
||||||
|
- Added support for saving TGA files.
|
||||||
|
|
||||||
GTK:
|
GTK:
|
||||||
|
|
||||||
|
@@ -318,9 +318,9 @@ const unsigned char wxIMAGE_ALPHA_OPAQUE = 0xff;
|
|||||||
channel with wxImage::HasAlpha. Currently the BMP, PNG, and TIFF format
|
channel with wxImage::HasAlpha. Currently the BMP, PNG, and TIFF format
|
||||||
handlers have full alpha channel support for loading so if you want to use
|
handlers have full alpha channel support for loading so if you want to use
|
||||||
alpha you have to use one of these formats. If you initialize the image
|
alpha you have to use one of these formats. If you initialize the image
|
||||||
alpha channel yourself using wxImage::SetAlpha, you should save it in PNG
|
alpha channel yourself using wxImage::SetAlpha, you should save it in
|
||||||
format to avoid losing it as this is the only handler that currently
|
either PNG or TGA format to avoid losing it as these are the only handlers
|
||||||
supports saving with alpha.
|
that currently support saving with alpha.
|
||||||
|
|
||||||
|
|
||||||
@section image_handlers Available image handlers
|
@section image_handlers Available image handlers
|
||||||
@@ -337,7 +337,7 @@ const unsigned char wxIMAGE_ALPHA_OPAQUE = 0xff;
|
|||||||
- wxPCXHandler: For loading and saving (see below).
|
- wxPCXHandler: For loading and saving (see below).
|
||||||
- wxPNMHandler: For loading and saving (see below).
|
- wxPNMHandler: For loading and saving (see below).
|
||||||
- wxTIFFHandler: For loading (including alpha support) and saving.
|
- wxTIFFHandler: For loading (including alpha support) and saving.
|
||||||
- wxTGAHandler: For loading only.
|
- wxTGAHandler: For loading and saving. Includes alpha support.
|
||||||
- wxIFFHandler: For loading only.
|
- wxIFFHandler: For loading only.
|
||||||
- wxXPMHandler: For loading and saving.
|
- wxXPMHandler: For loading and saving.
|
||||||
- wxICOHandler: For loading and saving.
|
- wxICOHandler: For loading and saving.
|
||||||
|
@@ -650,9 +650,70 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int SaveTGA(wxImage* WXUNUSED(image), wxOutputStream& WXUNUSED(stream))
|
int SaveTGA(const wxImage& image, wxOutputStream *stream)
|
||||||
{
|
{
|
||||||
wxLogError(wxT("Saving in TGA format is not implemented."));
|
bool hasAlpha = image.HasAlpha();
|
||||||
|
unsigned bytesPerPixel = 3 + (hasAlpha ? 1 : 0);
|
||||||
|
wxSize size = image.GetSize();
|
||||||
|
size_t scanlineSize = size.x * bytesPerPixel;
|
||||||
|
unsigned char *scanlineData = (unsigned char *) malloc(scanlineSize);
|
||||||
|
if (!scanlineData)
|
||||||
|
{
|
||||||
|
return wxTGA_MEMERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxON_BLOCK_EXIT1(free, scanlineData);
|
||||||
|
|
||||||
|
// Compose and write the TGA header
|
||||||
|
unsigned char hdr[HDR_SIZE];
|
||||||
|
(void) memset(&hdr, 0, HDR_SIZE);
|
||||||
|
|
||||||
|
hdr[HDR_COLORTYPE] = wxTGA_UNMAPPED;
|
||||||
|
hdr[HDR_IMAGETYPE] = 2 /* Uncompressed truecolour */;
|
||||||
|
|
||||||
|
hdr[HDR_WIDTH] = size.x & 0xFF;
|
||||||
|
hdr[HDR_WIDTH + 1] = (size.x >> 8) & 0xFF;
|
||||||
|
|
||||||
|
hdr[HDR_HEIGHT] = size.y & 0xFF;
|
||||||
|
hdr[HDR_HEIGHT + 1] = (size.y >> 8) & 0xFF;
|
||||||
|
|
||||||
|
hdr[HDR_BPP] = hasAlpha ? 32 : 24;
|
||||||
|
hdr[HDR_ORIENTATION] = 1 << 5; // set bit to indicate top-down order
|
||||||
|
if (hasAlpha)
|
||||||
|
{
|
||||||
|
hdr[HDR_ORIENTATION] |= 8; // number of alpha bits
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !stream->Write(hdr, HDR_SIZE) )
|
||||||
|
{
|
||||||
|
return wxTGA_IOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Write image data, converting RGB to BGR and adding alpha if applicable
|
||||||
|
|
||||||
|
unsigned char *src = image.GetData();
|
||||||
|
unsigned char *alpha = image.GetAlpha();
|
||||||
|
for (int y = 0; y < size.y; ++y)
|
||||||
|
{
|
||||||
|
unsigned char *dst = scanlineData;
|
||||||
|
for (int x = 0; x < size.x; ++x)
|
||||||
|
{
|
||||||
|
dst[0] = src[2];
|
||||||
|
dst[1] = src[1];
|
||||||
|
dst[2] = src[0];
|
||||||
|
if (alpha)
|
||||||
|
{
|
||||||
|
dst[3] = *(alpha++);
|
||||||
|
}
|
||||||
|
src += 3;
|
||||||
|
dst += bytesPerPixel;
|
||||||
|
}
|
||||||
|
if ( !stream->Write(scanlineData, scanlineSize) )
|
||||||
|
{
|
||||||
|
return wxTGA_IOERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return wxTGA_OK;
|
return wxTGA_OK;
|
||||||
}
|
}
|
||||||
@@ -712,7 +773,7 @@ bool wxTGAHandler::LoadFile(wxImage* image,
|
|||||||
|
|
||||||
bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose)
|
bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose)
|
||||||
{
|
{
|
||||||
int error = SaveTGA(image, stream);
|
int error = SaveTGA(*image, &stream);
|
||||||
|
|
||||||
if ( error != wxTGA_OK )
|
if ( error != wxTGA_OK )
|
||||||
{
|
{
|
||||||
@@ -720,14 +781,14 @@ bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose
|
|||||||
{
|
{
|
||||||
switch ( error )
|
switch ( error )
|
||||||
{
|
{
|
||||||
case wxTGA_INVFORMAT:
|
|
||||||
wxLogError(wxT("TGA: invalid image."));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wxTGA_MEMERR:
|
case wxTGA_MEMERR:
|
||||||
wxLogError(wxT("TGA: couldn't allocate memory."));
|
wxLogError(wxT("TGA: couldn't allocate memory."));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case wxTGA_IOERR:
|
||||||
|
wxLogError(wxT("TGA: couldn't write image data."));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wxLogError(wxT("TGA: unknown error!"));
|
wxLogError(wxT("TGA: unknown error!"));
|
||||||
}
|
}
|
||||||
|
@@ -874,13 +874,14 @@ static
|
|||||||
void CompareImage(const wxImageHandler& handler, const wxImage& expected)
|
void CompareImage(const wxImageHandler& handler, const wxImage& expected)
|
||||||
{
|
{
|
||||||
bool testAlpha = expected.HasAlpha();
|
bool testAlpha = expected.HasAlpha();
|
||||||
if (testAlpha && type != wxBITMAP_TYPE_PNG)
|
wxBitmapType type = handler.GetType();
|
||||||
|
if (testAlpha
|
||||||
|
&& !(type == wxBITMAP_TYPE_PNG || type == wxBITMAP_TYPE_TGA) )
|
||||||
{
|
{
|
||||||
// don't test images with alpha if this handler doesn't support alpha
|
// don't test images with alpha if this handler doesn't support alpha
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxBitmapType type = handler.GetType();
|
|
||||||
if (type == wxBITMAP_TYPE_JPEG /* skip lossy JPEG */
|
if (type == wxBITMAP_TYPE_JPEG /* skip lossy JPEG */
|
||||||
|| type == wxBITMAP_TYPE_TIF)
|
|| type == wxBITMAP_TYPE_TIF)
|
||||||
{
|
{
|
||||||
@@ -901,14 +902,6 @@ void CompareImage(const wxImageHandler& handler, const wxImage& expected)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !memOut.GetSize() )
|
|
||||||
{
|
|
||||||
// A handler that does not support saving can return true during
|
|
||||||
// SaveFile, in that case the stream is empty.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
wxMemoryInputStream memIn(memOut);
|
wxMemoryInputStream memIn(memOut);
|
||||||
CPPUNIT_ASSERT(memIn.IsOk());
|
CPPUNIT_ASSERT(memIn.IsOk());
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user