From a87c39daa8fa9a6dda3b0b4ba3e7e75eaeb8d469 Mon Sep 17 00:00:00 2001 From: Slyvtt Date: Tue, 3 May 2022 21:56:41 +0200 Subject: [PATCH] initial commit - not working --- IMG.c | 219 ++++++++++ IMG_bmp.c | 873 ++++++++++++++++++++++++++++++++++++++++ IMG_gif.c | 623 ++++++++++++++++++++++++++++ IMG_jpg.c | 493 +++++++++++++++++++++++ IMG_lbm.c | 501 +++++++++++++++++++++++ IMG_pcx.c | 275 +++++++++++++ IMG_png.c | 601 +++++++++++++++++++++++++++ IMG_pnm.c | 255 ++++++++++++ IMG_tga.c | 334 +++++++++++++++ IMG_tif.c | 298 ++++++++++++++ IMG_webp.c | 294 ++++++++++++++ IMG_xcf.c | 821 +++++++++++++++++++++++++++++++++++++ IMG_xpm.c | 511 +++++++++++++++++++++++ IMG_xv.c | 164 ++++++++ IMG_xxx.c | 87 ++++ Makefile.prizm | 38 ++ SDL/SDL_image.h | 138 +++++++ build | 4 + cSDL_image1_2_12.cbp | 65 +++ cSDL_image1_2_12.layout | 115 ++++++ 20 files changed, 6709 insertions(+) create mode 100644 IMG.c create mode 100644 IMG_bmp.c create mode 100644 IMG_gif.c create mode 100644 IMG_jpg.c create mode 100644 IMG_lbm.c create mode 100644 IMG_pcx.c create mode 100644 IMG_png.c create mode 100644 IMG_pnm.c create mode 100644 IMG_tga.c create mode 100644 IMG_tif.c create mode 100644 IMG_webp.c create mode 100644 IMG_xcf.c create mode 100644 IMG_xpm.c create mode 100644 IMG_xv.c create mode 100644 IMG_xxx.c create mode 100644 Makefile.prizm create mode 100644 SDL/SDL_image.h create mode 100755 build create mode 100644 cSDL_image1_2_12.cbp create mode 100644 cSDL_image1_2_12.layout diff --git a/IMG.c b/IMG.c new file mode 100644 index 0000000..a8bc087 --- /dev/null +++ b/IMG.c @@ -0,0 +1,219 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* A simple library to load images of various formats as SDL surfaces */ + +#include + +#include "SDL/SDL_image.h" +#include "SDL/SDL.h" + +#include +#include +#include +#include + + +#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) + +const SDL_version *IMG_Linked_Version(void) +{ + static SDL_version linked_version; + SDL_IMAGE_VERSION(&linked_version); + return(&linked_version); +} + +extern int IMG_InitJPG(); +extern void IMG_QuitJPG(); +extern int IMG_InitPNG(); +extern void IMG_QuitPNG(); +extern int IMG_InitTIF(); +extern void IMG_QuitTIF(); + +extern int IMG_InitWEBP(); +extern void IMG_QuitWEBP(); + +static int initialized = 0; + +int IMG_Init(int flags) +{ + int result = 0; + + if (flags & IMG_INIT_JPG) { + if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) { + result |= IMG_INIT_JPG; + } + } + if (flags & IMG_INIT_PNG) { + if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) { + result |= IMG_INIT_PNG; + } + } + if (flags & IMG_INIT_TIF) { + if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) { + result |= IMG_INIT_TIF; + } + } + if (flags & IMG_INIT_WEBP) { + if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) { + result |= IMG_INIT_WEBP; + } + } + initialized |= result; + + return (initialized); +} + +void IMG_Quit() +{ + if (initialized & IMG_INIT_JPG) { + IMG_QuitJPG(); + } + if (initialized & IMG_INIT_PNG) { + IMG_QuitPNG(); + } + if (initialized & IMG_INIT_TIF) { + IMG_QuitTIF(); + } + if (initialized & IMG_INIT_WEBP) { + IMG_QuitWEBP(); + } + initialized = 0; +} + + +static int stoupper(int c) +{ + if(c >= 'a' && c <= 'z') + return 'A' + (c - 'a'); + return c; +} + +/* Portable case-insensitive string compare function */ +static int IMG_string_equals(const char *str1, const char *str2) +{ + while ( *str1 && *str2 ) { + if ( stoupper((unsigned char)*str1) != + stoupper((unsigned char)*str2) ) + break; + ++str1; + ++str2; + } + return (!*str1 && !*str2); +} + + + +SDL_Surface *IMG_Load(const char *file) +{ + ///cSDL_LogToFile( "IMG_Load : %s", file ); + + SDL_RWops *src = SDL_RWFromFile(file, "rb"); + char buf[256]; + char *ext; + strcpy(buf, file); + ext = strrchr(buf, '.'); + + if(ext[0]=='.') ext++; + + if(!src) { + return NULL; + } + return IMG_LoadTyped_RW(src, 1, ext); +} + +/* Load an image from an SDL datasource (for compatibility) */ +SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc) +{ + return IMG_LoadTyped_RW(src, freesrc, NULL); +} + +/* Load an image from an SDL datasource, optionally specifying the type */ +SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type) +{ + ///cSDL_LogToFile( "IMG_LoadTypeRW : %p - %d - %s", src, freesrc, type ); + + int i; + SDL_Surface *image; + + /* Make sure there is something to do.. */ + if ( src == NULL ) { + IMG_SetError("Passed a NULL data source"); + ///cSDL_LogToFile( "IMG_LoadTypeRW : src is NULL !!!" ); + return(NULL); + } + + /* See whether or not this data source can handle seeking */ + long temp = SDL_RWseek(src, 0, RW_SEEK_CUR); + + dprint(1,10, C_BLACK, "temp = %d", temp ); + + if ( temp < 0 ) { + IMG_SetError("Can't seek in this data source"); + ///cSDL_LogToFile( "IMG_LoadTypeRW : can't seek in the file !!!" ); + if(freesrc) + SDL_RWclose(src); + return(NULL); + } + + /* Please kill me for this mess, doesn't work otherwise... */ + image = NULL; + + if(type && IMG_string_equals(type, "TGA")) image = IMG_LoadTGA_RW(src); + else if(IMG_isCUR(src)) image = IMG_LoadCUR_RW(src); + else if(IMG_isICO(src)) image = IMG_LoadICO_RW(src); + + //else if(IMG_isBMP(src)) cSDL_LogToFile( "IMG_LoadTypeRW : will now call IMG_LoadBMP_RW" ), image = IMG_LoadBMP_RW(src); + else if(type && IMG_string_equals(type, "BMP")) image = IMG_LoadBMP_RW(src); + + else if(IMG_isGIF(src)) image = IMG_LoadGIF_RW(src); + else if(IMG_isJPG(src)) image = IMG_LoadJPG_RW(src); + else if(IMG_isLBM(src)) image = IMG_LoadLBM_RW(src); + else if(IMG_isPCX(src)) image = IMG_LoadPCX_RW(src); + + //else if(IMG_isPNG(src)) cSDL_LogToFile( "IMG_LoadTypeRW : will now call IMG_LoadPNG_RW" ), image = IMG_LoadPNG_RW(src); + else if(type && IMG_string_equals(type, "PNG")) image = IMG_LoadPNG_RW(src); + + else if(IMG_isPNM(src)) image = IMG_LoadPNM_RW(src); + else if(IMG_isTIF(src)) image = IMG_LoadTIF_RW(src); + else if(IMG_isXCF(src)) image = IMG_LoadXCF_RW(src); + else if(IMG_isXPM(src)) image = IMG_LoadXPM_RW(src); + else if(IMG_isXV(src)) image = IMG_LoadXV_RW(src); + else if(IMG_isWEBP(src)) image = IMG_LoadWEBP_RW(src); + + if(freesrc) + SDL_RWclose(src); + + if(image) + return image; + else { + IMG_SetError("Unsupported image format"); + return NULL; + } +} + +/* Invert the alpha of a surface for use with OpenGL + This function is a no-op and only kept for backwards compatibility. + */ +int IMG_InvertAlpha(int on) +{ + return 1; +} diff --git a/IMG_bmp.c b/IMG_bmp.c new file mode 100644 index 0000000..5894245 --- /dev/null +++ b/IMG_bmp.c @@ -0,0 +1,873 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a BMP image file loading framework */ +/* ICO/CUR file support is here as well since it uses similar internal + * representation */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_BMP + +/* See if an image is contained in a data source */ +int IMG_isBMP(SDL_RWops *src) +{ + int start; + int is_BMP; + char magic[2]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_BMP = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + if ( strncmp(magic, "BM", 2) == 0 ) { + is_BMP = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_BMP); +} + +static int IMG_isICOCUR(SDL_RWops *src, int type) +{ + int start; + int is_ICOCUR; + + /* The Win32 ICO file header (14 bytes) */ + Uint16 bfReserved; + Uint16 bfType; + Uint16 bfCount; + + if ( !src ) + return 0; + puts(".a"); + start = SDL_RWtell(src); + puts(".b"); + is_ICOCUR = 0; + bfReserved = SDL_ReadLE16(src); + puts(".c"); + bfType = SDL_ReadLE16(src); + puts(".d"); + bfCount = SDL_ReadLE16(src); + puts(".e"); + if ((bfReserved == 0) && (bfType == type) && (bfCount != 0)) + is_ICOCUR = 1; + SDL_RWseek(src, start, RW_SEEK_SET); + puts(".f"); + + return (is_ICOCUR); +} + +int IMG_isICO(SDL_RWops *src) +{ + return IMG_isICOCUR(src, 1); +} + +int IMG_isCUR(SDL_RWops *src) +{ + puts("a"); + return IMG_isICOCUR(src, 2); +} + +#include "SDL/SDL_error.h" +#include "SDL/SDL_video.h" +#include "SDL/SDL_endian.h" + +#include +#include +#include +#include + +/* Compression encodings for BMP files */ +#ifndef BI_RGB +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#define BI_BITFIELDS 3 +#endif + +static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8) +{ + /* + | Sets the surface pixels from src. A bmp image is upside down. + */ + int pitch = surface->pitch; + int height = surface->h; + Uint8 *start = (Uint8 *)surface->pixels; + Uint8 *end = start + (height*pitch); + Uint8 *bits = end-pitch, *spot; + int ofs = 0; + Uint8 ch; + Uint8 needsPad; + +#define COPY_PIXEL(x) spot = &bits[ofs++]; if(spot >= start && spot < end) *spot = (x) + + for (;;) { + if ( !SDL_RWread(src, &ch, 1, 1) ) return 1; + /* + | encoded mode starts with a run length, and then a byte + | with two colour indexes to alternate between for the run + */ + if ( ch ) { + Uint8 pixel; + if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1; + if ( isRle8 ) { /* 256-color bitmap, compressed */ + do { + COPY_PIXEL(pixel); + } while (--ch); + } else { /* 16-color bitmap, compressed */ + Uint8 pixel0 = pixel >> 4; + Uint8 pixel1 = pixel & 0x0F; + for (;;) { + COPY_PIXEL(pixel0); /* even count, high nibble */ + if (!--ch) break; + COPY_PIXEL(pixel1); /* odd count, low nibble */ + if (!--ch) break; + } + } + } else { + /* + | A leading zero is an escape; it may signal the end of the bitmap, + | a cursor move, or some absolute data. + | zero tag may be absolute mode or an escape + */ + if ( !SDL_RWread(src, &ch, 1, 1) ) return 1; + switch (ch) { + case 0: /* end of line */ + ofs = 0; + bits -= pitch; /* go to previous */ + break; + case 1: /* end of bitmap */ + return 0; /* success! */ + case 2: /* delta */ + if ( !SDL_RWread(src, &ch, 1, 1) ) return 1; + ofs += ch; + if ( !SDL_RWread(src, &ch, 1, 1) ) return 1; + bits -= (ch * pitch); + break; + default: /* no compression */ + if (isRle8) { + needsPad = ( ch & 1 ); + do { + Uint8 pixel; + if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1; + COPY_PIXEL(pixel); + } while (--ch); + } else { + needsPad = ( ((ch+1)>>1) & 1 ); /* (ch+1)>>1: bytes size */ + for (;;) { + Uint8 pixel; + if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1; + COPY_PIXEL(pixel >> 4); + if (!--ch) break; + COPY_PIXEL(pixel & 0x0F); + if (!--ch) break; + } + } + /* pad at even boundary */ + if ( needsPad && !SDL_RWread(src, &ch, 1, 1) ) return 1; + break; + } + } + } +} + +static SDL_Surface *LoadBMP_RW (SDL_RWops *src, int freesrc) +{ + SDL_bool was_error; + long fp_offset; + int bmpPitch; + int i, pad; + SDL_Surface *surface; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; + SDL_Palette *palette; + Uint8 *bits; + Uint8 *top, *end; + SDL_bool topDown; + int ExpandBMP; + + /* The Win32 BMP file header (14 bytes) */ + char magic[2]; + Uint32 bfSize; + Uint16 bfReserved1; + Uint16 bfReserved2; + Uint32 bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we are passed a valid data source */ + surface = NULL; + was_error = SDL_FALSE; + if ( src == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Read in the BMP file header */ + fp_offset = SDL_RWtell(src); + + dprint(1,20, C_BLACK, "fp_offset = %d", fp_offset ); + r61524_display(gint_vram, 0, DHEIGHT, R61524_CPU); + getkey(); + + SDL_ClearError(); + if ( SDL_RWread(src, magic, 1, 2) != 2 ) { + //cSDL_LogToFile( "LoadBMP_RW : point 3 - magic test : fp_offset = %d", fp_offset ); + //cSDL_LogToFile( "LoadBMP_RW : point 3.5 - magic = %s", magic ); + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } + if ( strncmp(magic, "BM", 2) != 0 ) { + //cSDL_LogToFile( "LoadBMP_RW : point 4 - Not a BMP File" ); + IMG_SetError("File is not a Windows BMP file"); + was_error = SDL_TRUE; + goto done; + } + + cSDL_LogToFile( "JE SUIS PASSE !!!" ); + + bfSize = SDL_ReadLE32(src); + bfReserved1 = SDL_ReadLE16(src); + bfReserved2 = SDL_ReadLE16(src); + bfOffBits = SDL_ReadLE32(src); + + /* Read the Win32 BITMAPINFOHEADER */ + biSize = SDL_ReadLE32(src); + if ( biSize == 12 ) { + biWidth = (Uint32)SDL_ReadLE16(src); + biHeight = (Uint32)SDL_ReadLE16(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = BI_RGB; + biSizeImage = 0; + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + biClrUsed = 0; + biClrImportant = 0; + } else { + biWidth = SDL_ReadLE32(src); + biHeight = SDL_ReadLE32(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = SDL_ReadLE32(src); + biSizeImage = SDL_ReadLE32(src); + biXPelsPerMeter = SDL_ReadLE32(src); + biYPelsPerMeter = SDL_ReadLE32(src); + biClrUsed = SDL_ReadLE32(src); + biClrImportant = SDL_ReadLE32(src); + } + + cSDL_LogToFile( "LoadBMP_RW : point 5 - image data : W= %D , H= %D", biWidth, biHeight ); + + if (biHeight < 0) { + topDown = SDL_TRUE; + biHeight = -biHeight; + } else { + topDown = SDL_FALSE; + } + + /* Check for read error */ + if ( strcmp(SDL_GetError(), "") != 0 ) { + was_error = SDL_TRUE; + goto done; + } + + /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ + switch (biBitCount) { + case 1: + case 4: + ExpandBMP = biBitCount; + biBitCount = 8; + break; + default: + ExpandBMP = 0; + break; + } + + /* RLE4 and RLE8 BMP compression is supported */ + Rmask = Gmask = Bmask = Amask = 0; + switch (biCompression) { + case BI_RGB: + /* If there are no masks, use the defaults */ + if ( bfOffBits == (14+biSize) ) { + /* Default values for the BMP format */ + switch (biBitCount) { + case 15: + case 16: + Rmask = 0x7C00; + Gmask = 0x03E0; + Bmask = 0x001F; + break; + case 24: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; +#else + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; +#endif + break; + case 32: + Amask = 0xFF000000; + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + break; + default: + break; + } + break; + } + /* Fall through -- read the RGB masks */ + + default: + switch (biBitCount) { + case 15: + case 16: + Rmask = SDL_ReadLE32(src); + Gmask = SDL_ReadLE32(src); + Bmask = SDL_ReadLE32(src); + break; + case 32: + Rmask = SDL_ReadLE32(src); + Gmask = SDL_ReadLE32(src); + Bmask = SDL_ReadLE32(src); + Amask = SDL_ReadLE32(src); + break; + default: + break; + } + break; + } + + /* Create a compatible surface, note that the colors are RGB ordered */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, Amask); + if ( surface == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Load the palette, if any */ + palette = (surface->format)->palette; + if ( palette ) { + if ( SDL_RWseek(src, fp_offset+14+biSize, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + was_error = SDL_TRUE; + goto done; + } + + /* + | guich: always use 1<colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + palette->colors[i].unused = 0; + } + } else { + for ( i = 0; i < (int)biClrUsed; ++i ) { + SDL_RWread(src, &palette->colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + SDL_RWread(src, &palette->colors[i].unused, 1, 1); + } + } + palette->ncolors = biClrUsed; + } + + /* Read the surface pixels. Note that the bmp image is upside down */ + if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + was_error = SDL_TRUE; + goto done; + } + if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) { + was_error = readRlePixels(surface, src, biCompression == BI_RLE8); + if (was_error) IMG_SetError("Error reading from BMP"); + goto done; + } + top = (Uint8 *)surface->pixels; + end = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + switch (ExpandBMP) { + case 1: + bmpPitch = (biWidth + 7) >> 3; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + case 4: + bmpPitch = (biWidth + 1) >> 1; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + default: + pad = ((surface->pitch%4) ? + (4-(surface->pitch%4)) : 0); + break; + } + if ( topDown ) { + bits = top; + } else { + bits = end - surface->pitch; + } + while ( bits >= top && bits < end ) { + switch (ExpandBMP) { + case 1: + case 4: { + Uint8 pixel = 0; + int shift = (8-ExpandBMP); + for ( i=0; iw; ++i ) { + if ( i%(8/ExpandBMP) == 0 ) { + if ( !SDL_RWread(src, &pixel, 1, 1) ) { + IMG_SetError( + "Error reading from BMP"); + was_error = SDL_TRUE; + goto done; + } + } + *(bits+i) = (pixel>>shift); + pixel <<= ExpandBMP; + } } + break; + + default: + if ( SDL_RWread(src, bits, 1, surface->pitch) + != surface->pitch ) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + /* Byte-swap the pixels if needed. Note that the 24bpp + case has already been taken care of above. */ + switch(biBitCount) { + case 15: + case 16: { + Uint16 *pix = (Uint16 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap16(pix[i]); + break; + } + + case 32: { + Uint32 *pix = (Uint32 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap32(pix[i]); + break; + } + } +#endif + break; + } + /* Skip padding bytes, ugh */ + if ( pad ) { + Uint8 padbyte; + for ( i=0; ipitch; + } else { + bits -= surface->pitch; + } + } +done: + if ( was_error ) { + if ( src ) { + SDL_RWseek(src, fp_offset, RW_SEEK_SET); + } + if ( surface ) { + SDL_FreeSurface(surface); + } + surface = NULL; + } + if ( freesrc && src ) { + SDL_RWclose(src); + } + return(surface); +} + +static Uint8 +SDL_Read8(SDL_RWops * src) +{ + Uint8 value; + + SDL_RWread(src, &value, 1, 1); + return (value); +} + +static SDL_Surface * +LoadICOCUR_RW(SDL_RWops * src, int type, int freesrc) +{ + SDL_bool was_error; + long fp_offset; + int bmpPitch; + int i, pad; + SDL_Surface *surface; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint8 *bits; + int ExpandBMP; + int maxCol = 0; + int icoOfs = 0; + Uint32 palette[256]; + + /* The Win32 ICO file header (14 bytes) */ + Uint16 bfReserved; + Uint16 bfType; + Uint16 bfCount; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we are passed a valid data source */ + surface = NULL; + was_error = SDL_FALSE; + if (src == NULL) { + was_error = SDL_TRUE; + goto done; + } + + /* Read in the ICO file header */ + fp_offset = SDL_RWtell(src); + SDL_ClearError(); + + bfReserved = SDL_ReadLE16(src); + bfType = SDL_ReadLE16(src); + bfCount = SDL_ReadLE16(src); + if ((bfReserved != 0) || (bfType != type) || (bfCount == 0)) { + IMG_SetError("File is not a Windows %s file", type == 1 ? "ICO" : "CUR"); + was_error = SDL_TRUE; + goto done; + } + + /* Read the Win32 Icon Directory */ + for (i = 0; i < bfCount; i++) { + /* Icon Directory Entries */ + int bWidth = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ + int bHeight = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ + int bColorCount = SDL_Read8(src); /* Uint8, but 0 = 256 ! */ + Uint8 bReserved = SDL_Read8(src); + Uint16 wPlanes = SDL_ReadLE16(src); + Uint16 wBitCount = SDL_ReadLE16(src); + Uint32 dwBytesInRes = SDL_ReadLE32(src); + Uint32 dwImageOffset = SDL_ReadLE32(src); + + if (!bWidth) + bWidth = 256; + if (!bHeight) + bHeight = 256; + if (!bColorCount) + bColorCount = 256; + + //printf("%dx%d@%d - %08x\n", bWidth, bHeight, bColorCount, dwImageOffset); + if (bColorCount > maxCol) { + maxCol = bColorCount; + icoOfs = dwImageOffset; + //printf("marked\n"); + } + } + + /* Advance to the DIB Data */ + if (SDL_RWseek(src, icoOfs, RW_SEEK_SET) < 0) { + SDL_Error(SDL_EFSEEK); + was_error = SDL_TRUE; + goto done; + } + + /* Read the Win32 BITMAPINFOHEADER */ + biSize = SDL_ReadLE32(src); + if (biSize == 40) { + biWidth = SDL_ReadLE32(src); + biHeight = SDL_ReadLE32(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = SDL_ReadLE32(src); + biSizeImage = SDL_ReadLE32(src); + biXPelsPerMeter = SDL_ReadLE32(src); + biYPelsPerMeter = SDL_ReadLE32(src); + biClrUsed = SDL_ReadLE32(src); + biClrImportant = SDL_ReadLE32(src); + } else { + IMG_SetError("Unsupported ICO bitmap format"); + was_error = SDL_TRUE; + goto done; + } + + /* Check for read error */ + if (SDL_strcmp(SDL_GetError(), "") != 0) { + was_error = SDL_TRUE; + goto done; + } + + /* We don't support any BMP compression right now */ + switch (biCompression) { + case BI_RGB: + /* Default values for the BMP format */ + switch (biBitCount) { + case 1: + case 4: + ExpandBMP = biBitCount; + biBitCount = 8; + break; + case 8: + ExpandBMP = 8; + break; + case 32: + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + ExpandBMP = 0; + break; + default: + IMG_SetError("ICO file with unsupported bit count"); + was_error = SDL_TRUE; + goto done; + } + break; + default: + IMG_SetError("Compressed ICO files not supported"); + was_error = SDL_TRUE; + goto done; + } + + /* Create a RGBA surface */ + biHeight = biHeight >> 1; + //printf("%d x %d\n", biWidth, biHeight); + surface = + SDL_CreateRGBSurface(0, biWidth, biHeight, 32, 0x00FF0000, + 0x0000FF00, 0x000000FF, 0xFF000000); + if (surface == NULL) { + was_error = SDL_TRUE; + goto done; + } + + /* Load the palette, if any */ + //printf("bc %d bused %d\n", biBitCount, biClrUsed); + if (biBitCount <= 8) { + if (biClrUsed == 0) { + biClrUsed = 1 << biBitCount; + } + for (i = 0; i < (int) biClrUsed; ++i) { + SDL_RWread(src, &palette[i], 4, 1); + } + } + + /* Read the surface pixels. Note that the bmp image is upside down */ + bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); + switch (ExpandBMP) { + case 1: + bmpPitch = (biWidth + 7) >> 3; + pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); + break; + case 4: + bmpPitch = (biWidth + 1) >> 1; + pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); + break; + case 8: + bmpPitch = biWidth; + pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); + break; + default: + bmpPitch = biWidth * 4; + pad = 0; + break; + } + while (bits > (Uint8 *) surface->pixels) { + bits -= surface->pitch; + switch (ExpandBMP) { + case 1: + case 4: + case 8: + { + Uint8 pixel = 0; + int shift = (8 - ExpandBMP); + for (i = 0; i < surface->w; ++i) { + if (i % (8 / ExpandBMP) == 0) { + if (!SDL_RWread(src, &pixel, 1, 1)) { + IMG_SetError("Error reading from ICO"); + was_error = SDL_TRUE; + goto done; + } + } + *((Uint32 *) bits + i) = (palette[pixel >> shift]); + pixel <<= ExpandBMP; + } + } + break; + + default: + if (SDL_RWread(src, bits, 1, surface->pitch) + != surface->pitch) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } + break; + } + /* Skip padding bytes, ugh */ + if (pad) { + Uint8 padbyte; + for (i = 0; i < pad; ++i) { + SDL_RWread(src, &padbyte, 1, 1); + } + } + } + /* Read the mask pixels. Note that the bmp image is upside down */ + bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch); + ExpandBMP = 1; + bmpPitch = (biWidth + 7) >> 3; + pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0); + while (bits > (Uint8 *) surface->pixels) { + Uint8 pixel = 0; + int shift = (8 - ExpandBMP); + + bits -= surface->pitch; + for (i = 0; i < surface->w; ++i) { + if (i % (8 / ExpandBMP) == 0) { + if (!SDL_RWread(src, &pixel, 1, 1)) { + IMG_SetError("Error reading from ICO"); + was_error = SDL_TRUE; + goto done; + } + } + *((Uint32 *) bits + i) |= ((pixel >> shift) ? 0 : 0xFF000000); + pixel <<= ExpandBMP; + } + /* Skip padding bytes, ugh */ + if (pad) { + Uint8 padbyte; + for (i = 0; i < pad; ++i) { + SDL_RWread(src, &padbyte, 1, 1); + } + } + } + done: + if (was_error) { + if (src) { + SDL_RWseek(src, fp_offset, RW_SEEK_SET); + } + if (surface) { + SDL_FreeSurface(surface); + } + surface = NULL; + } + if (freesrc && src) { + SDL_RWclose(src); + } + return (surface); +} + +/* Load a BMP type image from an SDL datasource */ +SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src) +{ + return(LoadBMP_RW(src, 0)); +} + +/* Load a ICO type image from an SDL datasource */ +SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src) +{ + return(LoadICOCUR_RW(src, 1, 0)); +} + +/* Load a CUR type image from an SDL datasource */ +SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src) +{ + return(LoadICOCUR_RW(src, 2, 0)); +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isBMP(SDL_RWops *src) +{ + return(0); +} + +int IMG_isICO(SDL_RWops *src) +{ + return(0); +} + +int IMG_isCUR(SDL_RWops *src) +{ + return(0); +} + +/* Load a BMP type image from an SDL datasource */ +SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src) +{ + return(NULL); +} + +/* Load a BMP type image from an SDL datasource */ +SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src) +{ + return(NULL); +} + +/* Load a BMP type image from an SDL datasource */ +SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_BMP */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_gif.c b/IMG_gif.c new file mode 100644 index 0000000..0a5163a --- /dev/null +++ b/IMG_gif.c @@ -0,0 +1,623 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a GIF image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_GIF + +/* See if an image is contained in a data source */ +int IMG_isGIF(SDL_RWops *src) +{ + int start; + int is_GIF; + char magic[6]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_GIF = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + if ( (strncmp(magic, "GIF", 3) == 0) && + ((memcmp(magic + 3, "87a", 3) == 0) || + (memcmp(magic + 3, "89a", 3) == 0)) ) { + is_GIF = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_GIF); +} + +/* Code from here to end of file has been adapted from XPaint: */ +/* +-------------------------------------------------------------------+ */ +/* | Copyright 1990, 1991, 1993 David Koblas. | */ +/* | Copyright 1996 Torsten Martinsen. | */ +/* | Permission to use, copy, modify, and distribute this software | */ +/* | and its documentation for any purpose and without fee is hereby | */ +/* | granted, provided that the above copyright notice appear in all | */ +/* | copies and that both that copyright notice and this permission | */ +/* | notice appear in supporting documentation. This software is | */ +/* | provided "as is" without express or implied warranty. | */ +/* +-------------------------------------------------------------------+ */ + +/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */ +#define USED_BY_SDL + +#include + +#ifdef USED_BY_SDL +/* Changes to work with SDL: + + Include SDL header file + Use SDL_Surface rather than xpaint Image structure + Define SDL versions of RWSetMsg(), ImageNewCmap() and ImageSetCmap() +*/ +#include "SDL/SDL.h" + +#define Image SDL_Surface +#define RWSetMsg IMG_SetError +#define ImageNewCmap(w, h, s) SDL_AllocSurface(SDL_SWSURFACE,w,h,8,0,0,0,0) +#define ImageSetCmap(s, i, R, G, B) do { \ + s->format->palette->colors[i].r = R; \ + s->format->palette->colors[i].g = G; \ + s->format->palette->colors[i].b = B; \ + } while (0) +/* * * * * */ + +#else + +/* Original XPaint sources */ + +#include "image.h" +#include "rwTable.h" + +#define SDL_RWops FILE +#define SDL_RWclose fclose + +#endif /* USED_BY_SDL */ + + +#define MAXCOLORMAPSIZE 256 + +#define TRUE 1 +#define FALSE 0 + +#define CM_RED 0 +#define CM_GREEN 1 +#define CM_BLUE 2 + +#define MAX_LWZ_BITS 12 + +#define INTERLACE 0x40 +#define LOCALCOLORMAP 0x80 +#define BitSet(byte, bit) (((byte) & (bit)) == (bit)) + +#define ReadOK(file,buffer,len) SDL_RWread(file, buffer, len, 1) + +#define LM_to_uint(a,b) (((b)<<8)|(a)) + +static struct { + unsigned int Width; + unsigned int Height; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned int BitPixel; + unsigned int ColorResolution; + unsigned int Background; + unsigned int AspectRatio; + int GrayScale; +} GifScreen; + +static struct { + int transparent; + int delayTime; + int inputFlag; + int disposal; +} Gif89; + +static int ReadColorMap(SDL_RWops * src, int number, + unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag); +static int DoExtension(SDL_RWops * src, int label); +static int GetDataBlock(SDL_RWops * src, unsigned char *buf); +static int GetCode(SDL_RWops * src, int code_size, int flag); +static int LWZReadByte(SDL_RWops * src, int flag, int input_code_size); +static Image *ReadImage(SDL_RWops * src, int len, int height, int, + unsigned char cmap[3][MAXCOLORMAPSIZE], + int gray, int interlace, int ignore); + +Image * +IMG_LoadGIF_RW(SDL_RWops *src) +{ + int start; + unsigned char buf[16]; + unsigned char c; + unsigned char localColorMap[3][MAXCOLORMAPSIZE]; + int grayScale; + int useGlobalColormap; + int bitPixel; + int imageCount = 0; + char version[4]; + int imageNumber = 1; + Image *image = NULL; + + if ( src == NULL ) { + return NULL; + } + start = SDL_RWtell(src); + + if (!ReadOK(src, buf, 6)) { + RWSetMsg("error reading magic number"); + goto done; + } + if (strncmp((char *) buf, "GIF", 3) != 0) { + RWSetMsg("not a GIF file"); + goto done; + } + memcpy(version, (char *) buf + 3, 3); + version[3] = '\0'; + + if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { + RWSetMsg("bad version number, not '87a' or '89a'"); + goto done; + } + Gif89.transparent = -1; + Gif89.delayTime = -1; + Gif89.inputFlag = -1; + Gif89.disposal = 0; + + if (!ReadOK(src, buf, 7)) { + RWSetMsg("failed to read screen descriptor"); + goto done; + } + GifScreen.Width = LM_to_uint(buf[0], buf[1]); + GifScreen.Height = LM_to_uint(buf[2], buf[3]); + GifScreen.BitPixel = 2 << (buf[4] & 0x07); + GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); + GifScreen.Background = buf[5]; + GifScreen.AspectRatio = buf[6]; + + if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ + if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap, + &GifScreen.GrayScale)) { + RWSetMsg("error reading global colormap"); + goto done; + } + } + do { + if (!ReadOK(src, &c, 1)) { + RWSetMsg("EOF / read error on image data"); + goto done; + } + if (c == ';') { /* GIF terminator */ + if (imageCount < imageNumber) { + RWSetMsg("only %d image%s found in file", + imageCount, imageCount > 1 ? "s" : ""); + goto done; + } + } + if (c == '!') { /* Extension */ + if (!ReadOK(src, &c, 1)) { + RWSetMsg("EOF / read error on extention function code"); + goto done; + } + DoExtension(src, c); + continue; + } + if (c != ',') { /* Not a valid start character */ + continue; + } + ++imageCount; + + if (!ReadOK(src, buf, 9)) { + RWSetMsg("couldn't read left/top/width/height"); + goto done; + } + useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP); + + bitPixel = 1 << ((buf[8] & 0x07) + 1); + + if (!useGlobalColormap) { + if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) { + RWSetMsg("error reading local colormap"); + goto done; + } + image = ReadImage(src, LM_to_uint(buf[4], buf[5]), + LM_to_uint(buf[6], buf[7]), + bitPixel, localColorMap, grayScale, + BitSet(buf[8], INTERLACE), + imageCount != imageNumber); + } else { + image = ReadImage(src, LM_to_uint(buf[4], buf[5]), + LM_to_uint(buf[6], buf[7]), + GifScreen.BitPixel, GifScreen.ColorMap, + GifScreen.GrayScale, BitSet(buf[8], INTERLACE), + imageCount != imageNumber); + } + } while (image == NULL); + +#ifdef USED_BY_SDL + if ( Gif89.transparent >= 0 ) { + SDL_SetColorKey(image, SDL_SRCCOLORKEY, Gif89.transparent); + } +#endif + +done: + if ( image == NULL ) { + SDL_RWseek(src, start, RW_SEEK_SET); + } + return image; +} + +static int +ReadColorMap(SDL_RWops *src, int number, + unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray) +{ + int i; + unsigned char rgb[3]; + int flag; + + flag = TRUE; + + for (i = 0; i < number; ++i) { + if (!ReadOK(src, rgb, sizeof(rgb))) { + RWSetMsg("bad colormap"); + return 1; + } + buffer[CM_RED][i] = rgb[0]; + buffer[CM_GREEN][i] = rgb[1]; + buffer[CM_BLUE][i] = rgb[2]; + flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]); + } + +#if 0 + if (flag) + *gray = (number == 2) ? PBM_TYPE : PGM_TYPE; + else + *gray = PPM_TYPE; +#else + *gray = 0; +#endif + + return FALSE; +} + +static int +DoExtension(SDL_RWops *src, int label) +{ + static unsigned char buf[256]; + char *str; + + switch (label) { + case 0x01: /* Plain Text Extension */ + str = "Plain Text Extension"; + break; + case 0xff: /* Application Extension */ + str = "Application Extension"; + break; + case 0xfe: /* Comment Extension */ + str = "Comment Extension"; + while (GetDataBlock(src, (unsigned char *) buf) != 0) + ; + return FALSE; + case 0xf9: /* Graphic Control Extension */ + str = "Graphic Control Extension"; + (void) GetDataBlock(src, (unsigned char *) buf); + Gif89.disposal = (buf[0] >> 2) & 0x7; + Gif89.inputFlag = (buf[0] >> 1) & 0x1; + Gif89.delayTime = LM_to_uint(buf[1], buf[2]); + if ((buf[0] & 0x1) != 0) + Gif89.transparent = buf[3]; + + while (GetDataBlock(src, (unsigned char *) buf) != 0) + ; + return FALSE; + default: + str = (char *)buf; + sprintf(str, "UNKNOWN (0x%02x)", label); + break; + } + + while (GetDataBlock(src, (unsigned char *) buf) != 0) + ; + + return FALSE; +} + +static int ZeroDataBlock = FALSE; + +static int +GetDataBlock(SDL_RWops *src, unsigned char *buf) +{ + unsigned char count; + + if (!ReadOK(src, &count, 1)) { + /* pm_message("error in getting DataBlock size" ); */ + return -1; + } + ZeroDataBlock = count == 0; + + if ((count != 0) && (!ReadOK(src, buf, count))) { + /* pm_message("error in reading DataBlock" ); */ + return -1; + } + return count; +} + +static int +GetCode(SDL_RWops *src, int code_size, int flag) +{ + static unsigned char buf[280]; + static int curbit, lastbit, done, last_byte; + int i, j, ret; + unsigned char count; + + if (flag) { + curbit = 0; + lastbit = 0; + done = FALSE; + return 0; + } + if ((curbit + code_size) >= lastbit) { + if (done) { + if (curbit >= lastbit) + RWSetMsg("ran off the end of my bits"); + return -1; + } + buf[0] = buf[last_byte - 2]; + buf[1] = buf[last_byte - 1]; + + if ((count = GetDataBlock(src, &buf[2])) == 0) + done = TRUE; + + last_byte = 2 + count; + curbit = (curbit - lastbit) + 16; + lastbit = (2 + count) * 8; + } + ret = 0; + for (i = curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j; + + curbit += code_size; + + return ret; +} + +static int +LWZReadByte(SDL_RWops *src, int flag, int input_code_size) +{ + static int fresh = FALSE; + int code, incode; + static int code_size, set_code_size; + static int max_code, max_code_size; + static int firstcode, oldcode; + static int clear_code, end_code; + static int table[2][(1 << MAX_LWZ_BITS)]; + static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp; + register int i; + + /* Fixed buffer overflow found by Michael Skladnikiewicz */ + if (input_code_size > MAX_LWZ_BITS) + return -1; + + if (flag) { + set_code_size = input_code_size; + code_size = set_code_size + 1; + clear_code = 1 << set_code_size; + end_code = clear_code + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + + GetCode(src, 0, TRUE); + + fresh = TRUE; + + for (i = 0; i < clear_code; ++i) { + table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1 << MAX_LWZ_BITS); ++i) + table[0][i] = table[1][0] = 0; + + sp = stack; + + return 0; + } else if (fresh) { + fresh = FALSE; + do { + firstcode = oldcode = GetCode(src, code_size, FALSE); + } while (firstcode == clear_code); + return firstcode; + } + if (sp > stack) + return *--sp; + + while ((code = GetCode(src, code_size, FALSE)) >= 0) { + if (code == clear_code) { + for (i = 0; i < clear_code; ++i) { + table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1 << MAX_LWZ_BITS); ++i) + table[0][i] = table[1][i] = 0; + code_size = set_code_size + 1; + max_code_size = 2 * clear_code; + max_code = clear_code + 2; + sp = stack; + firstcode = oldcode = GetCode(src, code_size, FALSE); + return firstcode; + } else if (code == end_code) { + int count; + unsigned char buf[260]; + + if (ZeroDataBlock) + return -2; + + while ((count = GetDataBlock(src, buf)) > 0) + ; + + if (count != 0) { + /* + * pm_message("missing EOD in data stream (common occurence)"); + */ + } + return -2; + } + incode = code; + + if (code >= max_code) { + *sp++ = firstcode; + code = oldcode; + } + while (code >= clear_code) { + *sp++ = table[1][code]; + if (code == table[0][code]) + RWSetMsg("circular table entry BIG ERROR"); + code = table[0][code]; + } + + *sp++ = firstcode = table[1][code]; + + if ((code = max_code) < (1 << MAX_LWZ_BITS)) { + table[0][code] = oldcode; + table[1][code] = firstcode; + ++max_code; + if ((max_code >= max_code_size) && + (max_code_size < (1 << MAX_LWZ_BITS))) { + max_code_size *= 2; + ++code_size; + } + } + oldcode = incode; + + if (sp > stack) + return *--sp; + } + return code; +} + +static Image * +ReadImage(SDL_RWops * src, int len, int height, int cmapSize, + unsigned char cmap[3][MAXCOLORMAPSIZE], + int gray, int interlace, int ignore) +{ + Image *image; + unsigned char c; + int i, v; + int xpos = 0, ypos = 0, pass = 0; + + /* + ** Initialize the compression routines + */ + if (!ReadOK(src, &c, 1)) { + RWSetMsg("EOF / read error on image data"); + return NULL; + } + if (LWZReadByte(src, TRUE, c) < 0) { + RWSetMsg("error reading image"); + return NULL; + } + /* + ** If this is an "uninteresting picture" ignore it. + */ + if (ignore) { + while (LWZReadByte(src, FALSE, c) >= 0) + ; + return NULL; + } + image = ImageNewCmap(len, height, cmapSize); + + for (i = 0; i < cmapSize; i++) + ImageSetCmap(image, i, cmap[CM_RED][i], + cmap[CM_GREEN][i], cmap[CM_BLUE][i]); + + while ((v = LWZReadByte(src, FALSE, c)) >= 0) { +#ifdef USED_BY_SDL + ((Uint8 *)image->pixels)[xpos + ypos * image->pitch] = v; +#else + image->data[xpos + ypos * len] = v; +#endif + ++xpos; + if (xpos == len) { + xpos = 0; + if (interlace) { + switch (pass) { + case 0: + case 1: + ypos += 8; + break; + case 2: + ypos += 4; + break; + case 3: + ypos += 2; + break; + } + + if (ypos >= height) { + ++pass; + switch (pass) { + case 1: + ypos = 4; + break; + case 2: + ypos = 2; + break; + case 3: + ypos = 1; + break; + default: + goto fini; + } + } + } else { + ++ypos; + } + } + if (ypos >= height) + break; + } + + fini: + + return image; +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isGIF(SDL_RWops *src) +{ + return(0); +} + +/* Load a GIF type image from an SDL datasource */ +SDL_Surface *IMG_LoadGIF_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_GIF */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_jpg.c b/IMG_jpg.c new file mode 100644 index 0000000..a84b149 --- /dev/null +++ b/IMG_jpg.c @@ -0,0 +1,493 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a JPEG image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_JPG + +#include + +#ifdef JPEG_TRUE /* MinGW version of jpeg-8.x renamed TRUE to JPEG_TRUE etc. */ + typedef JPEG_boolean boolean; + #define TRUE JPEG_TRUE + #define FALSE JPEG_FALSE +#endif + +/* Define this for fast loading and not as good image quality */ +/*#define FAST_JPEG*/ + +/* Define this for quicker (but less perfect) JPEG identification */ +#define FAST_IS_JPEG + +static struct { + int loaded; + void *handle; + void (*jpeg_calc_output_dimensions) (j_decompress_ptr cinfo); + void (*jpeg_CreateDecompress) (j_decompress_ptr cinfo, int version, size_t structsize); + void (*jpeg_destroy_decompress) (j_decompress_ptr cinfo); + boolean (*jpeg_finish_decompress) (j_decompress_ptr cinfo); + int (*jpeg_read_header) (j_decompress_ptr cinfo, boolean require_image); + JDIMENSION (*jpeg_read_scanlines) (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines); + boolean (*jpeg_resync_to_restart) (j_decompress_ptr cinfo, int desired); + boolean (*jpeg_start_decompress) (j_decompress_ptr cinfo); + struct jpeg_error_mgr * (*jpeg_std_error) (struct jpeg_error_mgr * err); +} lib; + +#ifdef LOAD_JPG_DYNAMIC +int IMG_InitJPG() +{ + if ( lib.loaded == 0 ) { + lib.handle = SDL_LoadObject(LOAD_JPG_DYNAMIC); + if ( lib.handle == NULL ) { + return -1; + } + lib.jpeg_calc_output_dimensions = + (void (*) (j_decompress_ptr)) + SDL_LoadFunction(lib.handle, "jpeg_calc_output_dimensions"); + if ( lib.jpeg_calc_output_dimensions == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_CreateDecompress = + (void (*) (j_decompress_ptr, int, size_t)) + SDL_LoadFunction(lib.handle, "jpeg_CreateDecompress"); + if ( lib.jpeg_CreateDecompress == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_destroy_decompress = + (void (*) (j_decompress_ptr)) + SDL_LoadFunction(lib.handle, "jpeg_destroy_decompress"); + if ( lib.jpeg_destroy_decompress == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_finish_decompress = + (boolean (*) (j_decompress_ptr)) + SDL_LoadFunction(lib.handle, "jpeg_finish_decompress"); + if ( lib.jpeg_finish_decompress == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_read_header = + (int (*) (j_decompress_ptr, boolean)) + SDL_LoadFunction(lib.handle, "jpeg_read_header"); + if ( lib.jpeg_read_header == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_read_scanlines = + (JDIMENSION (*) (j_decompress_ptr, JSAMPARRAY, JDIMENSION)) + SDL_LoadFunction(lib.handle, "jpeg_read_scanlines"); + if ( lib.jpeg_read_scanlines == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_resync_to_restart = + (boolean (*) (j_decompress_ptr, int)) + SDL_LoadFunction(lib.handle, "jpeg_resync_to_restart"); + if ( lib.jpeg_resync_to_restart == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_start_decompress = + (boolean (*) (j_decompress_ptr)) + SDL_LoadFunction(lib.handle, "jpeg_start_decompress"); + if ( lib.jpeg_start_decompress == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.jpeg_std_error = + (struct jpeg_error_mgr * (*) (struct jpeg_error_mgr *)) + SDL_LoadFunction(lib.handle, "jpeg_std_error"); + if ( lib.jpeg_std_error == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + } + ++lib.loaded; + + return 0; +} +void IMG_QuitJPG() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + SDL_UnloadObject(lib.handle); + } + --lib.loaded; +} +#else +int IMG_InitJPG() +{ + if ( lib.loaded == 0 ) { + lib.jpeg_calc_output_dimensions = jpeg_calc_output_dimensions; + lib.jpeg_CreateDecompress = jpeg_CreateDecompress; + lib.jpeg_destroy_decompress = jpeg_destroy_decompress; + lib.jpeg_finish_decompress = jpeg_finish_decompress; + lib.jpeg_read_header = jpeg_read_header; + lib.jpeg_read_scanlines = jpeg_read_scanlines; + lib.jpeg_resync_to_restart = jpeg_resync_to_restart; + lib.jpeg_start_decompress = jpeg_start_decompress; + lib.jpeg_std_error = jpeg_std_error; + } + ++lib.loaded; + + return 0; +} +void IMG_QuitJPG() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + } + --lib.loaded; +} +#endif /* LOAD_JPG_DYNAMIC */ + +/* See if an image is contained in a data source */ +int IMG_isJPG(SDL_RWops *src) +{ + int start; + int is_JPG; + int in_scan; + Uint8 magic[4]; + + /* This detection code is by Steaphan Greene */ + /* Blame me, not Sam, if this doesn't work right. */ + /* And don't forget to report the problem to the the sdl list too! */ + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_JPG = 0; + in_scan = 0; + if ( SDL_RWread(src, magic, 2, 1) ) { + if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) { + is_JPG = 1; + while (is_JPG == 1) { + if(SDL_RWread(src, magic, 1, 2) != 2) { + is_JPG = 0; + } else if( (magic[0] != 0xFF) && (in_scan == 0) ) { + is_JPG = 0; + } else if( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) { + /* Extra padding in JPEG (legal) */ + /* or this is data and we are scanning */ + SDL_RWseek(src, -1, RW_SEEK_CUR); + } else if(magic[1] == 0xD9) { + /* Got to end of good JPEG */ + break; + } else if( (in_scan == 1) && (magic[1] == 0x00) ) { + /* This is an encoded 0xFF within the data */ + } else if( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) { + /* These have nothing else */ + } else if(SDL_RWread(src, magic+2, 1, 2) != 2) { + is_JPG = 0; + } else { + /* Yes, it's big-endian */ + Uint32 start; + Uint32 size; + Uint32 end; + start = SDL_RWtell(src); + size = (magic[2] << 8) + magic[3]; + end = SDL_RWseek(src, size-2, RW_SEEK_CUR); + if ( end != start + size - 2 ) is_JPG = 0; + if ( magic[1] == 0xDA ) { + /* Now comes the actual JPEG meat */ +#ifdef FAST_IS_JPEG + /* Ok, I'm convinced. It is a JPEG. */ + break; +#else + /* I'm not convinced. Prove it! */ + in_scan = 1; +#endif + } + } + } + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_JPG); +} + +#define INPUT_BUFFER_SIZE 4096 +typedef struct { + struct jpeg_source_mgr pub; + + SDL_RWops *ctx; + Uint8 buffer[INPUT_BUFFER_SIZE]; +} my_source_mgr; + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ +static void init_source (j_decompress_ptr cinfo) +{ + /* We don't actually need to do anything */ + return; +} + +/* + * Fill the input buffer --- called whenever buffer is emptied. + */ +static boolean fill_input_buffer (j_decompress_ptr cinfo) +{ + my_source_mgr * src = (my_source_mgr *) cinfo->src; + int nbytes; + + nbytes = SDL_RWread(src->ctx, src->buffer, 1, INPUT_BUFFER_SIZE); + if (nbytes <= 0) { + /* Insert a fake EOI marker */ + src->buffer[0] = (Uint8) 0xFF; + src->buffer[1] = (Uint8) JPEG_EOI; + nbytes = 2; + } + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ +static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_source_mgr * src = (my_source_mgr *) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) src->pub.fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never + * return FALSE, so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. + */ +static void term_source (j_decompress_ptr cinfo) +{ + /* We don't actually need to do anything */ + return; +} + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ +static void jpeg_SDL_RW_src (j_decompress_ptr cinfo, SDL_RWops *ctx) +{ + my_source_mgr *src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(my_source_mgr)); + src = (my_source_mgr *) cinfo->src; + } + + src = (my_source_mgr *) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = lib.jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->ctx = ctx; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} + +struct my_error_mgr { + struct jpeg_error_mgr errmgr; + jmp_buf escape; +}; + +static void my_error_exit(j_common_ptr cinfo) +{ + struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err; + longjmp(err->escape, 1); +} + +static void output_no_message(j_common_ptr cinfo) +{ + /* do nothing */ +} + +/* Load a JPEG type image from an SDL datasource */ +SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) +{ + int start; + struct jpeg_decompress_struct cinfo; + JSAMPROW rowptr[1]; + SDL_Surface *volatile surface = NULL; + struct my_error_mgr jerr; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + if ( !IMG_Init(IMG_INIT_JPG) ) { + return NULL; + } + + /* Create a decompression structure and load the JPEG header */ + cinfo.err = lib.jpeg_std_error(&jerr.errmgr); + jerr.errmgr.error_exit = my_error_exit; + jerr.errmgr.output_message = output_no_message; + if(setjmp(jerr.escape)) { + /* If we get here, libjpeg found an error */ + lib.jpeg_destroy_decompress(&cinfo); + if ( surface != NULL ) { + SDL_FreeSurface(surface); + } + SDL_RWseek(src, start, RW_SEEK_SET); + IMG_SetError("JPEG loading error"); + return NULL; + } + + lib.jpeg_create_decompress(&cinfo); + jpeg_SDL_RW_src(&cinfo, src); + lib.jpeg_read_header(&cinfo, TRUE); + + if(cinfo.num_components == 4) { + /* Set 32-bit Raw output */ + cinfo.out_color_space = JCS_CMYK; + cinfo.quantize_colors = FALSE; + lib.jpeg_calc_output_dimensions(&cinfo); + + /* Allocate an output surface to hold the image */ + surface = SDL_AllocSurface(SDL_SWSURFACE, + cinfo.output_width, cinfo.output_height, 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); +#else + 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF); +#endif + } else { + /* Set 24-bit RGB output */ + cinfo.out_color_space = JCS_RGB; + cinfo.quantize_colors = FALSE; +#ifdef FAST_JPEG + cinfo.scale_num = 1; + cinfo.scale_denom = 1; + cinfo.dct_method = JDCT_FASTEST; + cinfo.do_fancy_upsampling = FALSE; +#endif + lib.jpeg_calc_output_dimensions(&cinfo); + + /* Allocate an output surface to hold the image */ + surface = SDL_AllocSurface(SDL_SWSURFACE, + cinfo.output_width, cinfo.output_height, 24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x0000FF, 0x00FF00, 0xFF0000, +#else + 0xFF0000, 0x00FF00, 0x0000FF, +#endif + 0); + } + + if ( surface == NULL ) { + lib.jpeg_destroy_decompress(&cinfo); + SDL_RWseek(src, start, RW_SEEK_SET); + IMG_SetError("Out of memory"); + return NULL; + } + + /* Decompress the image */ + lib.jpeg_start_decompress(&cinfo); + while ( cinfo.output_scanline < cinfo.output_height ) { + rowptr[0] = (JSAMPROW)(Uint8 *)surface->pixels + + cinfo.output_scanline * surface->pitch; + lib.jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1); + } + lib.jpeg_finish_decompress(&cinfo); + lib.jpeg_destroy_decompress(&cinfo); + + return(surface); +} + +#else + +int IMG_InitJPG() +{ + IMG_SetError("JPEG images are not supported"); + return(-1); +} + +void IMG_QuitJPG() +{ +} + +/* See if an image is contained in a data source */ +int IMG_isJPG(SDL_RWops *src) +{ + return(0); +} + +/* Load a JPEG type image from an SDL datasource */ +SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_JPG */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_lbm.c b/IMG_lbm.c new file mode 100644 index 0000000..12304b0 --- /dev/null +++ b/IMG_lbm.c @@ -0,0 +1,501 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a ILBM image file loading framework + Load IFF pictures, PBM & ILBM packing methods, with or without stencil + Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001. + 24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati) + in December 2002. + EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain + (http://www.multimania.com/mavati) in December 2003. + Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004. + Buffer overflow fix in RLE decompression by David Raulo in January 2008. +*/ + +#include + +#include "SDL/SDL_endian.h" +#include "SDL/SDL_image.h" + +#ifdef LOAD_LBM + + +#define MAXCOLORS 256 + +/* Structure for an IFF picture ( BMHD = Bitmap Header ) */ + +typedef struct +{ + Uint16 w, h; /* width & height of the bitmap in pixels */ + Sint16 x, y; /* screen coordinates of the bitmap */ + Uint8 planes; /* number of planes of the bitmap */ + Uint8 mask; /* mask type ( 0 => no mask ) */ + Uint8 tcomp; /* compression type */ + Uint8 pad1; /* dummy value, for padding */ + Uint16 tcolor; /* transparent color */ + Uint8 xAspect, /* pixel aspect ratio */ + yAspect; + Sint16 Lpage; /* width of the screen in pixels */ + Sint16 Hpage; /* height of the screen in pixels */ +} BMHD; + +int IMG_isLBM( SDL_RWops *src ) +{ + int start; + int is_LBM; + Uint8 magic[4+4+4]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_LBM = 0; + if ( SDL_RWread( src, magic, sizeof(magic), 1 ) ) + { + if ( !memcmp( magic, "FORM", 4 ) && + ( !memcmp( magic + 8, "PBM ", 4 ) || + !memcmp( magic + 8, "ILBM", 4 ) ) ) + { + is_LBM = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return( is_LBM ); +} + +SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src ) +{ + int start; + SDL_Surface *Image; + Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk; + Uint32 size, bytesloaded, nbcolors; + Uint32 i, j, bytesperline, nbplanes, stencil, plane, h; + Uint32 remainingbytes; + Uint32 width; + BMHD bmhd; + char *error; + Uint8 flagHAM,flagEHB; + + Image = NULL; + error = NULL; + MiniBuf = NULL; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + /* Should be the size of the file minus 4+4 ( 'FORM'+size ) */ + if ( !SDL_RWread( src, &size, 4, 1 ) ) + { + error="error reading IFF chunk size"; + goto done; + } + + /* As size is not used here, no need to swap it */ + + if ( memcmp( id, "FORM", 4 ) != 0 ) + { + error="not a IFF file"; + goto done; + } + + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + pbm = 0; + + /* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */ + if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1; + else if ( memcmp( id, "ILBM", 4 ) ) + { + error="not a IFF picture"; + goto done; + } + + nbcolors = 0; + + memset( &bmhd, 0, sizeof( BMHD ) ); + flagHAM = 0; + flagEHB = 0; + + while ( memcmp( id, "BODY", 4 ) != 0 ) + { + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + if ( !SDL_RWread( src, &size, 4, 1 ) ) + { + error="error reading IFF chunk size"; + goto done; + } + + bytesloaded = 0; + + size = SDL_SwapBE32( size ); + + if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */ + { + if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) ) + { + error="error reading BMHD chunk"; + goto done; + } + + bytesloaded = sizeof( BMHD ); + + bmhd.w = SDL_SwapBE16( bmhd.w ); + bmhd.h = SDL_SwapBE16( bmhd.h ); + bmhd.x = SDL_SwapBE16( bmhd.x ); + bmhd.y = SDL_SwapBE16( bmhd.y ); + bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor ); + bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage ); + bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage ); + } + + if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */ + { + if ( !SDL_RWread( src, &colormap, size, 1 ) ) + { + error="error reading CMAP chunk"; + goto done; + } + + bytesloaded = size; + nbcolors = size / 3; + } + + if ( !memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */ + { + Uint32 viewmodes; + if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) ) + { + error="error reading CAMG chunk"; + goto done; + } + + bytesloaded = size; + viewmodes = SDL_SwapBE32( viewmodes ); + if ( viewmodes & 0x0800 ) + flagHAM = 1; + if ( viewmodes & 0x0080 ) + flagEHB = 1; + } + + if ( memcmp( id, "BODY", 4 ) ) + { + if ( size & 1 ) ++size; /* padding ! */ + size -= bytesloaded; + /* skip the remaining bytes of this chunk */ + if ( size ) SDL_RWseek( src, size, RW_SEEK_CUR ); + } + } + + /* compute some usefull values, based on the bitmap header */ + + width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */ + + bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2; + + nbplanes = bmhd.planes; + + if ( pbm ) /* File format : 'Packed Bitmap' */ + { + bytesperline *= 8; + nbplanes = 1; + } + + stencil = (bmhd.mask & 1); /* There is a mask ( 'stencil' ) */ + + /* Allocate memory for a temporary buffer ( used for + decompression/deinterleaving ) */ + + MiniBuf = (void *)malloc( bytesperline * (nbplanes + stencil) ); + if ( MiniBuf == NULL ) + { + error="no enough memory for temporary buffer"; + goto done; + } + + if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, (bmhd.planes==24 || flagHAM==1)?24:8, 0, 0, 0, 0 ) ) == NULL ) + goto done; + + if ( bmhd.mask & 2 ) /* There is a transparent color */ + SDL_SetColorKey( Image, SDL_SRCCOLORKEY, bmhd.tcolor ); + + /* Update palette informations */ + + /* There is no palette in 24 bits ILBM file */ + if ( nbcolors>0 && flagHAM==0 ) + { + /* FIXME: Should this include the stencil? See comment below */ + int nbrcolorsfinal = 1 << (nbplanes + stencil); + ptr = &colormap[0]; + + for ( i=0; iformat->palette->colors[i].r = *ptr++; + Image->format->palette->colors[i].g = *ptr++; + Image->format->palette->colors[i].b = *ptr++; + } + + /* Amiga EHB mode (Extra-Half-Bright) */ + /* 6 bitplanes mode with a 32 colors palette */ + /* The 32 last colors are the same but divided by 2 */ + /* Some Amiga pictures save 64 colors with 32 last wrong colors, */ + /* they shouldn't !, and here we overwrite these 32 bad colors. */ + if ( (nbcolors==32 || flagEHB ) && (1<format->palette->colors[i].r = (*ptr++)/2; + Image->format->palette->colors[i].g = (*ptr++)/2; + Image->format->palette->colors[i].b = (*ptr++)/2; + } + } + + /* If nbcolors < 2^nbplanes, repeat the colormap */ + /* This happens when pictures have a stencil mask */ + if ( nbrcolorsfinal > (1<format->palette->colors[i].r = Image->format->palette->colors[i%nbcolors].r; + Image->format->palette->colors[i].g = Image->format->palette->colors[i%nbcolors].g; + Image->format->palette->colors[i].b = Image->format->palette->colors[i%nbcolors].b; + } + if ( !pbm ) + Image->format->palette->ncolors = nbrcolorsfinal; + } + + /* Get the bitmap */ + + for ( h=0; h < bmhd.h; h++ ) + { + /* uncompress the datas of each planes */ + + for ( plane=0; plane < (nbplanes+stencil); plane++ ) + { + ptr = MiniBuf + ( plane * bytesperline ); + + remainingbytes = bytesperline; + + if ( bmhd.tcomp == 1 ) /* Datas are compressed */ + { + do + { + if ( !SDL_RWread( src, &count, 1, 1 ) ) + { + error="error reading BODY chunk"; + goto done; + } + + if ( count & 0x80 ) + { + count ^= 0xFF; + count += 2; /* now it */ + + if ( ( count > remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) ) + { + error="error reading BODY chunk"; + goto done; + } + memset( ptr, color, count ); + } + else + { + ++count; + + if ( ( count > remainingbytes ) || !SDL_RWread( src, ptr, count, 1 ) ) + { + error="error reading BODY chunk"; + goto done; + } + } + + ptr += count; + remainingbytes -= count; + + } while ( remainingbytes > 0 ); + } + else + { + if ( !SDL_RWread( src, ptr, bytesperline, 1 ) ) + { + error="error reading BODY chunk"; + goto done; + } + } + } + + /* One line has been read, store it ! */ + + ptr = Image->pixels; + if ( nbplanes==24 || flagHAM==1 ) + ptr += h * width * 3; + else + ptr += h * width; + + if ( pbm ) /* File format : 'Packed Bitmap' */ + { + memcpy( ptr, MiniBuf, width ); + } + else /* We have to un-interlace the bits ! */ + { + if ( nbplanes!=24 && flagHAM==0 ) + { + size = ( width + 7 ) / 8; + + for ( i=0; i < size; i++ ) + { + memset( ptr, 0, 8 ); + + for ( plane=0; plane < (nbplanes + stencil); plane++ ) + { + color = *( MiniBuf + i + ( plane * bytesperline ) ); + msk = 0x80; + + for ( j=0; j<8; j++ ) + { + if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j ); + else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 ); + + msk >>= 1; + } + } + ptr += 8; + } + } + else + { + Uint32 finalcolor = 0; + size = ( width + 7 ) / 8; + /* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */ + /* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */ + for ( i=0; i>(nbplanes-2) ) + { + case 0: /* take direct color from palette */ + finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16); + break; + case 1: /* modify only blue component */ + finalcolor = finalcolor&0x00FFFF; + finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes))); + break; + case 2: /* modify only red component */ + finalcolor = finalcolor&0xFFFF00; + finalcolor = finalcolor | pixelcolor<<(10-nbplanes); + break; + case 3: /* modify only green component */ + finalcolor = finalcolor&0xFF00FF; + finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes))); + break; + } + } + else + { + finalcolor = pixelcolor; + } + if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) + { + *ptr++ = (Uint8)(finalcolor>>16); + *ptr++ = (Uint8)(finalcolor>>8); + *ptr++ = (Uint8)(finalcolor); + } + else + { + *ptr++ = (Uint8)(finalcolor); + *ptr++ = (Uint8)(finalcolor>>8); + *ptr++ = (Uint8)(finalcolor>>16); + } + + maskBit = maskBit>>1; + } + } + } + } + } + +done: + + if ( MiniBuf ) free( MiniBuf ); + + if ( error ) + { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( Image ) { + SDL_FreeSurface( Image ); + Image = NULL; + } + IMG_SetError( error ); + } + + return( Image ); +} + +#else /* LOAD_LBM */ + +/* See if an image is contained in a data source */ +int IMG_isLBM(SDL_RWops *src) +{ + return(0); +} + +/* Load an IFF type image from an SDL datasource */ +SDL_Surface *IMG_LoadLBM_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_LBM */ diff --git a/IMG_pcx.c b/IMG_pcx.c new file mode 100644 index 0000000..3af20be --- /dev/null +++ b/IMG_pcx.c @@ -0,0 +1,275 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * PCX file reader: + * Supports: + * 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel) + * 8 bits/pixel in single-planar format (8 bits/plane/pixel) + * 24 bits/pixel in 3-plane format (8 bits/plane/pixel) + * + * (The <8bpp formats are expanded to 8bpp surfaces) + * + * Doesn't support: + * single-planar packed-pixel formats other than 8bpp + * 4-plane 32bpp format with a fourth "intensity" plane + */ +#include + +#include "SDL/SDL_endian.h" + +#include "SDL/SDL_image.h" + +#ifdef LOAD_PCX + +struct PCXheader { + Uint8 Manufacturer; + Uint8 Version; + Uint8 Encoding; + Uint8 BitsPerPixel; + Sint16 Xmin, Ymin, Xmax, Ymax; + Sint16 HDpi, VDpi; + Uint8 Colormap[48]; + Uint8 Reserved; + Uint8 NPlanes; + Sint16 BytesPerLine; + Sint16 PaletteInfo; + Sint16 HscreenSize; + Sint16 VscreenSize; + Uint8 Filler[54]; +}; + +/* See if an image is contained in a data source */ +int IMG_isPCX(SDL_RWops *src) +{ + int start; + int is_PCX; + const int ZSoft_Manufacturer = 10; + const int PC_Paintbrush_Version = 5; + const int PCX_Uncompressed_Encoding = 0; + const int PCX_RunLength_Encoding = 1; + struct PCXheader pcxh; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_PCX = 0; + if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) { + if ( (pcxh.Manufacturer == ZSoft_Manufacturer) && + (pcxh.Version == PC_Paintbrush_Version) && + (pcxh.Encoding == PCX_RunLength_Encoding || + pcxh.Encoding == PCX_Uncompressed_Encoding) ) { + is_PCX = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_PCX); +} + +/* Load a PCX type image from an SDL datasource */ +SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) +{ + int start; + struct PCXheader pcxh; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; + SDL_Surface *surface = NULL; + int width, height; + int y, bpl; + Uint8 *row, *buf = NULL; + char *error = NULL; + int bits, src_bits; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) { + error = "file truncated"; + goto done; + } + pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin); + pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin); + pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax); + pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax); + pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine); + + /* Create the surface of the appropriate type */ + width = (pcxh.Xmax - pcxh.Xmin) + 1; + height = (pcxh.Ymax - pcxh.Ymin) + 1; + Rmask = Gmask = Bmask = Amask = 0; + src_bits = pcxh.BitsPerPixel * pcxh.NPlanes; + if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4) + || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) { + bits = 8; + } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) { + bits = 24; + if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + } else { + Rmask = 0xFF0000; + Gmask = 0x00FF00; + Bmask = 0x0000FF; + } + } else { + error = "unsupported PCX format"; + goto done; + } + surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, + bits, Rmask, Gmask, Bmask, Amask); + if ( surface == NULL ) + goto done; + + bpl = pcxh.NPlanes * pcxh.BytesPerLine; + if (bpl > surface->pitch) { + error = "bytes per line is too large (corrupt?)"; + } + buf = malloc(bpl); + row = surface->pixels; + for ( y=0; yh; ++y ) { + /* decode a scan line to a temporary buffer first */ + int i, count = 0; + Uint8 ch; + Uint8 *dst = (src_bits == 8) ? row : buf; + if ( pcxh.Encoding == 0 ) { + if(!SDL_RWread(src, dst, bpl, 1)) { + error = "file truncated"; + goto done; + } + } else { + for(i = 0; i < bpl; i++) { + if(!count) { + if(!SDL_RWread(src, &ch, 1, 1)) { + error = "file truncated"; + goto done; + } + if( (ch & 0xc0) == 0xc0) { + count = ch & 0x3f; + if(!SDL_RWread(src, &ch, 1, 1)) { + error = "file truncated"; + goto done; + } + } else + count = 1; + } + dst[i] = ch; + count--; + } + } + + if(src_bits <= 4) { + /* expand planes to 1 byte/pixel */ + Uint8 *src = buf; + int plane; + for(plane = 0; plane < pcxh.NPlanes; plane++) { + int i, j, x = 0; + for(i = 0; i < pcxh.BytesPerLine; i++) { + Uint8 byte = *src++; + for(j = 7; j >= 0; j--) { + unsigned bit = (byte >> j) & 1; + /* skip padding bits */ + if (i * 8 + j >= width) + continue; + row[x++] |= bit << plane; + } + } + } + } else if(src_bits == 24) { + /* de-interlace planes */ + Uint8 *src = buf; + int plane; + for(plane = 0; plane < pcxh.NPlanes; plane++) { + int x; + dst = row + plane; + for(x = 0; x < width; x++) { + *dst = *src++; + dst += pcxh.NPlanes; + } + } + } + + row += surface->pitch; + } + + if(bits == 8) { + SDL_Color *colors = surface->format->palette->colors; + int nc = 1 << src_bits; + int i; + + surface->format->palette->ncolors = nc; + if(src_bits == 8) { + Uint8 ch; + /* look for a 256-colour palette */ + do { + if ( !SDL_RWread(src, &ch, 1, 1)) { + error = "file truncated"; + goto done; + } + } while ( ch != 12 ); + + for(i = 0; i < 256; i++) { + SDL_RWread(src, &colors[i].r, 1, 1); + SDL_RWread(src, &colors[i].g, 1, 1); + SDL_RWread(src, &colors[i].b, 1, 1); + } + } else { + for(i = 0; i < nc; i++) { + colors[i].r = pcxh.Colormap[i * 3]; + colors[i].g = pcxh.Colormap[i * 3 + 1]; + colors[i].b = pcxh.Colormap[i * 3 + 2]; + } + } + } + +done: + free(buf); + if ( error ) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + return(surface); +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isPCX(SDL_RWops *src) +{ + return(0); +} + +/* Load a PCX type image from an SDL datasource */ +SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_PCX */ diff --git a/IMG_png.c b/IMG_png.c new file mode 100644 index 0000000..c6c785f --- /dev/null +++ b/IMG_png.c @@ -0,0 +1,601 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a PNG image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_PNG + +/*============================================================================= + File: SDL_png.c + Purpose: A PNG loader and saver for the SDL library + Revision: + Created by: Philippe Lavoie (2 November 1998) + lavoie@zeus.genie.uottawa.ca + Modified by: + + Copyright notice: + Copyright (C) 1998 Philippe Lavoie + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Comments: The load and save routine are basically the ones you can find + in the example.c file from the libpng distribution. + + Changes: + 5/17/99 - Modified to use the new SDL data sources - Sam Lantinga + +=============================================================================*/ + +#include "SDL/SDL_endian.h" + +#ifdef macintosh +#define MACOS +#endif +#include + +/* Check for the older version of libpng */ +#if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR < 4) +#define LIBPNG_VERSION_12 +#endif + +static struct { + int loaded; + void *handle; + png_infop (*png_create_info_struct) (png_structp png_ptr); + png_structp (*png_create_read_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn); + void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr); + png_uint_32 (*png_get_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method); + png_voidp (*png_get_io_ptr) (png_structp png_ptr); + png_byte (*png_get_channels) (png_structp png_ptr, png_infop info_ptr); + png_uint_32 (*png_get_PLTE) (png_structp png_ptr, png_infop info_ptr, png_colorp *palette, int *num_palette); + png_uint_32 (*png_get_tRNS) (png_structp png_ptr, png_infop info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values); + png_uint_32 (*png_get_valid) (png_structp png_ptr, png_infop info_ptr, png_uint_32 flag); + void (*png_read_image) (png_structp png_ptr, png_bytepp image); + void (*png_read_info) (png_structp png_ptr, png_infop info_ptr); + void (*png_read_update_info) (png_structp png_ptr, png_infop info_ptr); + void (*png_set_expand) (png_structp png_ptr); + void (*png_set_gray_to_rgb) (png_structp png_ptr); + void (*png_set_packing) (png_structp png_ptr); + void (*png_set_read_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn); + void (*png_set_strip_16) (png_structp png_ptr); + int (*png_sig_cmp) (png_bytep sig, png_size_t start, png_size_t num_to_check); +#ifndef LIBPNG_VERSION_12 + jmp_buf* (*png_set_longjmp_fn) (png_structp, png_longjmp_ptr, size_t); +#endif +} lib; + +#ifdef LOAD_PNG_DYNAMIC +int IMG_InitPNG() +{ + if ( lib.loaded == 0 ) { + lib.handle = SDL_LoadObject(LOAD_PNG_DYNAMIC); + if ( lib.handle == NULL ) { + return -1; + } + lib.png_create_info_struct = + (png_infop (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_create_info_struct"); + if ( lib.png_create_info_struct == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_create_read_struct = + (png_structp (*) (png_const_charp, png_voidp, png_error_ptr, png_error_ptr)) + SDL_LoadFunction(lib.handle, "png_create_read_struct"); + if ( lib.png_create_read_struct == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_destroy_read_struct = + (void (*) (png_structpp, png_infopp, png_infopp)) + SDL_LoadFunction(lib.handle, "png_destroy_read_struct"); + if ( lib.png_destroy_read_struct == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_IHDR = + (png_uint_32 (*) (png_structp, png_infop, png_uint_32 *, png_uint_32 *, int *, int *, int *, int *, int *)) + SDL_LoadFunction(lib.handle, "png_get_IHDR"); + if ( lib.png_get_IHDR == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_channels = + (png_byte (*) (png_structp, png_infop)) + SDL_LoadFunction(lib.handle, "png_get_channels"); + if ( lib.png_get_channels == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_io_ptr = + (png_voidp (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_get_io_ptr"); + if ( lib.png_get_io_ptr == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_PLTE = + (png_uint_32 (*) (png_structp, png_infop, png_colorp *, int *)) + SDL_LoadFunction(lib.handle, "png_get_PLTE"); + if ( lib.png_get_PLTE == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_tRNS = + (png_uint_32 (*) (png_structp, png_infop, png_bytep *, int *, png_color_16p *)) + SDL_LoadFunction(lib.handle, "png_get_tRNS"); + if ( lib.png_get_tRNS == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_get_valid = + (png_uint_32 (*) (png_structp, png_infop, png_uint_32)) + SDL_LoadFunction(lib.handle, "png_get_valid"); + if ( lib.png_get_valid == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_read_image = + (void (*) (png_structp, png_bytepp)) + SDL_LoadFunction(lib.handle, "png_read_image"); + if ( lib.png_read_image == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_read_info = + (void (*) (png_structp, png_infop)) + SDL_LoadFunction(lib.handle, "png_read_info"); + if ( lib.png_read_info == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_read_update_info = + (void (*) (png_structp, png_infop)) + SDL_LoadFunction(lib.handle, "png_read_update_info"); + if ( lib.png_read_update_info == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_set_expand = + (void (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_set_expand"); + if ( lib.png_set_expand == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_set_gray_to_rgb = + (void (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_set_gray_to_rgb"); + if ( lib.png_set_gray_to_rgb == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_set_packing = + (void (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_set_packing"); + if ( lib.png_set_packing == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_set_read_fn = + (void (*) (png_structp, png_voidp, png_rw_ptr)) + SDL_LoadFunction(lib.handle, "png_set_read_fn"); + if ( lib.png_set_read_fn == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_set_strip_16 = + (void (*) (png_structp)) + SDL_LoadFunction(lib.handle, "png_set_strip_16"); + if ( lib.png_set_strip_16 == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.png_sig_cmp = + (int (*) (png_bytep, png_size_t, png_size_t)) + SDL_LoadFunction(lib.handle, "png_sig_cmp"); + if ( lib.png_sig_cmp == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } +#ifndef LIBPNG_VERSION_12 + lib.png_set_longjmp_fn = + (jmp_buf * (*) (png_structp, png_longjmp_ptr, size_t)) + SDL_LoadFunction(lib.handle, "png_set_longjmp_fn"); + if ( lib.png_set_longjmp_fn == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } +#endif + } + ++lib.loaded; + + return 0; +} +void IMG_QuitPNG() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + SDL_UnloadObject(lib.handle); + } + --lib.loaded; +} +#else +int IMG_InitPNG() +{ + if ( lib.loaded == 0 ) { + lib.png_create_info_struct = png_create_info_struct; + lib.png_create_read_struct = png_create_read_struct; + lib.png_destroy_read_struct = png_destroy_read_struct; + lib.png_get_IHDR = png_get_IHDR; + lib.png_get_channels = png_get_channels; + lib.png_get_io_ptr = png_get_io_ptr; + lib.png_get_PLTE = png_get_PLTE; + lib.png_get_tRNS = png_get_tRNS; + lib.png_get_valid = png_get_valid; + lib.png_read_image = png_read_image; + lib.png_read_info = png_read_info; + lib.png_read_update_info = png_read_update_info; + lib.png_set_expand = png_set_expand; + lib.png_set_gray_to_rgb = png_set_gray_to_rgb; + lib.png_set_packing = png_set_packing; + lib.png_set_read_fn = png_set_read_fn; + lib.png_set_strip_16 = png_set_strip_16; + lib.png_sig_cmp = png_sig_cmp; +#ifndef LIBPNG_VERSION_12 + lib.png_set_longjmp_fn = png_set_longjmp_fn; +#endif + } + ++lib.loaded; + + return 0; +} +void IMG_QuitPNG() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + } + --lib.loaded; +} +#endif /* LOAD_PNG_DYNAMIC */ + +/* See if an image is contained in a data source */ +int IMG_isPNG(SDL_RWops *src) +{ + int start; + int is_PNG; + Uint8 magic[4]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_PNG = 0; + if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) { + if ( magic[0] == 0x89 && + magic[1] == 'P' && + magic[2] == 'N' && + magic[3] == 'G' ) { + is_PNG = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_PNG); +} + +/* Load a PNG type image from an SDL datasource */ +static void png_read_data(png_structp ctx, png_bytep area, png_size_t size) +{ + SDL_RWops *src; + + src = (SDL_RWops *)lib.png_get_io_ptr(ctx); + SDL_RWread(src, area, size, 1); +} +SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) +{ + cSDL_LogToFile( "IMG_LoadPNG_RW : I am in the CORRECT function !!! !!!" ); + + int start; + const char *error; + SDL_Surface *volatile surface; + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type, num_channels; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; + SDL_Palette *palette; + png_bytep *volatile row_pointers; + int row, i; + volatile int ckey = -1; + png_color_16 *transv; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + cSDL_LogToFile( "IMG_LoadPNG_RW : point 1 : src is NULL !!!" ); + return NULL; + } + start = SDL_RWtell(src); + cSDL_LogToFile( "IMG_LoadPNG_RW : point2 : start = %d", start ); + + + if ( !IMG_Init(IMG_INIT_PNG) ) { + cSDL_LogToFile( "IMG_LoadPNG_RW : point3 - IMG_Init Failure" ); + return NULL; + } + + /* Initialize the data we will clean up when we're done */ + error = NULL; + png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL; + + /* Create the PNG loading context structure */ + png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL,NULL,NULL); + if (png_ptr == NULL){ + cSDL_LogToFile( "IMG_LoadPNG_RW : point 4 png_ptr is NULL" ); + error = "Couldn't allocate memory for PNG file or incompatible PNG dll"; + goto done; + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = lib.png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + cSDL_LogToFile( "IMG_LoadPNG_RW : point 5 info_ptr is NULL" ); + error = "Couldn't create image information for PNG file"; + goto done; + } + + /* Set error handling if you are using setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in png_create_read_struct() earlier. + */ + + +#ifndef LIBPNG_VERSION_12 + if ( setjmp(*lib.png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))) ) + { + cSDL_LogToFile( "IMG_LoadPNG_RW : point 6.1 LIBPNG VERSION 12" ); + +#else + if ( setjmp(png_ptr->jmpbuf) ) + { + cSDL_LogToFile( "IMG_LoadPNG_RW : point 6.1bis LIBPNG VERSION AUTRE" ); + +#endif + + cSDL_LogToFile( "IMG_LoadPNG_RW : point 6.2 Error reading the PNG file" ); + error = "Error reading the PNG file."; + goto done; + } + + + /* Set up the input control */ + lib.png_set_read_fn(png_ptr, src, png_read_data); + + /* Read PNG header info */ + lib.png_read_info(png_ptr, info_ptr); + lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, NULL, NULL); + + /* tell libpng to strip 16 bit/color files down to 8 bits/color */ + lib.png_set_strip_16(png_ptr) ; + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + lib.png_set_packing(png_ptr); + + /* scale greyscale values to the range 0..255 */ + if(color_type == PNG_COLOR_TYPE_GRAY) + lib.png_set_expand(png_ptr); + + /* For images with a single "transparent colour", set colour key; + if more than one index has transparency, or if partially transparent + entries exist, use full alpha channel */ + if (lib.png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + int num_trans; + Uint8 *trans; + lib.png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, + &transv); + if(color_type == PNG_COLOR_TYPE_PALETTE) { + /* Check if all tRNS entries are opaque except one */ + int i, t = -1; + for(i = 0; i < num_trans; i++) + if(trans[i] == 0) { + if(t >= 0) + break; + t = i; + } else if(trans[i] != 255) + break; + if(i == num_trans) { + /* exactly one transparent index */ + ckey = t; + } else { + /* more than one transparent index, or translucency */ + lib.png_set_expand(png_ptr); + } + } else + ckey = 0; /* actual value will be set later */ + } + + if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) + lib.png_set_gray_to_rgb(png_ptr); + + lib.png_read_update_info(png_ptr, info_ptr); + + lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, NULL, NULL); + + /* Allocate the SDL surface to hold the image */ + Rmask = Gmask = Bmask = Amask = 0 ; + num_channels = lib.png_get_channels(png_ptr, info_ptr); + if ( color_type != PNG_COLOR_TYPE_PALETTE ) { + if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + Amask = (num_channels == 4) ? 0xFF000000 : 0; + } else { + int s = (num_channels == 4) ? 0 : 8; + Rmask = 0xFF000000 >> s; + Gmask = 0x00FF0000 >> s; + Bmask = 0x0000FF00 >> s; + Amask = 0x000000FF >> s; + } + } + surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, + bit_depth*num_channels, Rmask,Gmask,Bmask,Amask); + if ( surface == NULL ) { + cSDL_LogToFile( "IMG_LoadPNG_RW : point 7 impossible to allocate memory to surface" ); + error = "Out of memory"; + goto done; + } + + if(ckey != -1) { + if(color_type != PNG_COLOR_TYPE_PALETTE) + /* FIXME: Should these be truncated or shifted down? */ + ckey = SDL_MapRGB(surface->format, + (Uint8)transv->red, + (Uint8)transv->green, + (Uint8)transv->blue); + SDL_SetColorKey(surface, SDL_SRCCOLORKEY, ckey); + } + + /* Create the array of pointers to image data */ + row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height); + if ( (row_pointers == NULL) ) { + cSDL_LogToFile( "IMG_LoadPNG_RW : point 8 row_pointer is NULL" ); + error = "Out of memory"; + goto done; + } + for (row = 0; row < (int)height; row++) { + row_pointers[row] = (png_bytep) + (Uint8 *)surface->pixels + row*surface->pitch; + } + + /* Read the entire image in one go */ + lib.png_read_image(png_ptr, row_pointers); + + /* and we're done! (png_read_end() can be omitted if no processing of + * post-IDAT text/time/etc. is desired) + * In some cases it can't read PNG's created by some popular programs (ACDSEE), + * we do not want to process comments, so we omit png_read_end + + lib.png_read_end(png_ptr, info_ptr); + */ + + /* Load the palette, if any */ + palette = surface->format->palette; + if ( palette ) { + int png_num_palette; + png_colorp png_palette; + lib.png_get_PLTE(png_ptr, info_ptr, &png_palette, &png_num_palette); + if(color_type == PNG_COLOR_TYPE_GRAY) { + palette->ncolors = 256; + for(i = 0; i < 256; i++) { + palette->colors[i].r = i; + palette->colors[i].g = i; + palette->colors[i].b = i; + } + } else if (png_num_palette > 0 ) { + palette->ncolors = png_num_palette; + for( i=0; icolors[i].b = png_palette[i].blue; + palette->colors[i].g = png_palette[i].green; + palette->colors[i].r = png_palette[i].red; + } + } + } + +done: /* Clean up and return */ + if ( png_ptr ) { + lib.png_destroy_read_struct(&png_ptr, + info_ptr ? &info_ptr : (png_infopp)0, + (png_infopp)0); + } + if ( row_pointers ) { + free(row_pointers); + } + if ( error ) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + + cSDL_LogToFile( "IMG_LoadPNG_RW : point 9 reached the end !!!" ); + + return(surface); +} + +#else + +int IMG_InitPNG() +{ + IMG_SetError("PNG images are not supported"); + return(-1); +} + +void IMG_QuitPNG() +{ +} + +/* See if an image is contained in a data source */ +int IMG_isPNG(SDL_RWops *src) +{ + return(0); +} + +/* Load a PNG type image from an SDL datasource */ +SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) +{ + cSDL_LogToFile( "IMG_LoadPNG_RW : I am in the NULL function !!! !!!" ); + return(NULL); +} + +#endif /* LOAD_PNG */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_pnm.c b/IMG_pnm.c new file mode 100644 index 0000000..9a2c67f --- /dev/null +++ b/IMG_pnm.c @@ -0,0 +1,255 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * PNM (portable anymap) image loader: + * + * Supports: PBM, PGM and PPM, ASCII and binary formats + * (PBM and PGM are loaded as 8bpp surfaces) + * Does not support: maximum component value > 255 + */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_PNM + +/* See if an image is contained in a data source */ +int IMG_isPNM(SDL_RWops *src) +{ + int start; + int is_PNM; + char magic[2]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_PNM = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + /* + * PNM magic signatures: + * P1 PBM, ascii format + * P2 PGM, ascii format + * P3 PPM, ascii format + * P4 PBM, binary format + * P5 PGM, binary format + * P6 PPM, binary format + * P7 PAM, a general wrapper for PNM data + */ + if ( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) { + is_PNM = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_PNM); +} + +/* read a non-negative integer from the source. return -1 upon error */ +static int ReadNumber(SDL_RWops *src) +{ + int number; + unsigned char ch; + + /* Initialize return value */ + number = 0; + + /* Skip leading whitespace */ + do { + if ( ! SDL_RWread(src, &ch, 1, 1) ) { + return(0); + } + /* Eat comments as whitespace */ + if ( ch == '#' ) { /* Comment is '#' to end of line */ + do { + if ( ! SDL_RWread(src, &ch, 1, 1) ) { + return -1; + } + } while ( (ch != '\r') && (ch != '\n') ); + } + } while ( isspace(ch) ); + + /* Add up the number */ + do { + number *= 10; + number += ch-'0'; + + if ( !SDL_RWread(src, &ch, 1, 1) ) { + return -1; + } + } while ( isdigit(ch) ); + + return(number); +} + +SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) +{ + int start; + SDL_Surface *surface = NULL; + int width, height; + int maxval, y, bpl; + Uint8 *row; + Uint8 *buf = NULL; + char *error = NULL; + Uint8 magic[2]; + int ascii; + enum { PBM, PGM, PPM, PAM } kind; + +#define ERROR(s) do { error = (s); goto done; } while(0) + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + SDL_RWread(src, magic, 2, 1); + kind = magic[1] - '1'; + ascii = 1; + if(kind >= 3) { + ascii = 0; + kind -= 3; + } + + width = ReadNumber(src); + height = ReadNumber(src); + if(width <= 0 || height <= 0) + ERROR("Unable to read image width and height"); + + if(kind != PBM) { + maxval = ReadNumber(src); + if(maxval <= 0 || maxval > 255) + ERROR("unsupported PNM format"); + } else + maxval = 255; /* never scale PBMs */ + + /* binary PNM allows just a single character of whitespace after + the last parameter, and we've already consumed it */ + + if(kind == PPM) { + /* 24-bit surface in R,G,B byte order */ + surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000ff, 0x0000ff00, 0x00ff0000, +#else + 0x00ff0000, 0x0000ff00, 0x000000ff, +#endif + 0); + } else { + /* load PBM/PGM as 8-bit indexed images */ + surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, + 0, 0, 0, 0); + } + if ( surface == NULL ) + ERROR("Out of memory"); + bpl = width * surface->format->BytesPerPixel; + if(kind == PGM) { + SDL_Color *c = surface->format->palette->colors; + int i; + for(i = 0; i < 256; i++) + c[i].r = c[i].g = c[i].b = i; + surface->format->palette->ncolors = 256; + } else if(kind == PBM) { + /* for some reason PBM has 1=black, 0=white */ + SDL_Color *c = surface->format->palette->colors; + c[0].r = c[0].g = c[0].b = 255; + c[1].r = c[1].g = c[1].b = 0; + surface->format->palette->ncolors = 2; + bpl = (width + 7) >> 3; + buf = malloc(bpl); + if(buf == NULL) + ERROR("Out of memory"); + } + + /* Read the image into the surface */ + row = surface->pixels; + for(y = 0; y < height; y++) { + if(ascii) { + int i; + if(kind == PBM) { + for(i = 0; i < width; i++) { + Uint8 ch; + do { + if(!SDL_RWread(src, &ch, + 1, 1)) + ERROR("file truncated"); + ch -= '0'; + } while(ch > 1); + row[i] = ch; + } + } else { + for(i = 0; i < bpl; i++) { + int c; + c = ReadNumber(src); + if(c < 0) + ERROR("file truncated"); + row[i] = c; + } + } + } else { + Uint8 *dst = (kind == PBM) ? buf : row; + if(!SDL_RWread(src, dst, bpl, 1)) + ERROR("file truncated"); + if(kind == PBM) { + /* expand bitmap to 8bpp */ + int i; + for(i = 0; i < width; i++) { + int bit = 7 - (i & 7); + row[i] = (buf[i >> 3] >> bit) & 1; + } + } + } + if(maxval < 255) { + /* scale up to full dynamic range (slow) */ + int i; + for(i = 0; i < bpl; i++) + row[i] = row[i] * 255 / maxval; + } + row += surface->pitch; + } +done: + free(buf); + if(error) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + return(surface); +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isPNM(SDL_RWops *src) +{ + return(0); +} + +/* Load a PNM type image from an SDL datasource */ +SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_PNM */ diff --git a/IMG_tga.c b/IMG_tga.c new file mode 100644 index 0000000..f914801 --- /dev/null +++ b/IMG_tga.c @@ -0,0 +1,334 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a Targa image file loading framework */ + +#include + +#include "SDL/SDL_endian.h" + +#include "SDL/SDL_image.h" + +#ifdef LOAD_TGA + +/* + * A TGA loader for the SDL library + * Supports: Reading 8, 15, 16, 24 and 32bpp images, with alpha or colourkey, + * uncompressed or RLE encoded. + * + * 2000-06-10 Mattias Engdegård : initial version + * 2000-06-26 Mattias Engdegård : read greyscale TGAs + * 2000-08-09 Mattias Engdegård : alpha inversion removed + */ + +struct TGAheader { + Uint8 infolen; /* length of info field */ + Uint8 has_cmap; /* 1 if image has colormap, 0 otherwise */ + Uint8 type; + + Uint8 cmap_start[2]; /* index of first colormap entry */ + Uint8 cmap_len[2]; /* number of entries in colormap */ + Uint8 cmap_bits; /* bits per colormap entry */ + + Uint8 yorigin[2]; /* image origin (ignored here) */ + Uint8 xorigin[2]; + Uint8 width[2]; /* image size */ + Uint8 height[2]; + Uint8 pixel_bits; /* bits/pixel */ + Uint8 flags; +}; + +enum tga_type { + TGA_TYPE_INDEXED = 1, + TGA_TYPE_RGB = 2, + TGA_TYPE_BW = 3, + TGA_TYPE_RLE_INDEXED = 9, + TGA_TYPE_RLE_RGB = 10, + TGA_TYPE_RLE_BW = 11 +}; + +#define TGA_INTERLEAVE_MASK 0xc0 +#define TGA_INTERLEAVE_NONE 0x00 +#define TGA_INTERLEAVE_2WAY 0x40 +#define TGA_INTERLEAVE_4WAY 0x80 + +#define TGA_ORIGIN_MASK 0x30 +#define TGA_ORIGIN_LEFT 0x00 +#define TGA_ORIGIN_RIGHT 0x10 +#define TGA_ORIGIN_LOWER 0x00 +#define TGA_ORIGIN_UPPER 0x20 + +/* read/write unaligned little-endian 16-bit ints */ +#define LE16(p) ((p)[0] + ((p)[1] << 8)) +#define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8) + +/* Load a TGA type image from an SDL datasource */ +SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; + struct TGAheader hdr; + int rle = 0; + int alpha = 0; + int indexed = 0; + int grey = 0; + int ckey = -1; + int ncols, w, h; + SDL_Surface *img = NULL; + Uint32 rmask, gmask, bmask, amask; + Uint8 *dst; + int i; + int bpp; + int lstep; + Uint32 pixel; + int count, rep; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) { + error = "Error reading TGA data"; + goto error; + } + ncols = LE16(hdr.cmap_len); + switch(hdr.type) { + case TGA_TYPE_RLE_INDEXED: + rle = 1; + /* fallthrough */ + case TGA_TYPE_INDEXED: + if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256) + goto unsupported; + indexed = 1; + break; + + case TGA_TYPE_RLE_RGB: + rle = 1; + /* fallthrough */ + case TGA_TYPE_RGB: + indexed = 0; + break; + + case TGA_TYPE_RLE_BW: + rle = 1; + /* fallthrough */ + case TGA_TYPE_BW: + if(hdr.pixel_bits != 8) + goto unsupported; + /* Treat greyscale as 8bpp indexed images */ + indexed = grey = 1; + break; + + default: + goto unsupported; + } + + bpp = (hdr.pixel_bits + 7) >> 3; + rmask = gmask = bmask = amask = 0; + switch(hdr.pixel_bits) { + case 8: + if(!indexed) { + goto unsupported; + } + break; + + case 15: + case 16: + /* 15 and 16bpp both seem to use 5 bits/plane. The extra alpha bit + is ignored for now. */ + rmask = 0x7c00; + gmask = 0x03e0; + bmask = 0x001f; + break; + + case 32: + alpha = 1; + /* fallthrough */ + case 24: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + int s = alpha ? 0 : 8; + amask = 0x000000ff >> s; + rmask = 0x0000ff00 >> s; + gmask = 0x00ff0000 >> s; + bmask = 0xff000000 >> s; + } else { + amask = alpha ? 0xff000000 : 0; + rmask = 0x00ff0000; + gmask = 0x0000ff00; + bmask = 0x000000ff; + } + break; + + default: + goto unsupported; + } + + if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE + || hdr.flags & TGA_ORIGIN_RIGHT) { + goto unsupported; + } + + SDL_RWseek(src, hdr.infolen, RW_SEEK_CUR); /* skip info field */ + + w = LE16(hdr.width); + h = LE16(hdr.height); + img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, + bpp * 8, + rmask, gmask, bmask, amask); + if(img == NULL) { + error = "Out of memory"; + goto error; + } + + if(hdr.has_cmap) { + int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3); + if(indexed && !grey) { + Uint8 *pal = malloc(palsiz), *p = pal; + SDL_Color *colors = img->format->palette->colors; + img->format->palette->ncolors = ncols; + SDL_RWread(src, pal, palsiz, 1); + for(i = 0; i < ncols; i++) { + switch(hdr.cmap_bits) { + case 15: + case 16: + { + Uint16 c = p[0] + (p[1] << 8); + p += 2; + colors[i].r = (c >> 7) & 0xf8; + colors[i].g = (c >> 2) & 0xf8; + colors[i].b = c << 3; + } + break; + case 24: + case 32: + colors[i].b = *p++; + colors[i].g = *p++; + colors[i].r = *p++; + if(hdr.cmap_bits == 32 && *p++ < 128) + ckey = i; + break; + } + } + free(pal); + if(ckey >= 0) + SDL_SetColorKey(img, SDL_SRCCOLORKEY, ckey); + } else { + /* skip unneeded colormap */ + SDL_RWseek(src, palsiz, RW_SEEK_CUR); + } + } + + if(grey) { + SDL_Color *colors = img->format->palette->colors; + for(i = 0; i < 256; i++) + colors[i].r = colors[i].g = colors[i].b = i; + img->format->palette->ncolors = 256; + } + + if(hdr.flags & TGA_ORIGIN_UPPER) { + lstep = img->pitch; + dst = img->pixels; + } else { + lstep = -img->pitch; + dst = (Uint8 *)img->pixels + (h - 1) * img->pitch; + } + + /* The RLE decoding code is slightly convoluted since we can't rely on + spans not to wrap across scan lines */ + count = rep = 0; + for(i = 0; i < h; i++) { + if(rle) { + int x = 0; + for(;;) { + Uint8 c; + + if(count) { + int n = count; + if(n > w - x) + n = w - x; + SDL_RWread(src, dst + x * bpp, n * bpp, 1); + count -= n; + x += n; + if(x == w) + break; + } else if(rep) { + int n = rep; + if(n > w - x) + n = w - x; + rep -= n; + while(n--) { + memcpy(dst + x * bpp, &pixel, bpp); + x++; + } + if(x == w) + break; + } + + SDL_RWread(src, &c, 1, 1); + if(c & 0x80) { + SDL_RWread(src, &pixel, bpp, 1); + rep = (c & 0x7f) + 1; + } else { + count = c + 1; + } + } + + } else { + SDL_RWread(src, dst, w * bpp, 1); + } + if(SDL_BYTEORDER == SDL_BIG_ENDIAN && bpp == 2) { + /* swap byte order */ + int x; + Uint16 *p = (Uint16 *)dst; + for(x = 0; x < w; x++) + p[x] = SDL_Swap16(p[x]); + } + dst += lstep; + } + return img; + +unsupported: + error = "Unsupported TGA format"; + +error: + SDL_RWseek(src, start, RW_SEEK_SET); + if ( img ) { + SDL_FreeSurface(img); + } + IMG_SetError(error); + return NULL; +} + +#else + +/* dummy TGA load routine */ +SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_TGA */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_tif.c b/IMG_tif.c new file mode 100644 index 0000000..9cd4dba --- /dev/null +++ b/IMG_tif.c @@ -0,0 +1,298 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) + +/* This is a TIFF image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_TIF + +#include + +static struct { + int loaded; + void *handle; + TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc); + void (*TIFFClose)(TIFF*); + int (*TIFFGetField)(TIFF*, ttag_t, ...); + int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int); + TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler); +} lib; + +#ifdef LOAD_TIF_DYNAMIC +int IMG_InitTIF() +{ + if ( lib.loaded == 0 ) { + lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC); + if ( lib.handle == NULL ) { + return -1; + } + lib.TIFFClientOpen = + (TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc)) + SDL_LoadFunction(lib.handle, "TIFFClientOpen"); + if ( lib.TIFFClientOpen == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.TIFFClose = + (void (*)(TIFF*)) + SDL_LoadFunction(lib.handle, "TIFFClose"); + if ( lib.TIFFClose == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.TIFFGetField = + (int (*)(TIFF*, ttag_t, ...)) + SDL_LoadFunction(lib.handle, "TIFFGetField"); + if ( lib.TIFFGetField == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.TIFFReadRGBAImage = + (int (*)(TIFF*, uint32, uint32, uint32*, int)) + SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage"); + if ( lib.TIFFReadRGBAImage == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + lib.TIFFSetErrorHandler = + (TIFFErrorHandler (*)(TIFFErrorHandler)) + SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler"); + if ( lib.TIFFSetErrorHandler == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + } + ++lib.loaded; + + return 0; +} +void IMG_QuitTIF() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + SDL_UnloadObject(lib.handle); + } + --lib.loaded; +} +#else +int IMG_InitTIF() +{ + if ( lib.loaded == 0 ) { + lib.TIFFClientOpen = TIFFClientOpen; + lib.TIFFClose = TIFFClose; + lib.TIFFGetField = TIFFGetField; + lib.TIFFReadRGBAImage = TIFFReadRGBAImage; + lib.TIFFSetErrorHandler = TIFFSetErrorHandler; + } + ++lib.loaded; + + return 0; +} +void IMG_QuitTIF() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + } + --lib.loaded; +} +#endif /* LOAD_TIF_DYNAMIC */ + +/* + * These are the thunking routine to use the SDL_RWops* routines from + * libtiff's internals. +*/ + +static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size) +{ + return SDL_RWread((SDL_RWops*)fd, buf, 1, size); +} + +static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin) +{ + return SDL_RWseek((SDL_RWops*)fd, offset, origin); +} + +static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size) +{ + return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size); +} + +static int tiff_close(thandle_t fd) +{ + /* + * We don't want libtiff closing our SDL_RWops*, but if it's not given + * a routine to try, and if the image isn't a TIFF, it'll segfault. + */ + return 0; +} + +static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size) +{ + return; +} + +static toff_t tiff_size(thandle_t fd) +{ + Uint32 save_pos; + toff_t size; + + save_pos = SDL_RWtell((SDL_RWops*)fd); + SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END); + size = SDL_RWtell((SDL_RWops*)fd); + SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET); + return size; +} + +int IMG_isTIF(SDL_RWops* src) +{ + int start; + int is_TIF; + Uint8 magic[4]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_TIF = 0; + if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) { + if ( (magic[0] == 'I' && + magic[1] == 'I' && + magic[2] == 0x2a && + magic[3] == 0x00) || + (magic[0] == 'M' && + magic[1] == 'M' && + magic[2] == 0x00 && + magic[3] == 0x2a) ) { + is_TIF = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_TIF); +} + +SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) +{ + int start; + TIFF* tiff; + SDL_Surface* surface = NULL; + Uint32 img_width, img_height; + Uint32 Rmask, Gmask, Bmask, Amask; + Uint32 x, y; + Uint32 half; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + if ( !IMG_Init(IMG_INIT_TIF) ) { + return NULL; + } + + /* turn off memory mapped access with the m flag */ + tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src, + tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap); + if(!tiff) + goto error; + + /* Retrieve the dimensions of the image from the TIFF tags */ + lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width); + lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height); + + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + Amask = 0xFF000000; + surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32, + Rmask, Gmask, Bmask, Amask); + if(!surface) + goto error; + + if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0)) + goto error; + + /* libtiff loads the image upside-down, flip it back */ + half = img_height / 2; + for(y = 0; y < half; y++) + { + Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4; + Uint32 *bot = (Uint32 *)surface->pixels + + (img_height - y - 1) * surface->pitch/4; + for(x = 0; x < img_width; x++) + { + Uint32 tmp = top[x]; + top[x] = bot[x]; + bot[x] = tmp; + } + } + lib.TIFFClose(tiff); + + return surface; + +error: + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + } + return NULL; +} + +#else + +int IMG_InitTIF() +{ + IMG_SetError("TIFF images are not supported"); + return(-1); +} + +void IMG_QuitTIF() +{ +} + +/* See if an image is contained in a data source */ +int IMG_isTIF(SDL_RWops *src) +{ + return(0); +} + +/* Load a TIFF type image from an SDL datasource */ +SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_TIF */ + +#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */ diff --git a/IMG_webp.c b/IMG_webp.c new file mode 100644 index 0000000..324646e --- /dev/null +++ b/IMG_webp.c @@ -0,0 +1,294 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a WEBP image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_WEBP + +/*============================================================================= + File: SDL_webp.c + Purpose: A WEBP loader for the SDL library + Revision: + Created by: Michael Bonfils (Murlock) (26 November 2011) + murlock42@gmail.com + +=============================================================================*/ + +#include "SDL_endian.h" + +#ifdef macintosh +#define MACOS +#endif +#include + +static struct { + int loaded; + void *handle; + int/*VP8StatuCode*/ (*webp_get_features_internal) (const uint8_t *data, uint32_t data_size, WebPBitstreamFeatures* const features, int decoder_abi_version); + uint8_t* (*webp_decode_rgb_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride); + uint8_t* (*webp_decode_rgba_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride); +} lib; + +#ifdef LOAD_WEBP_DYNAMIC +int IMG_InitWEBP() +{ + if ( lib.loaded == 0 ) { + lib.handle = SDL_LoadObject(LOAD_WEBP_DYNAMIC); + if ( lib.handle == NULL ) { + return -1; + } + lib.webp_get_features_internal = + ( int (*) (const uint8_t *, uint32_t, WebPBitstreamFeatures* const, int) ) + SDL_LoadFunction(lib.handle, "WebPGetFeaturesInternal" ); + if ( lib.webp_get_features_internal == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + + lib.webp_decode_rgb_into = + ( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) ) + SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" ); + if ( lib.webp_decode_rgb_into == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + + lib.webp_decode_rgba_into = + ( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) ) + SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" ); + if ( lib.webp_decode_rgba_into == NULL ) { + SDL_UnloadObject(lib.handle); + return -1; + } + } + ++lib.loaded; + + return 0; +} +void IMG_QuitWEBP() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + SDL_UnloadObject(lib.handle); + } + --lib.loaded; +} +#else +int IMG_InitWEBP() +{ + if ( lib.loaded == 0 ) { + lib.webp_get_features_internal = WebPGetFeaturesInternal; + lib.webp_decode_rgb_into = WebPDecodeRGBInto; + lib.webp_decode_rgba_into = WebPDecodeRGBAInto; + } + ++lib.loaded; + + return 0; +} +void IMG_QuitWEBP() +{ + if ( lib.loaded == 0 ) { + return; + } + if ( lib.loaded == 1 ) { + } + --lib.loaded; +} +#endif /* LOAD_WEBP_DYNAMIC */ + +static int webp_getinfo( SDL_RWops *src, int *datasize ) { + int start; + int is_WEBP; + int data; + Uint8 magic[20]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_WEBP = 0; + if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) { + if ( magic[ 0] == 'R' && + magic[ 1] == 'I' && + magic[ 2] == 'F' && + magic[ 3] == 'F' && + magic[ 8] == 'W' && + magic[ 9] == 'E' && + magic[10] == 'B' && + magic[11] == 'P' && + magic[12] == 'V' && + magic[13] == 'P' && + magic[14] == '8' && + magic[15] == ' ' ) { + is_WEBP = 1; + data = magic[16] | magic[17]<<8 | magic[18]<<16 | magic[19]<<24; + if ( datasize ) + *datasize = data; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_WEBP); +} + +/* See if an image is contained in a data source */ +int IMG_isWEBP(SDL_RWops *src) +{ + return webp_getinfo( src, NULL ); +} + +SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; + SDL_Surface *volatile surface = NULL; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; + WebPBitstreamFeatures features; + int raw_data_size; + uint8_t *raw_data; + int r; + uint8_t *ret; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + + start = SDL_RWtell(src); + + if ( !IMG_Init(IMG_INIT_WEBP) ) { + goto error; + } + + + raw_data_size = -1; + if ( !webp_getinfo( src, &raw_data_size ) ) { + error = "Invalid WEBP"; + goto error; + } + + // skip header + SDL_RWseek(src, start+20, RW_SEEK_SET ); + + raw_data = (uint8_t*) malloc( raw_data_size ); + if ( raw_data == NULL ) { + error = "Failed to allocate enought buffer for WEBP"; + goto error; + } + + r = SDL_RWread(src, raw_data, 1, raw_data_size ); + if ( r != raw_data_size ) { + error = "Failed to read WEBP"; + goto error; + } + +#if 0 + // extract size of picture, not interesting since we don't know about alpha channel + int width = -1, height = -1; + if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) { + printf("WebPGetInfo has failed\n" ); + return NULL; + } +#endif + + if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) { + error = "WebPGetFeatures has failed"; + return NULL; + } + + /* Check if it's ok !*/ + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + Amask = features.has_alpha?0xFF000001:0; + + surface = SDL_AllocSurface(SDL_SWSURFACE, features.width, features.height, + features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask); + + if ( surface == NULL ) { + error = "Failed to allocate SDL_Surface"; + goto error; + } + + if ( features.has_alpha ) { + ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h, surface->pitch ); + } else { + ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h, surface->pitch ); + } + + if ( !ret ) { + error = "Failed to decode WEBP"; + goto error; + } + + return surface; + + +error: + + if ( surface ) { + SDL_FreeSurface( surface ); + } + + if ( raw_data ) { + free( raw_data ); + } + + if ( error ) { + IMG_SetError( error ); + } + + SDL_RWseek(src, start, RW_SEEK_SET); + return(NULL); +} + +#else + +int IMG_InitWEBP() +{ + IMG_SetError("WEBP images are not supported"); + return(-1); +} + +void IMG_QuitWEBP() +{ +} + +/* See if an image is contained in a data source */ +int IMG_isWEBP(SDL_RWops *src) +{ + return(0); +} + +/* Load a WEBP type image from an SDL datasource */ +SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_WEBP */ diff --git a/IMG_xcf.c b/IMG_xcf.c new file mode 100644 index 0000000..b11163d --- /dev/null +++ b/IMG_xcf.c @@ -0,0 +1,821 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a XCF image file loading framework */ + +#include + +#include "SDL/SDL_endian.h" +#include "SDL/SDL_image.h" + +#ifdef LOAD_XCF + +#if DEBUG +static char prop_names [][30] = { + "end", + "colormap", + "active_layer", + "active_channel", + "selection", + "floating_selection", + "opacity", + "mode", + "visible", + "linked", + "preserve_transparency", + "apply_mask", + "edit_mask", + "show_mask", + "show_masked", + "offsets", + "color", + "compression", + "guides", + "resolution", + "tattoo", + "parasites", + "unit", + "paths", + "user_unit" +}; +#endif + + +typedef enum +{ + PROP_END = 0, + PROP_COLORMAP = 1, + PROP_ACTIVE_LAYER = 2, + PROP_ACTIVE_CHANNEL = 3, + PROP_SELECTION = 4, + PROP_FLOATING_SELECTION = 5, + PROP_OPACITY = 6, + PROP_MODE = 7, + PROP_VISIBLE = 8, + PROP_LINKED = 9, + PROP_PRESERVE_TRANSPARENCY = 10, + PROP_APPLY_MASK = 11, + PROP_EDIT_MASK = 12, + PROP_SHOW_MASK = 13, + PROP_SHOW_MASKED = 14, + PROP_OFFSETS = 15, + PROP_COLOR = 16, + PROP_COMPRESSION = 17, + PROP_GUIDES = 18, + PROP_RESOLUTION = 19, + PROP_TATTOO = 20, + PROP_PARASITES = 21, + PROP_UNIT = 22, + PROP_PATHS = 23, + PROP_USER_UNIT = 24 +} xcf_prop_type; + +typedef enum { + COMPR_NONE = 0, + COMPR_RLE = 1, + COMPR_ZLIB = 2, + COMPR_FRACTAL = 3 +} xcf_compr_type; + +typedef enum { + IMAGE_RGB = 0, + IMAGE_GREYSCALE = 1, + IMAGE_INDEXED = 2 +} xcf_image_type; + +typedef struct { + Uint32 id; + Uint32 length; + union { + struct { + Uint32 num; + char * cmap; + } colormap; // 1 + struct { + Uint32 drawable_offset; + } floating_selection; // 5 + Sint32 opacity; + Sint32 mode; + int visible; + int linked; + int preserve_transparency; + int apply_mask; + int show_mask; + struct { + Sint32 x; + Sint32 y; + } offset; + unsigned char color [3]; + Uint8 compression; + struct { + Sint32 x; + Sint32 y; + } resolution; + struct { + char * name; + Uint32 flags; + Uint32 size; + char * data; + } parasite; + } data; +} xcf_prop; + +typedef struct { + char sign [14]; + Uint32 width; + Uint32 height; + Sint32 image_type; + xcf_prop * properties; + + Uint32 * layer_file_offsets; + Uint32 * channel_file_offsets; + + xcf_compr_type compr; + Uint32 cm_num; + unsigned char * cm_map; +} xcf_header; + +typedef struct { + Uint32 width; + Uint32 height; + Sint32 layer_type; + char * name; + xcf_prop * properties; + + Uint32 hierarchy_file_offset; + Uint32 layer_mask_offset; + + Uint32 offset_x; + Uint32 offset_y; + int visible; +} xcf_layer; + +typedef struct { + Uint32 width; + Uint32 height; + char * name; + xcf_prop * properties; + + Uint32 hierarchy_file_offset; + + Uint32 color; + Uint32 opacity; + int selection; + int visible; +} xcf_channel; + +typedef struct { + Uint32 width; + Uint32 height; + Uint32 bpp; + + Uint32 * level_file_offsets; +} xcf_hierarchy; + +typedef struct { + Uint32 width; + Uint32 height; + + Uint32 * tile_file_offsets; +} xcf_level; + +typedef unsigned char * xcf_tile; + +typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int); + + +/* See if an image is contained in a data source */ +int IMG_isXCF(SDL_RWops *src) +{ + int start; + int is_XCF; + char magic[14]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_XCF = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + if (strncmp(magic, "gimp xcf ", 9) == 0) { + is_XCF = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_XCF); +} + +static char * read_string (SDL_RWops * src) { + Uint32 tmp; + char * data; + + tmp = SDL_ReadBE32 (src); + if (tmp > 0) { + data = (char *) malloc (sizeof (char) * tmp); + SDL_RWread (src, data, tmp, 1); + } + else { + data = NULL; + } + + return data; +} + + +static Uint32 Swap32 (Uint32 v) { + return + ((v & 0x000000FF) << 16) + | ((v & 0x0000FF00)) + | ((v & 0x00FF0000) >> 16) + | ((v & 0xFF000000)); +} + +static void xcf_read_property (SDL_RWops * src, xcf_prop * prop) { + prop->id = SDL_ReadBE32 (src); + prop->length = SDL_ReadBE32 (src); + +#if DEBUG + printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length); +#endif + + switch (prop->id) { + case PROP_COLORMAP: + prop->data.colormap.num = SDL_ReadBE32 (src); + prop->data.colormap.cmap = (char *) malloc (sizeof (char) * prop->data.colormap.num * 3); + SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1); + break; + + case PROP_OFFSETS: + prop->data.offset.x = SDL_ReadBE32 (src); + prop->data.offset.y = SDL_ReadBE32 (src); + break; + case PROP_OPACITY: + prop->data.opacity = SDL_ReadBE32 (src); + break; + case PROP_COMPRESSION: + case PROP_COLOR: + SDL_RWread (src, &prop->data, prop->length, 1); + break; + case PROP_VISIBLE: + prop->data.visible = SDL_ReadBE32 (src); + break; + default: + // SDL_RWread (src, &prop->data, prop->length, 1); + SDL_RWseek (src, prop->length, RW_SEEK_CUR); + } +} + +static void free_xcf_header (xcf_header * h) { + if (h->cm_num) + free (h->cm_map); + + free (h); +} + +static xcf_header * read_xcf_header (SDL_RWops * src) { + xcf_header * h; + xcf_prop prop; + + h = (xcf_header *) malloc (sizeof (xcf_header)); + SDL_RWread (src, h->sign, 14, 1); + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->image_type = SDL_ReadBE32 (src); + + h->properties = NULL; + h->compr = COMPR_NONE; + h->cm_num = 0; + h->cm_map = NULL; + + // Just read, don't save + do { + xcf_read_property (src, &prop); + if (prop.id == PROP_COMPRESSION) + h->compr = prop.data.compression; + else if (prop.id == PROP_COLORMAP) { + // unused var: int i; + + h->cm_num = prop.data.colormap.num; + h->cm_map = (unsigned char *) malloc (sizeof (unsigned char) * 3 * h->cm_num); + memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num); + free (prop.data.colormap.cmap); + } + } while (prop.id != PROP_END); + + return h; +} + +static void free_xcf_layer (xcf_layer * l) { + free (l->name); + free (l); +} + +static xcf_layer * read_xcf_layer (SDL_RWops * src) { + xcf_layer * l; + xcf_prop prop; + + l = (xcf_layer *) malloc (sizeof (xcf_layer)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + l->layer_type = SDL_ReadBE32 (src); + + l->name = read_string (src); + + do { + xcf_read_property (src, &prop); + if (prop.id == PROP_OFFSETS) { + l->offset_x = prop.data.offset.x; + l->offset_y = prop.data.offset.y; + } else if (prop.id == PROP_VISIBLE) { + l->visible = prop.data.visible ? 1 : 0; + } + } while (prop.id != PROP_END); + + l->hierarchy_file_offset = SDL_ReadBE32 (src); + l->layer_mask_offset = SDL_ReadBE32 (src); + + return l; +} + +static void free_xcf_channel (xcf_channel * c) { + free (c->name); + free (c); +} + +static xcf_channel * read_xcf_channel (SDL_RWops * src) { + xcf_channel * l; + xcf_prop prop; + + l = (xcf_channel *) malloc (sizeof (xcf_channel)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + + l->name = read_string (src); + + l->selection = 0; + do { + xcf_read_property (src, &prop); + switch (prop.id) { + case PROP_OPACITY: + l->opacity = prop.data.opacity << 24; + break; + case PROP_COLOR: + l->color = ((Uint32) prop.data.color[0] << 16) + | ((Uint32) prop.data.color[1] << 8) + | ((Uint32) prop.data.color[2]); + break; + case PROP_SELECTION: + l->selection = 1; + break; + case PROP_VISIBLE: + l->visible = prop.data.visible ? 1 : 0; + break; + default: + ; + } + } while (prop.id != PROP_END); + + l->hierarchy_file_offset = SDL_ReadBE32 (src); + + return l; +} + +static void free_xcf_hierarchy (xcf_hierarchy * h) { + free (h->level_file_offsets); + free (h); +} + +static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) { + xcf_hierarchy * h; + int i; + + h = (xcf_hierarchy *) malloc (sizeof (xcf_hierarchy)); + h->width = SDL_ReadBE32 (src); + h->height = SDL_ReadBE32 (src); + h->bpp = SDL_ReadBE32 (src); + + h->level_file_offsets = NULL; + i = 0; + do { + h->level_file_offsets = (Uint32 *) realloc (h->level_file_offsets, sizeof (Uint32) * (i+1)); + h->level_file_offsets [i] = SDL_ReadBE32 (src); + } while (h->level_file_offsets [i++]); + + return h; +} + +static void free_xcf_level (xcf_level * l) { + free (l->tile_file_offsets); + free (l); +} + +static xcf_level * read_xcf_level (SDL_RWops * src) { + xcf_level * l; + int i; + + l = (xcf_level *) malloc (sizeof (xcf_level)); + l->width = SDL_ReadBE32 (src); + l->height = SDL_ReadBE32 (src); + + l->tile_file_offsets = NULL; + i = 0; + do { + l->tile_file_offsets = (Uint32 *) realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1)); + l->tile_file_offsets [i] = SDL_ReadBE32 (src); + } while (l->tile_file_offsets [i++]); + + return l; +} + +static void free_xcf_tile (unsigned char * t) { + free (t); +} + +static unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) { + unsigned char * load; + + load = (unsigned char *) malloc (len); // expect this is okay + SDL_RWread (src, load, len, 1); + + return load; +} + +static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) { + unsigned char * load, * t, * data, * d; + Uint32 reallen; + int i, size, count, j, length; + unsigned char val; + + t = load = (unsigned char *) malloc (len); + reallen = SDL_RWread (src, t, 1, len); + + data = (unsigned char *) malloc (x*y*bpp); + for (i = 0; i < bpp; i++) { + d = data + i; + size = x*y; + count = 0; + + while (size > 0) { + val = *t++; + + length = val; + if (length >= 128) { + length = 255 - (length - 1); + if (length == 128) { + length = (*t << 8) + t[1]; + t += 2; + } + + count += length; + size -= length; + + while (length-- > 0) { + *d = *t++; + d += bpp; + } + } + else { + length += 1; + if (length == 128) { + length = (*t << 8) + t[1]; + t += 2; + } + + count += length; + size -= length; + + val = *t++; + + for (j = 0; j < length; j++) { + *d = val; + d += bpp; + } + } + } + } + + free (load); + return (data); +} + +static Uint32 rgb2grey (Uint32 a) { + Uint8 l; + l = 0.2990 * ((a && 0x00FF0000) >> 16) + + 0.5870 * ((a && 0x0000FF00) >> 8) + + 0.1140 * ((a && 0x000000FF)); + + return (l << 16) | (l << 8) | l; +} + +static void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) { + Uint32 c = 0; + + switch (itype) { + case IMAGE_RGB: + case IMAGE_INDEXED: + c = opacity | color; + break; + case IMAGE_GREYSCALE: + c = opacity | rgb2grey (color); + break; + } + SDL_FillRect (surf, NULL, c); +} + +static int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) { + xcf_hierarchy * hierarchy; + xcf_level * level; + unsigned char * tile; + Uint8 * p8; + Uint16 * p16; + Uint32 * p; + int x, y, tx, ty, ox, oy, i, j; + Uint32 *row; + + SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET); + hierarchy = read_xcf_hierarchy (src); + + level = NULL; + for (i = 0; hierarchy->level_file_offsets [i]; i++) { + SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET); + level = read_xcf_level (src); + + ty = tx = 0; + for (j = 0; level->tile_file_offsets [j]; j++) { + SDL_RWseek (src, level->tile_file_offsets [j], RW_SEEK_SET); + ox = tx+64 > level->width ? level->width % 64 : 64; + oy = ty+64 > level->height ? level->height % 64 : 64; + + if (level->tile_file_offsets [j+1]) { + tile = load_tile + (src, + level->tile_file_offsets [j+1] - level->tile_file_offsets [j], + hierarchy->bpp, + ox, oy); + } + else { + tile = load_tile + (src, + ox*oy*6, + hierarchy->bpp, + ox, oy); + } + + p8 = tile; + p16 = (Uint16 *) p8; + p = (Uint32 *) p8; + for (y=ty; y < ty+oy; y++) { + row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4); + switch (hierarchy->bpp) { + case 4: + for (x=tx; x < tx+ox; x++) + *row++ = Swap32 (*p++); + break; + case 3: + for (x=tx; x < tx+ox; x++) { + *row = 0xFF000000; + *row |= ((Uint32) *(p8++) << 16); + *row |= ((Uint32) *(p8++) << 8); + *row |= ((Uint32) *(p8++) << 0); + row++; + } + break; + case 2: // Indexed/Greyscale + Alpha + switch (head->image_type) { + case IMAGE_INDEXED: + for (x=tx; x < tx+ox; x++) { + *row = ((Uint32) (head->cm_map [*p8*3]) << 16); + *row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8); + *row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0); + *row |= ((Uint32) *p8++ << 24);; + row++; + } + break; + case IMAGE_GREYSCALE: + for (x=tx; x < tx+ox; x++) { + *row = ((Uint32) *p8 << 16); + *row |= ((Uint32) *p8 << 8); + *row |= ((Uint32) *p8++ << 0); + *row |= ((Uint32) *p8++ << 24);; + row++; + } + break; + default: + fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type); + return 1; + } + break; + case 1: // Indexed/Greyscale + switch (head->image_type) { + case IMAGE_INDEXED: + for (x = tx; x < tx+ox; x++) { + *row++ = 0xFF000000 + | ((Uint32) (head->cm_map [*p8*3]) << 16) + | ((Uint32) (head->cm_map [*p8*3+1]) << 8) + | ((Uint32) (head->cm_map [*p8*3+2]) << 0); + p8++; + } + break; + case IMAGE_GREYSCALE: + for (x=tx; x < tx+ox; x++) { + *row++ = 0xFF000000 + | (((Uint32) (*p8)) << 16) + | (((Uint32) (*p8)) << 8) + | (((Uint32) (*p8)) << 0); + ++p8; + } + break; + default: + fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type); + return 1; + } + break; + } + } + tx += 64; + if (tx >= level->width) { + tx = 0; + ty += 64; + } + if (ty >= level->height) { + break; + } + + free_xcf_tile (tile); + } + free_xcf_level (level); + } + + free_xcf_hierarchy (hierarchy); + + return 0; +} + +SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; + SDL_Surface *surface, *lays; + xcf_header * head; + xcf_layer * layer; + xcf_channel ** channel; + int chnls, i, offsets; + Uint32 offset, fp; + + unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int); + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + /* Initialize the data we will clean up when we're done */ + surface = NULL; + + head = read_xcf_header (src); + + switch (head->compr) { + case COMPR_NONE: + load_tile = load_xcf_tile_none; + break; + case COMPR_RLE: + load_tile = load_xcf_tile_rle; + break; + default: + fprintf (stderr, "Unsupported Compression.\n"); + free_xcf_header (head); + return NULL; + } + + /* Create the surface of the appropriate type */ + surface = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if ( surface == NULL ) { + error = "Out of memory"; + goto done; + } + + head->layer_file_offsets = NULL; + offsets = 0; + + while ((offset = SDL_ReadBE32 (src))) { + head->layer_file_offsets = (Uint32 *) realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1)); + head->layer_file_offsets [offsets] = offset; + offsets++; + } + fp = SDL_RWtell (src); + + lays = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if ( lays == NULL ) { + error = "Out of memory"; + goto done; + } + + // Blit layers backwards, because Gimp saves them highest first + for (i = offsets; i > 0; i--) { + SDL_Rect rs, rd; + SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET); + + layer = read_xcf_layer (src); + do_layer_surface (lays, src, head, layer, load_tile); + rs.x = 0; + rs.y = 0; + rs.w = layer->width; + rs.h = layer->height; + rd.x = layer->offset_x; + rd.y = layer->offset_y; + rd.w = layer->width; + rd.h = layer->height; + + if (layer->visible) + SDL_BlitSurface (lays, &rs, surface, &rd); + free_xcf_layer (layer); + } + + SDL_FreeSurface (lays); + + SDL_RWseek (src, fp, RW_SEEK_SET); + + // read channels + channel = NULL; + chnls = 0; + while ((offset = SDL_ReadBE32 (src))) { + channel = (xcf_channel **) realloc (channel, sizeof (xcf_channel *) * (chnls+1)); + fp = SDL_RWtell (src); + SDL_RWseek (src, offset, RW_SEEK_SET); + channel [chnls++] = (read_xcf_channel (src)); + SDL_RWseek (src, fp, RW_SEEK_SET); + } + + if (chnls) { + SDL_Surface * chs; + + chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, + 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); + + if (chs == NULL) { + error = "Out of memory"; + goto done; + } + for (i = 0; i < chnls; i++) { + // printf ("CNLBLT %i\n", i); + if (!channel [i]->selection && channel [i]->visible) { + create_channel_surface (chs, head->image_type, channel [i]->color, channel [i]->opacity); + SDL_BlitSurface (chs, NULL, surface, NULL); + } + free_xcf_channel (channel [i]); + } + + SDL_FreeSurface (chs); + } + +done: + free_xcf_header (head); + if ( error ) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + + return(surface); +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isXCF(SDL_RWops *src) +{ + return(0); +} + +/* Load a XCF type image from an SDL datasource */ +SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_XCF */ diff --git a/IMG_xpm.c b/IMG_xpm.c new file mode 100644 index 0000000..f6847cc --- /dev/null +++ b/IMG_xpm.c @@ -0,0 +1,511 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * XPM (X PixMap) image loader: + * + * Supports the XPMv3 format, EXCEPT: + * - hotspot coordinates are ignored + * - only colour ('c') colour symbols are used + * - rgb.txt is not used (for portability), so only RGB colours + * are recognized (#rrggbb etc) - only a few basic colour names are + * handled + * + * The result is an 8bpp indexed surface if possible, otherwise 32bpp. + * The colourkey is correctly set if transparency is used. + * + * Besides the standard API, also provides + * + * SDL_Surface *IMG_ReadXPMFromArray(char **xpm) + * + * that reads the image data from an XPM file included in the C source. + * + * TODO: include rgb.txt here. The full table (from solaris 2.6) only + * requires about 13K in binary form. + */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_XPM + +/* See if an image is contained in a data source */ +int IMG_isXPM(SDL_RWops *src) +{ + int start; + int is_XPM; + char magic[9]; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_XPM = 0; + if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { + if ( memcmp(magic, "/* XPM */", sizeof(magic)) == 0 ) { + is_XPM = 1; + } + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_XPM); +} + +/* Hash table to look up colors from pixel strings */ +#define STARTING_HASH_SIZE 256 + +struct hash_entry { + char *key; + Uint32 color; + struct hash_entry *next; +}; + +struct color_hash { + struct hash_entry **table; + struct hash_entry *entries; /* array of all entries */ + struct hash_entry *next_free; + int size; + int maxnum; +}; + +static int hash_key(const char *key, int cpp, int size) +{ + int hash; + + hash = 0; + while ( cpp-- > 0 ) { + hash = hash * 33 + *key++; + } + return hash & (size - 1); +} + +static struct color_hash *create_colorhash(int maxnum) +{ + int bytes, s; + struct color_hash *hash; + + /* we know how many entries we need, so we can allocate + everything here */ + hash = malloc(sizeof *hash); + if(!hash) + return NULL; + + /* use power-of-2 sized hash table for decoding speed */ + for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) + ; + hash->size = s; + hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); + hash->entries = NULL; /* in case malloc fails */ + hash->table = malloc(bytes); + if(!hash->table) + return NULL; + memset(hash->table, 0, bytes); + hash->entries = malloc(maxnum * sizeof(struct hash_entry)); + if(!hash->entries) { + free(hash->table); + return NULL; + } + hash->next_free = hash->entries; + return hash; +} + +static int add_colorhash(struct color_hash *hash, + char *key, int cpp, Uint32 color) +{ + int index = hash_key(key, cpp, hash->size); + struct hash_entry *e = hash->next_free++; + e->color = color; + e->key = key; + e->next = hash->table[index]; + hash->table[index] = e; + return 1; +} + +/* fast lookup that works if cpp == 1 */ +#define QUICK_COLORHASH(hash, key) ((hash)->table[*(Uint8 *)(key)]->color) + +static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp) +{ + struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)]; + while(entry) { + if(memcmp(key, entry->key, cpp) == 0) + return entry->color; + entry = entry->next; + } + return 0; /* garbage in - garbage out */ +} + +static void free_colorhash(struct color_hash *hash) +{ + if(hash && hash->table) { + free(hash->table); + free(hash->entries); + free(hash); + } +} + +/* portable case-insensitive string comparison */ +static int string_equal(const char *a, const char *b, int n) +{ + while(*a && *b && n) { + if(toupper((unsigned char)*a) != toupper((unsigned char)*b)) + return 0; + a++; + b++; + n--; + } + return *a == *b; +} + +#define ARRAYSIZE(a) (int)(sizeof(a) / sizeof((a)[0])) + +/* + * convert colour spec to RGB (in 0xrrggbb format). + * return 1 if successful. + */ +static int color_to_rgb(char *spec, int speclen, Uint32 *rgb) +{ + /* poor man's rgb.txt */ + static struct { char *name; Uint32 rgb; } known[] = { + {"none", 0xffffffff}, + {"black", 0x00000000}, + {"white", 0x00ffffff}, + {"red", 0x00ff0000}, + {"green", 0x0000ff00}, + {"blue", 0x000000ff} + }; + + if(spec[0] == '#') { + char buf[7]; + switch(speclen) { + case 4: + buf[0] = buf[1] = spec[1]; + buf[2] = buf[3] = spec[2]; + buf[4] = buf[5] = spec[3]; + break; + case 7: + memcpy(buf, spec + 1, 6); + break; + case 13: + buf[0] = spec[1]; + buf[1] = spec[2]; + buf[2] = spec[5]; + buf[3] = spec[6]; + buf[4] = spec[9]; + buf[5] = spec[10]; + break; + } + buf[6] = '\0'; + *rgb = strtol(buf, NULL, 16); + return 1; + } else { + int i; + for(i = 0; i < ARRAYSIZE(known); i++) + if(string_equal(known[i].name, spec, speclen)) { + *rgb = known[i].rgb; + return 1; + } + return 0; + } +} + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +static char *linebuf; +static int buflen; +static char *error; + +/* + * Read next line from the source. + * If len > 0, it's assumed to be at least len chars (for efficiency). + * Return NULL and set error upon EOF or parse error. + */ +static char *get_next_line(char ***lines, SDL_RWops *src, int len) +{ + char *linebufnew; + + if(lines) { + return *(*lines)++; + } else { + char c; + int n; + do { + if(SDL_RWread(src, &c, 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + } while(c != '"'); + if(len) { + len += 4; /* "\",\n\0" */ + if(len > buflen){ + buflen = len; + linebufnew = realloc(linebuf, buflen); + if(!linebufnew) { + free(linebuf); + error = "Out of memory"; + return NULL; + } + linebuf = linebufnew; + } + if(SDL_RWread(src, linebuf, len - 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + n = len - 2; + } else { + n = 0; + do { + if(n >= buflen - 1) { + if(buflen == 0) + buflen = 16; + buflen *= 2; + linebufnew = realloc(linebuf, buflen); + if(!linebufnew) { + free(linebuf); + error = "Out of memory"; + return NULL; + } + linebuf = linebufnew; + } + if(SDL_RWread(src, linebuf + n, 1, 1) <= 0) { + error = "Premature end of data"; + return NULL; + } + } while(linebuf[n++] != '"'); + n--; + } + linebuf[n] = '\0'; + return linebuf; + } +} + +#define SKIPSPACE(p) \ +do { \ + while(isspace((unsigned char)*(p))) \ + ++(p); \ +} while(0) + +#define SKIPNONSPACE(p) \ +do { \ + while(!isspace((unsigned char)*(p)) && *p) \ + ++(p); \ +} while(0) + +/* read XPM from either array or RWops */ +static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) +{ + int start = 0; + SDL_Surface *image = NULL; + int index; + int x, y; + int w, h, ncolors, cpp; + int indexed; + Uint8 *dst; + struct color_hash *colors = NULL; + SDL_Color *im_colors = NULL; + char *keystrings = NULL, *nextkey; + char *line; + char ***xpmlines = NULL; + int pixels_len; + + error = NULL; + linebuf = NULL; + buflen = 0; + + if ( src ) + start = SDL_RWtell(src); + + if(xpm) + xpmlines = &xpm; + + line = get_next_line(xpmlines, src, 0); + if(!line) + goto done; + /* + * The header string of an XPMv3 image has the format + * + * [ ] + * + * where the hotspot coords are intended for mouse cursors. + * Right now we don't use the hotspots but it should be handled + * one day. + */ + if(sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 + || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { + error = "Invalid format description"; + goto done; + } + + keystrings = malloc(ncolors * cpp); + if(!keystrings) { + error = "Out of memory"; + goto done; + } + nextkey = keystrings; + + /* Create the new surface */ + if(ncolors <= 256) { + indexed = 1; + image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, + 0, 0, 0, 0); + im_colors = image->format->palette->colors; + image->format->palette->ncolors = ncolors; + } else { + indexed = 0; + image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, + 0xff0000, 0x00ff00, 0x0000ff, 0); + } + if(!image) { + /* Hmm, some SDL error (out of memory?) */ + goto done; + } + + /* Read the colors */ + colors = create_colorhash(ncolors); + if (!colors) { + error = "Out of memory"; + goto done; + } + for(index = 0; index < ncolors; ++index ) { + char *p; + line = get_next_line(xpmlines, src, 0); + if(!line) + goto done; + + p = line + cpp + 1; + + /* parse a colour definition */ + for(;;) { + char nametype; + char *colname; + Uint32 rgb, pixel; + + SKIPSPACE(p); + if(!*p) { + error = "colour parse error"; + goto done; + } + nametype = *p; + SKIPNONSPACE(p); + SKIPSPACE(p); + colname = p; + SKIPNONSPACE(p); + if(nametype == 's') + continue; /* skip symbolic colour names */ + + if(!color_to_rgb(colname, p - colname, &rgb)) + continue; + + memcpy(nextkey, line, cpp); + if(indexed) { + SDL_Color *c = im_colors + index; + c->r = (Uint8)(rgb >> 16); + c->g = (Uint8)(rgb >> 8); + c->b = (Uint8)(rgb); + pixel = index; + } else + pixel = rgb; + add_colorhash(colors, nextkey, cpp, pixel); + nextkey += cpp; + if(rgb == 0xffffffff) + SDL_SetColorKey(image, SDL_SRCCOLORKEY, pixel); + break; + } + } + + /* Read the pixels */ + pixels_len = w * cpp; + dst = image->pixels; + for(y = 0; y < h; y++) { + line = get_next_line(xpmlines, src, pixels_len); + if(indexed) { + /* optimization for some common cases */ + if(cpp == 1) + for(x = 0; x < w; x++) + dst[x] = (Uint8)QUICK_COLORHASH(colors, + line + x); + else + for(x = 0; x < w; x++) + dst[x] = (Uint8)get_colorhash(colors, + line + x * cpp, + cpp); + } else { + for (x = 0; x < w; x++) + ((Uint32*)dst)[x] = get_colorhash(colors, + line + x * cpp, + cpp); + } + dst += image->pitch; + } + +done: + if(error) { + if ( src ) + SDL_RWseek(src, start, RW_SEEK_SET); + if ( image ) { + SDL_FreeSurface(image); + image = NULL; + } + IMG_SetError(error); + } + free(keystrings); + free_colorhash(colors); + free(linebuf); + return(image); +} + +/* Load a XPM type image from an RWops datasource */ +SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) +{ + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + return load_xpm(NULL, src); +} + +SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +{ + return load_xpm(xpm, NULL); +} + +#else /* not LOAD_XPM */ + +/* See if an image is contained in a data source */ +int IMG_isXPM(SDL_RWops *src) +{ + return(0); +} + + +/* Load a XPM type image from an SDL datasource */ +SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) +{ + return(NULL); +} + +SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +{ + return NULL; +} +#endif /* not LOAD_XPM */ diff --git a/IMG_xv.c b/IMG_xv.c new file mode 100644 index 0000000..5427147 --- /dev/null +++ b/IMG_xv.c @@ -0,0 +1,164 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a XV thumbnail image file loading framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_XV + +static int get_line(SDL_RWops *src, char *line, int size) +{ + while ( size > 0 ) { + if ( SDL_RWread(src, line, 1, 1) <= 0 ) { + return -1; + } + if ( *line == '\r' ) { + continue; + } + if ( *line == '\n' ) { + *line = '\0'; + return 0; + } + ++line; + --size; + } + /* Out of space for the line */ + return -1; +} + +static int get_header(SDL_RWops *src, int *w, int *h) +{ + char line[1024]; + + *w = 0; + *h = 0; + + /* Check the header magic */ + if ( (get_line(src, line, sizeof(line)) < 0) || + (memcmp(line, "P7 332", 6) != 0) ) { + return -1; + } + + /* Read the header */ + while ( get_line(src, line, sizeof(line)) == 0 ) { + if ( memcmp(line, "#BUILTIN:", 9) == 0 ) { + /* Builtin image, no data */ + break; + } + if ( memcmp(line, "#END_OF_COMMENTS", 16) == 0 ) { + if ( get_line(src, line, sizeof(line)) == 0 ) { + sscanf(line, "%d %d", w, h); + if ( *w >= 0 && *h >= 0 ) { + return 0; + } + } + break; + } + } + /* No image data */ + return -1; +} + +/* See if an image is contained in a data source */ +int IMG_isXV(SDL_RWops *src) +{ + int start; + int is_XV; + int w, h; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_XV = 0; + if ( get_header(src, &w, &h) == 0 ) { + is_XV = 1; + } + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_XV); +} + +/* Load a XV thumbnail image from an SDL datasource */ +SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; + SDL_Surface *surface = NULL; + int w, h; + Uint8 *pixels; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + /* Read the header */ + if ( get_header(src, &w, &h) < 0 ) { + error = "Unsupported image format"; + goto done; + } + + /* Create the 3-3-2 indexed palette surface */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0xe0, 0x1c, 0x03, 0); + if ( surface == NULL ) { + error = "Out of memory"; + goto done; + } + + /* Load the image data */ + for ( pixels = (Uint8 *)surface->pixels; h > 0; --h ) { + if ( SDL_RWread(src, pixels, w, 1) <= 0 ) { + error = "Couldn't read image data"; + goto done; + } + pixels += surface->pitch; + } + +done: + if ( error ) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + return surface; +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isXV(SDL_RWops *src) +{ + return(0); +} + +/* Load a XXX type image from an SDL datasource */ +SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_XV */ diff --git a/IMG_xxx.c b/IMG_xxx.c new file mode 100644 index 0000000..819583d --- /dev/null +++ b/IMG_xxx.c @@ -0,0 +1,87 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is a generic "format not supported" image framework */ + +#include + +#include "SDL/SDL_image.h" + +#ifdef LOAD_XXX + +/* See if an image is contained in a data source */ +int IMG_isXXX(SDL_RWops *src) +{ + int start; + int is_XXX; + + if ( !src ) + return 0; + start = SDL_RWtell(src); + is_XXX = 0; + + /* Detect the image here */ + + SDL_RWseek(src, start, RW_SEEK_SET); + return(is_XXX); +} + +/* Load a XXX type image from an SDL datasource */ +SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; + SDL_Surface *surface = NULL; + + if ( !src ) { + /* The error message has been set in SDL_RWFromFile */ + return NULL; + } + start = SDL_RWtell(src); + + /* Load the image here */ + + if ( error ) { + SDL_RWseek(src, start, RW_SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + return surface; +} + +#else + +/* See if an image is contained in a data source */ +int IMG_isXXX(SDL_RWops *src) +{ + return(0); +} + +/* Load a XXX type image from an SDL datasource */ +SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src) +{ + return(NULL); +} + +#endif /* LOAD_XXX */ diff --git a/Makefile.prizm b/Makefile.prizm new file mode 100644 index 0000000..1608449 --- /dev/null +++ b/Makefile.prizm @@ -0,0 +1,38 @@ +INCLUDE = -I./include -I/home/sylvain/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/include/openlibm/ +CFLAGS = -O2 $(INCLUDE) -lm -m4-nofpu -mb -ffreestanding -nostdlib -lcPNG -lczlib -lSDL_prizm -Wa,--dsp -DLOAD_GIF -DLOAD_LBM -DLOAD_PCX -DLOAD_PNM -DLOAD_TGA -DLOAD_XCF -DLOAD_BMP -DLOAD_PNG +AR = sh-elf-gcc-ar +RANLIB = sh-elf-gcc-ranlib +CC = sh-elf-gcc + +CONFIG_H = +TARGET = libSDL_image_prizm.a +SOURCES = \ + IMG.c \ + IMG_bmp.c \ + IMG_gif.c \ + IMG_jpg.c \ + IMG_lbm.c \ + IMG_pcx.c \ + IMG_png.c \ + IMG_pnm.c \ + IMG_tga.c \ + IMG_tif.c \ + IMG_webp.c \ + IMG_xcf.c \ + IMG_xpm.c \ + IMG_xv.c + +OBJECTS = $(SOURCES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + #cp $(CONFIG_H).default $(CONFIG_H) + $(AR) cr $@ $^ + $(RANLIB) $@ + +.c.o: + $(CC) $(INCLUDE) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJECTS) $(TARGET) diff --git a/SDL/SDL_image.h b/SDL/SDL_image.h new file mode 100644 index 0000000..8844bb1 --- /dev/null +++ b/SDL/SDL_image.h @@ -0,0 +1,138 @@ +/* + SDL_image: An example image loading library for use with SDL + Copyright (C) 1997-2012 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* A simple library to load images of various formats as SDL surfaces */ + +#ifndef _SDL_IMAGE_H +#define _SDL_IMAGE_H + +#include "SDL/SDL.h" +#include "SDL/SDL_version.h" +#include "SDL/begin_code.h" + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_IMAGE_MAJOR_VERSION 1 +#define SDL_IMAGE_MINOR_VERSION 2 +#define SDL_IMAGE_PATCHLEVEL 12 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_image library. + */ +#define SDL_IMAGE_VERSION(X) \ +{ \ + (X)->major = SDL_IMAGE_MAJOR_VERSION; \ + (X)->minor = SDL_IMAGE_MINOR_VERSION; \ + (X)->patch = SDL_IMAGE_PATCHLEVEL; \ +} + +/* This function gets the version of the dynamically linked SDL_image library. + it should NOT be used to fill a version structure, instead you should + use the SDL_IMAGE_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL IMG_Linked_Version(void); + +typedef enum +{ + IMG_INIT_JPG = 0x00000001, + IMG_INIT_PNG = 0x00000002, + IMG_INIT_TIF = 0x00000004, + IMG_INIT_WEBP = 0x00000008 +} IMG_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from IMG_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL IMG_Init(int flags); + +/* Unloads libraries loaded with IMG_Init */ +extern DECLSPEC void SDLCALL IMG_Quit(void); + +/* Load an image from an SDL data source. + The 'type' may be one of: "BMP", "GIF", "PNG", etc. + + If the image format supports a transparent pixel, SDL will set the + colorkey for the surface. You can enable RLE acceleration on the + surface afterwards by calling: + SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey); + */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type); +/* Convenience functions */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file); +extern DECLSPEC SDL_Surface * SDLCALL IMG_Load_RW(SDL_RWops *src, int freesrc); + +/* Invert the alpha of a surface for use with OpenGL + This function is now a no-op, and only provided for backwards compatibility. +*/ +extern DECLSPEC int SDLCALL IMG_InvertAlpha(int on); + +/* Functions to detect a file type, given a seekable source */ +extern DECLSPEC int SDLCALL IMG_isICO(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isCUR(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isBMP(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isGIF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isJPG(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isLBM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPCX(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPNG(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isPNM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isTIF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXCF(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXPM(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isXV(SDL_RWops *src); +extern DECLSPEC int SDLCALL IMG_isWEBP(SDL_RWops *src); + +/* Individual loading functions */ +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_RW(SDL_RWops *src); +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_RW(SDL_RWops *src); + +extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm); + +/* We'll use SDL for reporting errors */ +#define IMG_SetError SDL_SetError +#define IMG_GetError SDL_GetError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "SDL/close_code.h" + +#endif /* _SDL_IMAGE_H */ diff --git a/build b/build new file mode 100755 index 0000000..1fee4d9 --- /dev/null +++ b/build @@ -0,0 +1,4 @@ +make -f Makefile.prizm clean +make -f Makefile.prizm +cp libSDL_image_prizm.a ~/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/ +cp ./SDL/*.h ~/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/include/SDL/ diff --git a/cSDL_image1_2_12.cbp b/cSDL_image1_2_12.cbp new file mode 100644 index 0000000..1769d75 --- /dev/null +++ b/cSDL_image1_2_12.cbp @@ -0,0 +1,65 @@ + + + + + + diff --git a/cSDL_image1_2_12.layout b/cSDL_image1_2_12.layout new file mode 100644 index 0000000..7e5ac01 --- /dev/null +++ b/cSDL_image1_2_12.layout @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +