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).
|
||||
- Fixed resizing columns in wxGrid when they were reordered.
|
||||
- Added wxImage::Rotate180() (Jeff Tupper).
|
||||
- Added support for saving TGA files.
|
||||
|
||||
GTK:
|
||||
|
||||
|
@@ -318,9 +318,9 @@ const unsigned char wxIMAGE_ALPHA_OPAQUE = 0xff;
|
||||
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
|
||||
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
|
||||
format to avoid losing it as this is the only handler that currently
|
||||
supports saving with alpha.
|
||||
alpha channel yourself using wxImage::SetAlpha, you should save it in
|
||||
either PNG or TGA format to avoid losing it as these are the only handlers
|
||||
that currently support saving with alpha.
|
||||
|
||||
|
||||
@section image_handlers Available image handlers
|
||||
@@ -337,7 +337,7 @@ const unsigned char wxIMAGE_ALPHA_OPAQUE = 0xff;
|
||||
- wxPCXHandler: For loading and saving (see below).
|
||||
- wxPNMHandler: For loading and saving (see below).
|
||||
- wxTIFFHandler: For loading (including alpha support) and saving.
|
||||
- wxTGAHandler: For loading only.
|
||||
- wxTGAHandler: For loading and saving. Includes alpha support.
|
||||
- wxIFFHandler: For loading only.
|
||||
- wxXPMHandler: For loading and saving.
|
||||
- wxICOHandler: For loading and saving.
|
||||
|
@@ -650,9 +650,70 @@ int ReadTGA(wxImage* image, wxInputStream& stream)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -712,7 +773,7 @@ bool wxTGAHandler::LoadFile(wxImage* image,
|
||||
|
||||
bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose)
|
||||
{
|
||||
int error = SaveTGA(image, stream);
|
||||
int error = SaveTGA(*image, &stream);
|
||||
|
||||
if ( error != wxTGA_OK )
|
||||
{
|
||||
@@ -720,14 +781,14 @@ bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose
|
||||
{
|
||||
switch ( error )
|
||||
{
|
||||
case wxTGA_INVFORMAT:
|
||||
wxLogError(wxT("TGA: invalid image."));
|
||||
break;
|
||||
|
||||
case wxTGA_MEMERR:
|
||||
wxLogError(wxT("TGA: couldn't allocate memory."));
|
||||
break;
|
||||
|
||||
case wxTGA_IOERR:
|
||||
wxLogError(wxT("TGA: couldn't write image data."));
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogError(wxT("TGA: unknown error!"));
|
||||
}
|
||||
|
@@ -874,13 +874,14 @@ static
|
||||
void CompareImage(const wxImageHandler& handler, const wxImage& expected)
|
||||
{
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
wxBitmapType type = handler.GetType();
|
||||
if (type == wxBITMAP_TYPE_JPEG /* skip lossy JPEG */
|
||||
|| type == wxBITMAP_TYPE_TIF)
|
||||
{
|
||||
@@ -901,14 +902,6 @@ void CompareImage(const wxImageHandler& handler, const wxImage& expected)
|
||||
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);
|
||||
CPPUNIT_ASSERT(memIn.IsOk());
|
||||
|
||||
|
Reference in New Issue
Block a user