/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG.c |
---|
0,0 → 1,134 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* A simple library to load images of various formats as SDL surfaces */ |
#include <stdio.h> |
#include <string.h> |
#include <ctype.h> |
#include "SDL_image.h" |
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) |
/* Table of image detection and loading functions */ |
static struct { |
char *type; |
int (*is)(SDL_RWops *src); |
SDL_Surface *(*load)(SDL_RWops *src); |
} supported[] = { |
/* keep magicless formats first */ |
{ "TGA", 0, IMG_LoadTGA_RW }, |
{ "BMP", IMG_isBMP, IMG_LoadBMP_RW }, |
{ "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */ |
{ "XPM", IMG_isXPM, IMG_LoadXPM_RW }, |
{ "XCF", IMG_isXCF, IMG_LoadXCF_RW }, |
{ "PCX", IMG_isPCX, IMG_LoadPCX_RW }, |
{ "GIF", IMG_isGIF, IMG_LoadGIF_RW }, |
{ "JPG", IMG_isJPG, IMG_LoadJPG_RW }, |
{ "TIF", IMG_isTIF, IMG_LoadTIF_RW }, |
{ "PNG", IMG_isPNG, IMG_LoadPNG_RW } |
}; |
/* Load an image from a file */ |
SDL_Surface *IMG_Load(const char *file) |
{ |
SDL_RWops *src = SDL_RWFromFile(file, "rb"); |
char *ext = strrchr(file, '.'); |
if(ext) |
ext++; |
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); |
} |
/* Portable case-insensitive string compare function */ |
int IMG_string_equals(const char *str1, const char *str2) |
{ |
while ( *str1 && *str2 ) { |
if ( toupper((unsigned char)*str1) != |
toupper((unsigned char)*str2) ) |
break; |
++str1; |
++str2; |
} |
return (!*str1 && !*str2); |
} |
/* Load an image from an SDL datasource, optionally specifying the type */ |
SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type) |
{ |
int i, start; |
SDL_Surface *image; |
/* Make sure there is something to do.. */ |
if ( src == NULL ) { |
return(NULL); |
} |
/* See whether or not this data source can handle seeking */ |
if ( SDL_RWseek(src, 0, SEEK_CUR) < 0 ) { |
IMG_SetError("Can't seek in this data source"); |
return(NULL); |
} |
/* Detect the type of image being loaded */ |
start = SDL_RWtell(src); |
image = NULL; |
for ( i=0; i < ARRAYSIZE(supported); ++i ) { |
if( (supported[i].is |
&& (SDL_RWseek(src, start, SEEK_SET), |
supported[i].is(src))) |
|| (type && IMG_string_equals(type, supported[i].type))) { |
#ifdef DEBUG_IMGLIB |
SDL_printf("IMGLIB: Loading image as %s\n", |
supported[i].type); |
#endif |
SDL_RWseek(src, start, SEEK_SET); |
image = supported[i].load(src); |
break; |
} |
} |
/* Clean up, check for errors, and return */ |
if ( freesrc ) { |
SDL_RWclose(src); |
} |
if ( i == ARRAYSIZE(supported) ) { |
IMG_SetError("Unsupported image format"); |
} |
return(image); |
} |
/* 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; |
} |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_bmp.c |
---|
0,0 → 1,69 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* This is a BMP image file loading framework */ |
#include <stdio.h> |
#include <string.h> |
#include "SDL_image.h" |
#ifdef LOAD_BMP |
/* See if an image is contained in a data source */ |
int IMG_isBMP(SDL_RWops *src) |
{ |
int is_BMP; |
char magic[2]; |
is_BMP = 0; |
if ( SDL_RWread(src, magic, 2, 1) ) { |
if ( strncmp(magic, "BM", 2) == 0 ) { |
is_BMP = 1; |
} |
} |
return(is_BMP); |
} |
/* Load a BMP type image from an SDL datasource */ |
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src) |
{ |
return(SDL_LoadBMP_RW(src, 0)); |
} |
#else |
/* See if an image is contained in a data source */ |
int IMG_isBMP(SDL_RWops *src) |
{ |
return(0); |
} |
/* Load a BMP type image from an SDL datasource */ |
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src) |
{ |
return(NULL); |
} |
#endif /* LOAD_BMP */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_gif.c |
---|
0,0 → 1,604 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* This is a GIF image file loading framework */ |
#include <stdio.h> |
#include <string.h> |
#include "SDL_image.h" |
#ifdef LOAD_GIF |
/* See if an image is contained in a data source */ |
int IMG_isGIF(SDL_RWops *src) |
{ |
int is_GIF; |
char magic[6]; |
is_GIF = 0; |
if ( SDL_RWread(src, magic, 6, 1) ) { |
if ( (strncmp(magic, "GIF", 3) == 0) && |
((memcmp(magic + 3, "87a", 3) == 0) || |
(memcmp(magic + 3, "89a", 3) == 0)) ) { |
is_GIF = 1; |
} |
} |
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 <stdio.h> |
#include <string.h> |
#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.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) |
{ |
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 ) { |
goto done; |
} |
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; |
} |
strncpy(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: |
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; |
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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_jpg.c |
---|
0,0 → 1,242 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* This is a JPEG image file loading framework */ |
#include <stdio.h> |
#include <string.h> |
#include "SDL_image.h" |
#ifdef LOAD_JPG |
#include <jpeglib.h> |
/* Define this for fast loading and not as good image quality */ |
/*#define FAST_JPEG*/ |
/* See if an image is contained in a data source */ |
int IMG_isJPG(SDL_RWops *src) |
{ |
int is_JPG; |
Uint8 magic[4]; |
is_JPG = 0; |
if ( SDL_RWread(src, magic, 2, 1) ) { |
if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) { |
SDL_RWread(src, magic, 4, 1); |
SDL_RWread(src, magic, 4, 1); |
if ( memcmp((char *)magic, "JFIF", 4) == 0 ) { |
is_JPG = 1; |
} |
} |
} |
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 int 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 = 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 */ |
} |
/* Load a JPEG type image from an SDL datasource */ |
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) |
{ |
struct jpeg_error_mgr errmgr; |
struct jpeg_decompress_struct cinfo; |
JSAMPROW rowptr[1]; |
SDL_Surface *surface; |
/* Create a decompression structure and load the JPEG header */ |
cinfo.err = jpeg_std_error(&errmgr); |
jpeg_create_decompress(&cinfo); |
jpeg_SDL_RW_src(&cinfo, src); |
jpeg_read_header(&cinfo, TRUE); |
/* 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 |
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 ) { |
IMG_SetError("Out of memory"); |
goto done; |
} |
/* Decompress the image */ |
jpeg_start_decompress(&cinfo); |
while ( cinfo.output_scanline < cinfo.output_height ) { |
rowptr[0] = (JSAMPROW)(Uint8 *)surface->pixels + |
cinfo.output_scanline * surface->pitch; |
jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1); |
} |
jpeg_finish_decompress(&cinfo); |
/* Clean up and return */ |
done: |
jpeg_destroy_decompress(&cinfo); |
return(surface); |
} |
#else |
/* 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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_pcx.c |
---|
0,0 → 1,253 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* |
* 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 <stdio.h> |
#include <stdlib.h> |
#include "SDL_endian.h" |
#include "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 is_PCX; |
const int ZSoft_Manufacturer = 10; |
const int PC_Paintbrush_Version = 5; |
const int PCX_RunLength_Encoding = 1; |
struct PCXheader pcxh; |
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) ) { |
is_PCX = 1; |
} |
} |
return(is_PCX); |
} |
/* Load a PCX type image from an SDL datasource */ |
SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) |
{ |
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 ) { |
goto done; |
} |
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; |
buf = malloc(bpl); |
row = surface->pixels; |
for ( y=0; y<surface->h; ++y ) { |
/* decode a scan line to a temporary buffer first */ |
int i, count = 0; |
Uint8 ch; |
Uint8 *dst = (src_bits == 8) ? row : buf; |
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; |
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_FreeSurface(surface); |
IMG_SetError(error); |
surface = NULL; |
} |
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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_png.c |
---|
0,0 → 1,286 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* This is a PNG image file loading framework */ |
#include <stdlib.h> |
#include <stdio.h> |
#include "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_endian.h" |
#ifdef macintosh |
#define MACOS |
#endif |
#include <png.h> |
#define PNG_BYTES_TO_CHECK 4 |
/* See if an image is contained in a data source */ |
int IMG_isPNG(SDL_RWops *src) |
{ |
unsigned char buf[PNG_BYTES_TO_CHECK]; |
/* Read in the signature bytes */ |
if (SDL_RWread(src, buf, 1, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) |
return 0; |
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */ |
return( !png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); |
} |
/* 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 *)png_get_io_ptr(ctx); |
SDL_RWread(src, area, size, 1); |
} |
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) |
{ |
SDL_Surface *volatile surface; |
png_structp png_ptr; |
png_infop info_ptr; |
png_uint_32 width, height; |
int bit_depth, color_type, interlace_type; |
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; |
/* Initialize the data we will clean up when we're done */ |
png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL; |
/* Check to make sure we have something to do */ |
if ( ! src ) { |
goto done; |
} |
/* Create the PNG loading context structure */ |
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, |
NULL,NULL,NULL); |
if (png_ptr == NULL){ |
IMG_SetError("Couldn't allocate memory for PNG file"); |
goto done; |
} |
/* Allocate/initialize the memory for image information. REQUIRED. */ |
info_ptr = png_create_info_struct(png_ptr); |
if (info_ptr == NULL) { |
IMG_SetError("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. |
*/ |
if ( setjmp(png_ptr->jmpbuf) ) { |
IMG_SetError("Error reading the PNG file."); |
goto done; |
} |
/* Set up the input control */ |
png_set_read_fn(png_ptr, src, png_read_data); |
/* Read PNG header info */ |
png_read_info(png_ptr, info_ptr); |
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 */ |
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). |
*/ |
png_set_packing(png_ptr); |
/* scale greyscale values to the range 0..255 */ |
if(color_type == PNG_COLOR_TYPE_GRAY) |
png_set_expand(png_ptr); |
/* For images with a single "transparent colour", set colour key; |
if more than one index has transparency, use full alpha channel */ |
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
int num_trans; |
Uint8 *trans; |
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, |
&transv); |
if(color_type == PNG_COLOR_TYPE_PALETTE) { |
if(num_trans == 1) { |
/* exactly one transparent value: set colour key */ |
ckey = trans[0]; |
} else |
png_set_expand(png_ptr); |
} else |
ckey = 0; /* actual value will be set later */ |
} |
if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) |
png_set_gray_to_rgb(png_ptr); |
png_read_update_info(png_ptr, info_ptr); |
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 ; |
if ( color_type != PNG_COLOR_TYPE_PALETTE ) { |
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { |
Rmask = 0x000000FF; |
Gmask = 0x0000FF00; |
Bmask = 0x00FF0000; |
Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0; |
} else { |
int s = (info_ptr->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*info_ptr->channels, Rmask,Gmask,Bmask,Amask); |
if ( surface == NULL ) { |
IMG_SetError("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) ) { |
IMG_SetError("Out of memory"); |
SDL_FreeSurface(surface); |
surface = NULL; |
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 */ |
png_read_image(png_ptr, row_pointers); |
/* read rest of file, get additional chunks in info_ptr - REQUIRED */ |
png_read_end(png_ptr, info_ptr); |
/* Load the palette, if any */ |
palette = surface->format->palette; |
if ( 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 (info_ptr->num_palette > 0 ) { |
palette->ncolors = info_ptr->num_palette; |
for( i=0; i<info_ptr->num_palette; ++i ) { |
palette->colors[i].b = info_ptr->palette[i].blue; |
palette->colors[i].g = info_ptr->palette[i].green; |
palette->colors[i].r = info_ptr->palette[i].red; |
} |
} |
} |
done: /* Clean up and return */ |
png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0, |
(png_infopp)0); |
if ( row_pointers ) { |
free(row_pointers); |
} |
return(surface); |
} |
#else |
/* 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) |
{ |
return(NULL); |
} |
#endif /* LOAD_PNG */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_pnm.c |
---|
0,0 → 1,242 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* |
* 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 <stdio.h> |
#include <stdlib.h> |
#include <ctype.h> |
#include <string.h> |
#include "SDL_image.h" |
#ifdef LOAD_PNM |
/* See if an image is contained in a data source */ |
int IMG_isPNM(SDL_RWops *src) |
{ |
char magic[2]; |
/* |
* 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 |
*/ |
return (SDL_RWread(src, magic, 2, 1) |
&& magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6'); |
} |
/* 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) |
{ |
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 } kind; |
#define ERROR(s) do { error = (s); goto done; } while(0) |
if(!src) |
return NULL; |
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_FreeSurface(surface); |
IMG_SetError(error); |
surface = NULL; |
} |
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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_tga.c |
---|
0,0 → 1,321 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include "SDL_endian.h" |
#include "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 <f91-men@nada.kth.se>: initial version |
* 2000-06-26 Mattias Engdegård <f91-men@nada.kth.se>: read greyscale TGAs |
* 2000-08-09 Mattias Engdegård <f91-men@nada.kth.se>: 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) |
static void unsupported(void) |
{ |
IMG_SetError("unsupported TGA format"); |
} |
/* Load a TGA type image from an SDL datasource */ |
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) |
{ |
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; |
Uint32 rmask, gmask, bmask, amask; |
Uint8 *dst; |
int i; |
int bpp; |
int lstep; |
Uint32 pixel; |
int count, rep; |
if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) |
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 error; |
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 error; |
/* Treat greyscale as 8bpp indexed images */ |
indexed = grey = 1; |
break; |
default: |
unsupported(); |
return NULL; |
} |
bpp = (hdr.pixel_bits + 7) >> 3; |
rmask = gmask = bmask = amask = 0; |
switch(hdr.pixel_bits) { |
case 8: |
if(!indexed) { |
unsupported(); |
return NULL; |
} |
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: |
unsupported(); |
return NULL; |
} |
if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE |
|| hdr.flags & TGA_ORIGIN_RIGHT) { |
unsupported(); |
return NULL; |
} |
SDL_RWseek(src, hdr.infolen, 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(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, 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; |
error: |
IMG_SetError("Error reading TGA data"); |
return NULL; |
} |
#else |
/* dummy TGA load routine */ |
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) |
{ |
return(NULL); |
} |
#endif /* LOAD_TGA */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_tif.c |
---|
0,0 → 1,174 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
5/29/2000: TIFF loader written. Mark Baker (mbaker@0x7a69.net) |
2000-07-28: Fixed two off-by one bugs in reversal loop and made it work on |
big-endian machines (Mattias) |
2000-08-09: Removed alpha inversion (Mattias) |
*/ |
/* This is a TIFF image file loading framework */ |
#include <stdio.h> |
#include "SDL_image.h" |
#ifdef LOAD_TIF |
#include <tiffio.h> |
/* |
* 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 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, SEEK_END); |
size = SDL_RWtell((SDL_RWops*)fd); |
SDL_RWseek((SDL_RWops*)fd, save_pos, SEEK_SET); |
return size; |
} |
int IMG_isTIF(SDL_RWops* src) |
{ |
TIFF* tiff; |
TIFFErrorHandler prev_handler; |
/* Suppress output from libtiff */ |
prev_handler = TIFFSetErrorHandler(NULL); |
/* Attempt to process the given file data */ |
/* turn off memory mapped access with the m flag */ |
tiff = TIFFClientOpen("SDL_image", "rm", (thandle_t)src, |
tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, NULL, NULL); |
/* Reset the default error handler, since it can be useful for info */ |
TIFFSetErrorHandler(prev_handler); |
/* If it's not a TIFF, then tiff will be NULL. */ |
if(!tiff) |
return 0; |
/* Free up any dynamically allocated memory libtiff uses */ |
TIFFClose(tiff); |
return 1; |
} |
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) |
{ |
TIFF* tiff; |
SDL_Surface* surface = NULL; |
Uint32 img_width, img_height; |
Uint32 Rmask, Gmask, Bmask, Amask, mask; |
Uint32 x, y; |
Uint32 half; |
/* turn off memory mapped access with the m flag */ |
tiff = TIFFClientOpen("SDL_image", "rm", (thandle_t)src, |
tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, NULL, NULL); |
if(!tiff) |
return NULL; |
/* Retrieve the dimensions of the image from the TIFF tags */ |
TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width); |
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) |
return NULL; |
if(!TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0)) |
return NULL; |
/* 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; |
} |
} |
TIFFClose(tiff); |
return surface; |
} |
#else |
/* 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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_xcf.c |
---|
0,0 → 1,796 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
XCF support by Bernhard J. Pietsch <bjtp@gmx.net> |
*/ |
/* This is a XCF image file loading framework */ |
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include "SDL_image.h" |
#ifdef LOAD_XCF |
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" |
}; |
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; |
} xcf_layer; |
typedef struct { |
Uint32 width; |
Uint32 height; |
char * name; |
xcf_prop * properties; |
Uint32 hierarchy_file_offset; |
Uint32 color; |
Uint32 opacity; |
int selection : 1; |
} 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 is_XCF; |
char magic[14]; |
is_XCF = 0; |
if ( SDL_RWread(src, magic, 14, 1) ) { |
if (strncmp(magic, "gimp xcf ", 9) == 0) { |
is_XCF = 1; |
} |
} |
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)); |
} |
void xcf_read_property (SDL_RWops * src, xcf_prop * prop) { |
prop->id = SDL_ReadBE32 (src); |
prop->length = SDL_ReadBE32 (src); |
printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length); |
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; |
default: |
// SDL_RWread (src, &prop->data, prop->length, 1); |
SDL_RWseek (src, prop->length, SEEK_CUR); |
} |
} |
void free_xcf_header (xcf_header * h) { |
if (h->cm_num) |
free (h->cm_map); |
free (h); |
} |
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) { |
int i; |
h->cm_num = prop.data.colormap.num; |
h->cm_map = (char *) malloc (sizeof (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; |
} |
void free_xcf_layer (xcf_layer * l) { |
free (l->name); |
free (l); |
} |
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; |
} |
} while (prop.id != PROP_END); |
l->hierarchy_file_offset = SDL_ReadBE32 (src); |
l->layer_mask_offset = SDL_ReadBE32 (src); |
return l; |
} |
void free_xcf_channel (xcf_channel * c) { |
free (c->name); |
free (c); |
} |
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; |
default: |
} |
} while (prop.id != PROP_END); |
l->hierarchy_file_offset = SDL_ReadBE32 (src); |
return l; |
} |
void free_xcf_hierarchy (xcf_hierarchy * h) { |
free (h->level_file_offsets); |
free (h); |
} |
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; |
} |
void free_xcf_level (xcf_level * l) { |
free (l->tile_file_offsets); |
free (l); |
} |
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; |
} |
void free_xcf_tile (unsigned char * t) { |
free (t); |
} |
unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) { |
unsigned char * load; |
load = (char *) malloc (len); // expect this is okay |
SDL_RWread (src, load, len, 1); |
return load; |
} |
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 = (char *) malloc (len); |
reallen = SDL_RWread (src, t, 1, len); |
data = (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; |
} |
void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) { |
Uint32 c; |
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); |
} |
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, width, height, i, j; |
Uint32 *row; |
SDL_RWseek (src, layer->hierarchy_file_offset, 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], 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], 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); |
} |
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); |
} |
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { |
SDL_Surface *surface, *lays; |
xcf_header * head; |
xcf_layer * layer; |
xcf_channel ** channel; |
int read_error, chnls, i, offsets; |
Uint32 offset, fp; |
unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int); |
/* Initialize the data we will clean up when we're done */ |
surface = NULL; |
read_error = 0; |
/* Check to make sure we have something to do */ |
if ( ! src ) { |
goto done; |
} |
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 ) { |
IMG_SetError("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 ) { |
IMG_SetError("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], 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; |
free_xcf_layer (layer); |
SDL_BlitSurface (lays, &rs, surface, &rd); |
} |
SDL_FreeSurface (lays); |
SDL_RWseek (src, fp, 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, SEEK_SET); |
channel [chnls++] = (read_xcf_channel (src)); |
SDL_RWseek (src, fp, SEEK_SET); |
} |
if (chnls) { |
SDL_Surface * chs; |
chs = SDL_AllocSurface(SDL_SWSURFACE, head->width, head->height, 32, |
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); |
if (chs == NULL) { |
IMG_SetError("Out of memory"); |
goto done; |
} |
for (i = 0; i < chnls; i++) { |
// printf ("CNLBLT %i\n", i); |
if (!channel [i]->selection) { |
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 ( read_error ) { |
SDL_FreeSurface(surface); |
IMG_SetError("Error reading XCF data"); |
surface = NULL; |
} |
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 */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/IMG_xpm.c |
---|
0,0 → 1,462 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
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 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* This is an XPM image file loading framework */ |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <ctype.h> |
#include "SDL_image.h" |
#ifdef LOAD_XPM |
/* See if an image is contained in a data source */ |
int IMG_isXPM(SDL_RWops *src) |
{ |
int is_XPM; |
char magic[10]; |
is_XPM = 0; |
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) { |
if(memcmp(magic, "/* XPM */", 9) == 0) { |
is_XPM = 1; |
} |
} |
return(is_XPM); |
} |
static char *SDL_RWgets(char *string, int maxlen, SDL_RWops *src) |
{ |
int i; |
for ( i=0; i<(maxlen-1); ++i ) { |
if ( SDL_RWread(src, &string[i], 1, 1) <= 0 ) { |
/* EOF or error */ |
if ( i == 0 ) { |
/* Hmm, EOF on initial read, return NULL */ |
return NULL; |
} |
break; |
} |
/* In this case it's okay to use either '\r' or '\n' |
as line separators because blank lines are just |
ignored by the XPM format. |
*/ |
if ( (string[i] == '\n') || (string[i] == '\r') ) { |
break; |
} |
} |
string[i] = '\0'; |
return(string); |
} |
/* 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) |
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); |
} |
} |
#define ARRAYSIZE(a) (int)(sizeof(a) / sizeof((a)[0])) |
/* |
* convert colour spec to RGB (in 0xrrggbb format). |
* return 1 if successful. may scribble on the colorspec buffer. |
*/ |
static int color_to_rgb(char *spec, 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]; |
++spec; |
switch(strlen(spec)) { |
case 3: |
buf[0] = buf[1] = spec[0]; |
buf[2] = buf[3] = spec[1]; |
buf[4] = buf[5] = spec[2]; |
break; |
case 6: |
memcpy(buf, spec, 6); |
break; |
case 12: |
buf[0] = spec[0]; |
buf[1] = spec[1]; |
buf[2] = spec[4]; |
buf[3] = spec[5]; |
buf[4] = spec[8]; |
buf[5] = spec[9]; |
break; |
} |
buf[6] = '\0'; |
*rgb = strtol(buf, NULL, 16); |
return 1; |
} else { |
int i; |
for(i = 0; i < ARRAYSIZE(known); i++) |
if(IMG_string_equals(known[i].name, spec)) { |
*rgb = known[i].rgb; |
return 1; |
} |
return 0; |
} |
} |
static char *skipspace(char *p) |
{ |
while(isspace((unsigned char)*p)) |
++p; |
return p; |
} |
static char *skipnonspace(char *p) |
{ |
while(!isspace((unsigned char)*p) && *p) |
++p; |
return p; |
} |
#ifndef MAX |
#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
#endif |
/* Load a XPM type image from an SDL datasource */ |
SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) |
{ |
SDL_Surface *image; |
char line[1024]; |
char *here; |
int index; |
int x, y; |
int w, h, ncolors, cpp; |
int pixels_len; |
char *pixels = NULL; |
int indexed; |
Uint8 *dst; |
struct color_hash *colors; |
SDL_Color *im_colors = NULL; |
char *keystrings, *nextkey; |
char *error = NULL; |
/* Skip to the first string, which describes the image */ |
do { |
here = SDL_RWgets(line, sizeof(line), src); |
if ( !here ) { |
IMG_SetError("Premature end of data"); |
return(NULL); |
} |
here = skipspace(here); |
} while(*here != '"'); |
/* |
* The header string of an XPMv3 image has the format |
* |
* <width> <height> <ncolors> <cpp> [ <hotspot_x> <hotspot_y> ] |
* |
* 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(here + 1, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 |
|| w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { |
IMG_SetError("Invalid format description"); |
return(NULL); |
} |
keystrings = malloc(ncolors * cpp); |
if(!keystrings) { |
IMG_SetError("Out of memory"); |
free(pixels); |
return NULL; |
} |
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?) */ |
free(pixels); |
return(NULL); |
} |
/* Read the colors */ |
colors = create_colorhash(ncolors); |
if ( ! colors ) { |
error = "Out of memory"; |
goto done; |
} |
for(index = 0; index < ncolors; ++index ) { |
char *key; |
int len; |
do { |
here = SDL_RWgets(line, sizeof(line), src); |
if(!here) { |
error = "Premature end of data"; |
goto done; |
} |
here = skipspace(here); |
} while(*here != '"'); |
++here; |
len = strlen(here); |
if(len < cpp + 7) |
continue; /* cannot be a valid line */ |
key = here; |
key[cpp] = '\0'; |
here += cpp + 1; |
/* parse a colour definition */ |
for(;;) { |
char nametype; |
char *colname; |
char delim; |
Uint32 rgb; |
here = skipspace(here); |
nametype = *here; |
here = skipnonspace(here); |
here = skipspace(here); |
colname = here; |
while(*here && !isspace((unsigned char)*here) |
&& *here != '"') |
here++; |
if(!*here) { |
error = "color parse error"; |
goto done; |
} |
if(nametype == 's') |
continue; /* skip symbolic colour names */ |
delim = *here; |
*here = '\0'; |
if(delim) |
here++; |
if(!color_to_rgb(colname, &rgb)) |
continue; |
memcpy(nextkey, key, cpp); |
if(indexed) { |
SDL_Color *c = im_colors + index; |
c->r = rgb >> 16; |
c->g = rgb >> 8; |
c->b = rgb; |
add_colorhash(colors, nextkey, cpp, index); |
} else |
add_colorhash(colors, nextkey, cpp, rgb); |
nextkey += cpp; |
if(rgb == 0xffffffff) |
SDL_SetColorKey(image, SDL_SRCCOLORKEY, |
indexed ? index : rgb); |
break; |
} |
} |
/* Read the pixels */ |
pixels_len = w * cpp; |
pixels = malloc(MAX(pixels_len + 5, 20)); |
if(!pixels) { |
error = "Out of memory"; |
goto done; |
} |
dst = image->pixels; |
for (y = 0; y < h; ) { |
char *s; |
char c; |
do { |
if(SDL_RWread(src, &c, 1, 1) <= 0) { |
error = "Premature end of data"; |
goto done; |
} |
} while(c == ' '); |
if(c != '"') { |
/* comment or empty line, skip it */ |
while(c != '\n' && c != '\r') { |
if(SDL_RWread(src, &c, 1, 1) <= 0) { |
error = "Premature end of data"; |
goto done; |
} |
} |
continue; |
} |
if(SDL_RWread(src, pixels, pixels_len + 3, 1) <= 0) { |
error = "Premature end of data"; |
goto done; |
} |
s = pixels; |
if(indexed) { |
/* optimization for some common cases */ |
if(cpp == 1) |
for(x = 0; x < w; x++) |
dst[x] = QUICK_COLORHASH(colors, |
s + x); |
else |
for(x = 0; x < w; x++) |
dst[x] = get_colorhash(colors, |
s + x * cpp, |
cpp); |
} else { |
for (x = 0; x < w; x++) |
((Uint32*)dst)[x] = get_colorhash(colors, |
s + x * cpp, |
cpp); |
} |
dst += image->pitch; |
y++; |
} |
done: |
if(error) { |
if(image) |
SDL_FreeSurface(image); |
image = NULL; |
IMG_SetError(error); |
} |
free(pixels); |
free(keystrings); |
free_colorhash(colors); |
return(image); |
} |
#else |
/* 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); |
} |
#endif /* LOAD_XPM */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/Makefile |
---|
0,0 → 1,7 |
OBJS = IMG_bmp.o IMG.o IMG_gif.o IMG_jpg.o IMG_pcx.o IMG_png.o IMG_pnm.o \ |
IMG_tga.o IMG_tif.o IMG_xcf.o IMG_xpm.o |
OUTFILE = ../lib/libSDL_image.a |
CFLAGS = -I../include -D_REENTRANT -DLOAD_BMP -DLOAD_GIF -DLOAD_JPG \ |
-DLOAD_PCX -DLOAD_PNG -DLOAD_PNM -DLOAD_TGA -DLOAD_XPM |
include $(MENUETDEV)/makefiles/Makefile_for_lib |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/SDL_image.h |
---|
0,0 → 1,93 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program 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 General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
/* A simple library to load images of various formats as SDL surfaces */ |
#ifndef _IMG_h |
#define _IMG_h |
#include "SDL.h" |
#include "begin_code.h" |
/* Set up for C function definitions, even when using C++ */ |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* 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 *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, |
char *type); |
/* Convenience functions */ |
extern DECLSPEC SDL_Surface *IMG_Load(const char *file); |
extern DECLSPEC SDL_Surface *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 IMG_InvertAlpha(int on); |
/* Functions to detect a file type, given a seekable source */ |
extern DECLSPEC int IMG_isBMP(SDL_RWops *src); |
extern DECLSPEC int IMG_isPNM(SDL_RWops *src); |
extern DECLSPEC int IMG_isXPM(SDL_RWops *src); |
extern DECLSPEC int IMG_isXCF(SDL_RWops *src); |
extern DECLSPEC int IMG_isPCX(SDL_RWops *src); |
extern DECLSPEC int IMG_isGIF(SDL_RWops *src); |
extern DECLSPEC int IMG_isJPG(SDL_RWops *src); |
extern DECLSPEC int IMG_isTIF(SDL_RWops *src); |
extern DECLSPEC int IMG_isPNG(SDL_RWops *src); |
/* Individual loading functions */ |
extern DECLSPEC SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadGIF_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src); |
extern DECLSPEC SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src); |
/* We'll use SDL for reporting errors */ |
#define IMG_SetError SDL_SetError |
#define IMG_GetError SDL_GetError |
/* used internally, NOT an exported function */ |
extern DECLSPEC int IMG_string_equals(const char *str1, const char *str2); |
/* Ends C function definitions when using C++ */ |
#ifdef __cplusplus |
} |
#endif |
#include "close_code.h" |
#endif /* _IMG_h */ |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/test/Makefile |
---|
0,0 → 1,6 |
OUTFILE = showimg |
OBJS = showimage.o |
LIBS = -L../../lib -lSDL -lSDL_image -lSDL -lpng -ljpeg -lz |
CFLAGS = -I../../include -I.. |
include $(MENUETDEV)/makefiles/Makefile_for_program |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/test/showimage.c |
---|
0,0 → 1,185 |
/* |
SHOW: A test application for the SDL image loading library. |
Copyright (C) 1999 Sam Lantinga |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program 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 General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include "SDL.h" |
#include "SDL_image.h" |
/* Draw a Gimpish background pattern to show transparency in the image */ |
void draw_background(SDL_Surface *screen) |
{ |
Uint8 *dst = screen->pixels; |
int x, y; |
int bpp = screen->format->BytesPerPixel; |
Uint32 col[2]; |
col[0] = SDL_MapRGB(screen->format, 0x66, 0x66, 0x66); |
col[1] = SDL_MapRGB(screen->format, 0x99, 0x99, 0x99); |
for(y = 0; y < screen->h; y++) { |
for(x = 0; x < screen->w; x++) { |
/* use an 8x8 checkerboard pattern */ |
Uint32 c = col[((x ^ y) >> 3) & 1]; |
switch(bpp) { |
case 1: |
dst[x] = c; |
break; |
case 2: |
((Uint16 *)dst)[x] = c; |
break; |
case 3: |
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { |
dst[x * 3] = c; |
dst[x * 3 + 1] = c >> 8; |
dst[x * 3 + 2] = c >> 16; |
} else { |
dst[x * 3] = c >> 16; |
dst[x * 3 + 1] = c >> 8; |
dst[x * 3 + 2] = c; |
} |
break; |
case 4: |
((Uint32 *)dst)[x] = c; |
break; |
} |
} |
dst += screen->pitch; |
} |
} |
int app_main(int argc, char *argv[]) |
{ |
Uint32 flags; |
SDL_Surface *screen, *image; |
int i, depth, done; |
SDL_Event event; |
argv[1]="../1/test.png"; |
argc=2; |
/* Initialize the SDL library */ |
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { |
SDL_printf("Couldn't initialize SDL: %s\n",SDL_GetError()); |
return(255); |
} |
flags = SDL_SWSURFACE; |
for ( i=1; i<argc; ++i ) { |
SDL_ShowCursor(0); |
image = IMG_Load(argv[i]); |
if ( image == NULL ) { |
SDL_printf("Couldn't load %s: %s\n", |
argv[i], SDL_GetError()); |
continue; |
} |
{ |
static char xttl[128]; |
sprintf(xttl,"Showimage - filename is \"%s\"",argv[1]); |
SDL_WM_SetCaption(xttl, "showimage"); |
} |
/* Create a display for the image */ |
depth = SDL_VideoModeOK(image->w, image->h, 32, flags); |
/* Use the deepest native mode, except that we emulate 32bpp |
for viewing non-indexed images on 8bpp screens */ |
if ( depth == 0 ) { |
if ( image->format->BytesPerPixel > 1 ) { |
depth = 32; |
} else { |
depth = 8; |
} |
} else |
if ( (image->format->BytesPerPixel > 1) && (depth == 8) ) { |
depth = 32; |
} |
if(depth == 8) |
flags |= SDL_HWPALETTE; |
screen = SDL_SetVideoMode(image->w, image->h, depth, flags); |
if ( screen == NULL ) { |
SDL_printf("Couldn't set %dx%dx%d video mode: %s\n", |
image->w, image->h, depth, SDL_GetError()); |
continue; |
} |
/* Set the palette, if one exists */ |
if ( image->format->palette ) { |
SDL_SetColors(screen, image->format->palette->colors, |
0, image->format->palette->ncolors); |
} |
/* Draw a background pattern if the surface has transparency */ |
if(image->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY)) |
draw_background(screen); |
/* Display the image */ |
SDL_BlitSurface(image, NULL, screen, NULL); |
SDL_UpdateRect(screen, 0, 0, 0, 0); |
done = 0; |
while ( ! done ) { |
if ( SDL_PollEvent(&event) ) { |
switch (event.type) { |
case SDL_KEYUP: |
switch (event.key.keysym.sym) { |
case SDLK_LEFT: |
if ( i > 1 ) { |
i -= 2; |
done = 1; |
} |
break; |
case SDLK_RIGHT: |
if ( argv[i+1] ) { |
done = 1; |
} |
break; |
case SDLK_ESCAPE: |
case SDLK_q: |
argv[i+1] = NULL; |
/* Drop through to done */ |
case SDLK_SPACE: |
case SDLK_TAB: |
done = 1; |
break; |
default: |
break; |
} |
break; |
case SDL_QUIT: |
argv[i+1] = NULL; |
done = 1; |
break; |
default: |
break; |
} |
} else { |
SDL_Delay(3); |
} |
} |
SDL_FreeSurface(image); |
} |
/* We're done! */ |
SDL_Quit(); |
return(0); |
} |
/contrib/sdk/sources/SDL-1.2.2/SDL_image/test/test.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |