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:
Dimitri Schoolwerth
2010-12-28 22:38:04 +00:00
parent 5828d76add
commit 3d926ff8a9
4 changed files with 76 additions and 21 deletions

View File

@@ -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:

View File

@@ -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.

View File

@@ -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!"));
}

View File

@@ -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());