Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DRESsedAlarm184/LWXGL/llms.txt

Use this file to discover all available pages before exploring further.

LWXGL can load indexed-color TGA files and 1-bit XBM files and render them into image elements using the same palette-indexed pixel buffer system as the raster drawing API. Images are stored in a named registry — you allocate a TGA once and can draw it into any image element by name. This guide covers loading from disk, loading from memory, XBM support, palette control, transparency, and capturing back-buffer regions.

TGA Format Requirements

LWXGL’s TGA loader has strict requirements. Files that do not meet these criteria will be rejected with error code 2.
FieldRequired value
Color map type1 (palette present)
Image type1 (uncompressed indexed) or 9 (RLE indexed)
Colormap origin0 (both bytes h[3] and h[4] must be 0)
Palette entry count16 (encoded as h[5]=16, h[6]=0)
Palette entry depth24-bit RGB (h[7]=24)
Image bit depth8 bits per pixel (h[16]=8)
OriginTop-left (h[17]=0x20) or bottom-left (h[17]=0x00)
A 16-entry, 8-bit indexed TGA can be created by most graphics editors (GIMP, Aseprite, etc.) by exporting as “Indexed TGA” with a 16-color palette.

Allocating and Drawing TGA Files

AllocateTGA

int AllocateTGA(const char* name, const char* path,
                int change_palette, int transparent);
Loads a TGA file from disk and stores it in the internal registry under name. The name is an arbitrary string key used to reference the image later. Return values:
  • 0 — success
  • 1 — file not found
  • 2 — invalid TGA format
Parameters:
  • name — registry key string
  • path — filesystem path to the .tga file
  • change_palette — if non-zero, LWXGL replaces its active 16-color palette with the TGA’s own palette each time the image is drawn (see Palette Replacement below)
  • transparent — palette index to treat as transparent (pixels with this index are skipped during drawing); pass -1 for no transparency
int status = AllocateTGA("player_sprite", "assets/player.tga", 0, -1);
if (status == 1) { /* file not found */ }
if (status == 2) { /* wrong format */ }

DrawIndexedTGA

void DrawIndexedTGA(int id, int x, int y, const char* name);
Draws the named TGA into the image element id at offset (x, y) within the element. Pixels are clipped to the element bounds. If change_palette was set when allocating, the palette is updated before drawing.
// Draw "player_sprite" at offset (0, 0) inside element 5
DrawIndexedTGA(5, 0, 0, "player_sprite");
UpdateImage(5);

CreateTGAImage (convenience)

int CreateTGAImage(int id, int x, int y, const char* path, int change_palette);
A single-call convenience wrapper that:
  1. Allocates the TGA (if not already loaded) under the internal key "TGAImage_" + path
  2. Creates an image element sized to the TGA dimensions
  3. Draws the TGA at offset (0, 0)
  4. Calls UpdateImage
No transparent parameter — use AllocateTGA + DrawIndexedTGA when you need transparency.
// Load, create element, draw, flush — all in one call
if (CreateTGAImage(10, 50, 50, "assets/logo.tga", 0) != 0) {
    // handle error
}

DeleteTGA

void DeleteTGA(const char* name);
Frees the palette and pixel buffers for the named TGA and removes it from the registry. Does nothing if the name is not found.
DeleteTGA("player_sprite");

Palette Replacement

When change_palette is non-zero, DrawIndexedTGA replaces LWXGL’s 16-color palette with the TGA file’s own palette at draw time. This means the TGA is rendered in its original colors rather than the current application palette.
// Draw a TGA in its own colors; all other elements using
// the palette will also reflect the new colors after this call.
AllocateTGA("background", "assets/bg.tga", 1, -1);
DrawIndexedTGA(3, 0, 0, "background");
UpdateImage(3);
Palette replacement is global. After DrawIndexedTGA with change_palette = 1, all other image elements and UI widgets will use the new palette colors until you call PaletteReset(). Plan your draw order accordingly, or load TGAs with change_palette = 0 when you need consistent UI colors.

Palette functions

// Query a palette entry
void PaletteQuery(int idx, unsigned char* r, unsigned char* g, unsigned char* b);

// Modify a palette entry; pass redraw=1 to refresh all image elements
void PaletteModify(int idx, unsigned char r, unsigned char g, unsigned char b, int redraw);

// Reset all 16 palette entries to LWXGL defaults and redraw images
void PaletteReset();

Transparency

The transparent parameter in AllocateTGA specifies a palette index that is treated as transparent — those pixels are skipped during DrawIndexedTGA. Pass -1 to disable transparency.
// Palette index 0 (black) is the transparent color in this sprite
AllocateTGA("icon", "assets/icon.tga", 0, 0);

// Palette index 15 (white) treated as transparent
AllocateTGA("mask", "assets/mask.tga", 0, 15);

Loading TGA from Memory

int AllocateMemoryTGA(const char* name, const char* buffer, int size,
                      int change_palette, int transparent);
