]> git.saurik.com Git - wxWidgets.git/commitdiff
Added saving support to TGA image handler.
authorDimitri Schoolwerth <dimitri.schoolwerth@gmail.com>
Tue, 28 Dec 2010 22:38:04 +0000 (22:38 +0000)
committerDimitri Schoolwerth <dimitri.schoolwerth@gmail.com>
Tue, 28 Dec 2010 22:38:04 +0000 (22:38 +0000)
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

docs/changes.txt
interface/wx/image.h
src/common/imagtga.cpp
tests/image/image.cpp

index b30d607c3b9e946226644cb54f92640fe5532520..41de14cffc5b7b860f3080ecae9a094516e49792 100644 (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:
 
index 703d247a1a85196dddac7cd6f528776d1ff75167..256a8617778022aa519293b7a35fb85f2c7b57cf 100644 (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.
index 62080d22c1f5490cb0d852ce9f6bf3e35f08ebcb..e3b5473995a80754ac2fded21dc3cb68835ba18d 100644 (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!"));
             }
index 2e72d8118cbe7a6a8f11c303e62042e9d6a5bb84..c39fa8650efcf3043dbd1757a83734824d4fe90c 100644 (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());