Some users reported that they can't properly save a bitmap as TGA with bmap_save, because the bitmap gets mirrored. This is due the fact that TGA stores a handedness flag that defines if the image origin is in the upper- or lower left corner. --- I found out, that if you set the flag in the TGA, that indicates the origin in the lower left corner, and you write the image upside down into the file, the bitmap is saved correctly and is loaded correctly back into the engine.

So I have written the following function "bmap_savetga" a while ago (inspired by ventilator's C-Script in the wiki) in Lite-C for another project to circumvent the upside-down problem; it also saves the alpha channel in the TGA, if and only if the passed BMAP* has an alpha channel, too; otherwise the TGA just saves RGB data.

Here is the function:

Code:
// Saves a bitmap as tga file
BOOL bmap_savetga (BMAP* b, char* filename)
{
    BOOL bSuccess = false;

    if (b && filename && strlen(filename) > 0)
    {
        var fh = file_open_write(filename);
        if (fh)
        {
            int height = b->height;
            int width = b->width;

            var format = bmap_lock(b, 0);

            // if the bitmap has an alpha channel
            BOOL bAlpha = (((format == 8888) || (format == 1555) || (format == 4444)) && (b->bytespp == 4));

            // header

            int i;
            for (i = 0; i < 2; i++)
                file_asc_write(fh, 0);

            file_asc_write(fh, 2); // uncompressed

            for (i = 0; i < 7; i++)
                file_asc_write(fh, 0);

            // y origin (lower left corner)
            file_asc_write(fh, height & 255);
            file_asc_write(fh, (height >> 8) & 255);

            file_asc_write(fh, width & 255);
            file_asc_write(fh, (width >> 8) & 255);

            file_asc_write(fh, height & 255);
            file_asc_write(fh, (height >> 8) & 255);
            
            int bypp = 24;
            if (bAlpha)
                bypp = 32;

            file_asc_write(fh, bypp); // bypp
            file_asc_write(fh, 0);

            // pixels

            COLOR bgr;
            var alpha;

            int ix, iy;
            for (iy = 0; iy < height; iy++)
            {
                for (ix = 0; ix < width; ix++)
                {
                    // retrieve BGR color and alpha
                    pixel_to_vec(&bgr, &alpha, format, pixel_for_bmap(b, ix, height - 1 - iy));

                    file_asc_write(fh, bgr.blue); // b
                    file_asc_write(fh, bgr.green); // g
                    file_asc_write(fh, bgr.red); // r

                    if (bAlpha)
                        file_asc_write(fh, alpha * 2.55); // a
                }
            }

            // done!
            bmap_unlock(b);
            file_close(fh);

            bSuccess = true;
        }
    }

    return(bSuccess);
}



Here is an example, that creates an RGBA image with a horizontal color gradient and a vertical alpha gradient, saves it and loads it again:

Code:
#include <acknex.h>
#include <default.c>

int main ()
{
    wait(3);
    
    int format = 8888;
    BMAP* b = bmap_createblack(100, 200, format);
    
    bmap_lock(b, 0);
    
    // create red to green gradient from left to right
    // and alpha gradient from translucent to solid from up to bottom
    
    int ix, iy;
    for (ix = 0; ix < b->width; ix++)
    {
        for (iy = 0; iy < b->height; iy++)
        {
            double fx = (double)ix / (double)(b->width-1);
            double fy = (double)iy / (double)(b->height-1);
            
            VECTOR color;
            vec_lerp(&color, COLOR_RED, COLOR_GREEN, fx);
            
            var pixel = pixel_for_vec(&color, 100 * fy, format);
            
            pixel_to_bmap(b, ix, iy, pixel);
        }
    }
    
    bmap_unlock(b);
    
    // save to file
    bmap_savetga(b, "b.tga");
    
    // load from file to compare
    BMAP* bf = bmap_create("b.tga");
    
    video_set(32+b->width+16+bf->width+32, 32+maxv(b->height, bf->height)+32, 0, 2);
    
    while (1)
    {
        draw_text("engine", 32, 32, COLOR_WHITE);
        draw_quad(b, vector(32, 48, 0), NULL, NULL, NULL, NULL, 100, 0);
        
        draw_text("file", 32 + b->width + 16, 32, COLOR_WHITE);
        draw_quad(bf, vector(32 + b->width + 16, 48, 0), NULL, NULL, NULL, NULL, 100, 0);
        
        wait(1);
    }
}



Screenshot:


I hope you find this useful.

Regards,
-Christian