Loads a TGA from an in-memory byte buffer using memfd_create to expose it as a temporary file descriptor, then calls AllocateTGA internally. This is useful for TGA data embedded in your binary (e.g. via xxd -i) or downloaded at runtime.
// Assume tga_data[] and tga_data_len are generated by xxd -i
extern unsigned char tga_data[];
extern unsigned int  tga_data_len;

int status = AllocateMemoryTGA("embedded_sprite",
                                (const char*)tga_data, tga_data_len,
                                0, -1);
Known parameter-swap bug: inside AllocateMemoryTGA the change_palette and transparent arguments are passed to AllocateTGA in swapped ordertransparent is forwarded as change_palette and change_palette is forwarded as transparent. As a workaround, swap your intended values at the call site: pass your desired transparent value as the change_palette argument and vice versa.
// Workaround: swap the last two args at the call site
// Desired: change_palette=0, transparent=-1
// Pass:    change_palette=-1, transparent=0  (swapped)
AllocateMemoryTGA("sprite", buf, len, -1, 0);
AllocateMemoryTGA uses the Linux-specific memfd_create syscall, so this function is only available on Linux kernel 3.17+.

XBM Support

XBM is a 1-bit bitmap format where each pixel is either 0 or 1. LWXGL maps the two bit values to two palette indices, allowing you to use XBMs as monochrome sprites or icons.

AllocateXBM

int AllocateXBM(const char* name, const char* path, int colors, int transparent);
  • name — registry key
  • path — path to the .xbm file
  • colors — packed palette indices: high nibble = color for bit-1 pixels, low nibble = color for bit-0 pixels
  • transparent1 to make bit-1 pixels transparent, 0 to make bit-0 pixels transparent, or any other value for no transparency
Returns 1 on success, 0 on failure.
// bit-1 → CLR_WHITE (0xF), bit-0 → CLR_BLACK (0x0)
// No transparency
int colors = (CLR_WHITE << 4) | CLR_BLACK;  // 0xF0
AllocateXBM("cursor_icon", "assets/cursor.xbm", colors, -1);

DrawIndexedTGA(7, 0, 0, "cursor_icon");
UpdateImage(7);

CreateXBMImage (convenience)

int CreateXBMImage(int id, int x, int y, const char* path, int colors);
Allocates the XBM (if not already loaded) under "XBMImage_" + path, creates a sized image element, draws, and flushes. No transparency parameter.
int colors = (CLR_LGREEN << 4) | CLR_BLACK;  // 0xA0
CreateXBMImage(8, 20, 20, "assets/logo.xbm", colors);

Capturing Screen Regions

unsigned char* CaptureRegion(int x, int y, unsigned short w, unsigned short h);
Captures a rectangular region from the current back-buffer and returns it as a heap-allocated in-memory TGA buffer. The buffer is a valid indexed TGA (type 1, 16-entry palette) that reflects the current palette.
  • Caller must free() the returned buffer.
  • Buffer size: 66 + w * h bytes (18-byte TGA header + 48-byte palette + w * h pixel data)
// Capture a 200×150 region starting at (50, 30)
unsigned char* screenshot = CaptureRegion(50, 30, 200, 150);
if (screenshot) {
    FILE* f = fopen("capture.tga", "wb");
    fwrite(screenshot, 1, 66 + 200 * 150, f);
    fclose(f);
    free(screenshot);
}
CaptureRegion can be used to implement a screenshot button, or to feed back a rendered region into AllocateMemoryTGA for further compositing.

Complete Example: Sprite Sheet with Recoloring

This example loads a TGA sprite with transparency, draws it, then demonstrates palette recoloring to render the same sprite in different team colors.
#include "libLWXGL.h"
#include <stdio.h>

#define CANVAS 1

int main(void) {
    CreateWindow(400, 200, "TGA Sprite Demo", CLR_BLACK, FLAG_NONE);
    CreateImage(CANVAS, 0, 0, 400, 200);

    // Load the sprite: palette index 0 is transparent (background)
    int status = AllocateTGA("hero", "assets/hero.tga", 0, 0);
    if (status != 0) {
        fprintf(stderr, "Failed to load TGA (error %d)\n", status);
        TerminateWindow();
        return 1;
    }

    // Draw the sprite at (20, 40) in its default colors
    ClearImage(CANVAS, CLR_BLACK);
    DrawIndexedTGA(CANVAS, 20, 40, "hero");

    // Recolor palette index 4 (red armor) to blue
    PaletteModify(4, 30, 80, 220, 0);  // r=30 g=80 b=220, no immediate redraw

    // Draw a second copy at (200, 40) in the modified palette
    DrawIndexedTGA(CANVAS, 200, 40, "hero");

    UpdateImage(CANVAS);

    // Restore default palette
    PaletteReset();

    MainWindowLoop(60, NULL);
    TerminateWindow();
    return 0;
}

Build docs developers (and LLMs) love