In ksquirrel-libs I use the following wrappers for built-in types (valid for x86, 32-bit platform): int - s32, unsigned int - u32, short - s16, unsigned short - u16, char - s8, unsinged char - u8. All of them are defined in fmt_types.h.
Defines one metainfo record. For example:
 {"JPEG 'COM' marker", "File written by Photoshop"}
struct fmt_metaentry
{
    Group name, for example "SGI Image name"
    std::string group;

    Information. For example "This image was created with MegaTool 0.5.1"
    std::string data;

};

Defines 32-bit pixel. Red, Green, Blue and Alpha channel.
struct RGBA
{
    RGBA() : r(0), g(0), b(0), a(0)
    {}

    RGBA(s32 r1, s32 g1, s32 b1, s32 a1) : r(r1), g(g1), b(b1), a(a1)
    {}

    u8 r;
    u8 g;
    u8 b;
    u8 a;
}PACKED;

Defines 24-bit color pixel. Red, Green, Blue.
struct RGB
{
    RGB() : r(0), g(0), b(0)
    {}

    RGB(s32 r1, s32 g1, s32 b1) : r(r1), g(g1), b(b1)
    {}

    u8 r;
    u8 g;
    u8 b;

}PACKED;

Defines one image. It stores the main information about one image: width,
height, metainfo, ...
struct fmt_image
{
    fmt_image() : w(0), h(0), bpp(0), hasalpha(false), needflip(false),
		    delay(0), interlaced(false), passes(1)
    {}

    width of the image
    s32                 w;
    height
    s32                 h;
    bits per pixel
    s32                 bpp;
    has alpha channel ?
    bool                hasalpha;
    flip ? (for example BMP needs)
    bool                needflip;
    only for animated images (like GIF)
    s32	                delay;
    Is it interlaced or normal ?
    bool		interlaced;
    Item 'passes' stores a number of passes if the image is iterlaced, or 1 otherwise.
    s32			passes;
    color space (RGB, RGBA, CMYK, LAB ...)
    std::string colorspace;
    compression type (RLE, JPEG, Deflate ...)
    std::string compression;

};

The main structure in ksquirrel-libs. It contains all information needed
to decode a file with one or more images.
struct fmt_info
{
    fmt_info() : animated(false)
    {}

    Array of fmt_image structures. One structure defines one image.
    std::vector<fmt_image>      image;

    Metainfo entries
    std::vector<fmt_metaentry>  meta;

    Is it animated or static ?
    bool		animated;

};


enum fmt_compression { 

No compression
CompressionNo = 1,

RLE compression
CompressionRLE = 2,

Internal cmpression. E.g. compression_level will be passed to internal routines,
for example in libjpeg, libpng.
Note: if the image can be compressed with RLE encoding and with only RLE
encoding, compression_scheme should be CompressionInternal
CompressionInternal = 4 };

Write options for image format
struct fmt_writeoptionsabs
{
    Can be interlaced ?
    bool interlaced;

    if interlaced, this value should store preferred number of passes.
    s32 passes;

    if the image should be flipped before writing
    bool needflip;

        with which compression it can be encoded ?
        for example: CompressionNo | CompressionRLE.
        it means, that image can be encoded with RLE
        method or can be saved without any compression.
    s32  compression_scheme;

        minimum compression level, maximum and default.
        For example, JPEG library has minimum = 0,
        maximum = 100 and default = 25.
    s32  compression_min, compression_max, compression_def;

}PACKED;

this information will be passed to writing function
struct fmt_writeoptions
{
    write interlaced image or normal ?
    bool interlaced;

    with which compression encode the image ?
    fmt_compression compression_scheme;

    compression level
    s32 compression_level;

    has alpha channel ? If no, A channel in RGBA image will be ignored
    bool alpha;

}PACKED;


We can use comparison operators for RGBA and RGB pixels. For example:

#define SQ_NEED_OPERATOR_RGBA_RGB

RGBA rgba;
RGB rgb;
...
if(rgba == rgb)
    printf("Pixels are equal!\n");

#if defined SQ_NEED_OPERATOR_RGBA_RGBA
static s32 operator== (const RGBA &rgba1, const RGBA &rgba2)
{
    return (rgba1.r == rgba2.r && rgba1.g == rgba2.g && rgba1.b == rgba2.b && rgba1.a == rgba2.a);
}
#endif

#if defined SQ_NEED_OPERATOR_RGB_RGBA
static s32 operator== (const RGB &rgb, const RGBA &rgba)
{
    return (rgb.r == rgba.r && rgb.g == rgba.g && rgb.b == rgba.b);
}
#endif

#if defined SQ_NEED_OPERATOR_RGBA_RGB
static s32 operator== (const RGBA &rgba, const RGB &rgb)
{
    return (rgba.r == rgb.r && rgba.g == rgb.g && rgba.b == rgb.b);
}
#endif

#endif