IMG.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 22 Jan 2012 21:52:00 -0500
changeset 320 aa5d55b11751
parent 280 ec4ae96c100c
child 343 5bf0f0d6a74e
permissions -rw-r--r--
Updated for SDL 2.0
     1 /*
     2   SDL_image:  An example image loading library for use with SDL
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* A simple library to load images of various formats as SDL surfaces */
    23 
    24 #include <stdio.h>
    25 #include <string.h>
    26 #include <ctype.h>
    27 
    28 #include "SDL_image.h"
    29 
    30 #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
    31 
    32 /* Table of image detection and loading functions */
    33 static struct {
    34 	char *type;
    35 	int (SDLCALL *is)(SDL_RWops *src);
    36 	SDL_Surface *(SDLCALL *load)(SDL_RWops *src);
    37 } supported[] = {
    38 	/* keep magicless formats first */
    39 	{ "TGA", NULL,      IMG_LoadTGA_RW },
    40 	{ "CUR", IMG_isCUR, IMG_LoadCUR_RW },
    41 	{ "ICO", IMG_isICO, IMG_LoadICO_RW },
    42 	{ "BMP", IMG_isBMP, IMG_LoadBMP_RW },
    43 	{ "GIF", IMG_isGIF, IMG_LoadGIF_RW },
    44 	{ "JPG", IMG_isJPG, IMG_LoadJPG_RW },
    45 	{ "LBM", IMG_isLBM, IMG_LoadLBM_RW },
    46 	{ "PCX", IMG_isPCX, IMG_LoadPCX_RW },
    47 	{ "PNG", IMG_isPNG, IMG_LoadPNG_RW },
    48 	{ "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
    49 	{ "TIF", IMG_isTIF, IMG_LoadTIF_RW },
    50 	{ "XCF", IMG_isXCF, IMG_LoadXCF_RW },
    51 	{ "XPM", IMG_isXPM, IMG_LoadXPM_RW },
    52 	{ "XV",  IMG_isXV,  IMG_LoadXV_RW  },
    53 	{ "WEBP", IMG_isWEBP, IMG_LoadWEBP_RW },
    54 };
    55 
    56 const SDL_version *IMG_Linked_Version(void)
    57 {
    58 	static SDL_version linked_version;
    59 	SDL_IMAGE_VERSION(&linked_version);
    60 	return(&linked_version);
    61 }
    62 
    63 extern int IMG_InitJPG();
    64 extern void IMG_QuitJPG();
    65 extern int IMG_InitPNG();
    66 extern void IMG_QuitPNG();
    67 extern int IMG_InitTIF();
    68 extern void IMG_QuitTIF();
    69 
    70 extern int IMG_InitWEBP();
    71 extern void IMG_QuitWEBP();
    72 
    73 static int initialized = 0;
    74 
    75 int IMG_Init(int flags)
    76 {
    77 	int result = 0;
    78 
    79 	if (flags & IMG_INIT_JPG) {
    80 		if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
    81 			result |= IMG_INIT_JPG;
    82 		}
    83 	}
    84 	if (flags & IMG_INIT_PNG) {
    85 		if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {
    86 			result |= IMG_INIT_PNG;
    87 		}
    88 	}
    89 	if (flags & IMG_INIT_TIF) {
    90 		if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) {
    91 			result |= IMG_INIT_TIF;
    92 		}
    93 	}
    94 	if (flags & IMG_INIT_WEBP) {
    95 		if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) {
    96 			result |= IMG_INIT_WEBP;
    97 		}
    98 	}
    99 	initialized |= result;
   100 
   101 	return (initialized);
   102 }
   103 
   104 void IMG_Quit()
   105 {
   106 	if (initialized & IMG_INIT_JPG) {
   107 		IMG_QuitJPG();
   108 	}
   109 	if (initialized & IMG_INIT_PNG) {
   110 		IMG_QuitPNG();
   111 	}
   112 	if (initialized & IMG_INIT_TIF) {
   113 		IMG_QuitTIF();
   114 	}
   115 	if (initialized & IMG_INIT_WEBP) {
   116 		IMG_QuitWEBP();
   117 	}
   118 	initialized = 0;
   119 }
   120 
   121 #if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
   122 /* Load an image from a file */
   123 SDL_Surface *IMG_Load(const char *file)
   124 {
   125     SDL_RWops *src = SDL_RWFromFile(file, "rb");
   126     char *ext = strrchr(file, '.');
   127     if(ext) {
   128         ext++;
   129     }
   130     if(!src) {
   131         /* The error message has been set in SDL_RWFromFile */
   132         return NULL;
   133     }
   134     return IMG_LoadTyped_RW(src, 1, ext);
   135 }
   136 #endif
   137 
   138 /* Load an image from an SDL datasource (for compatibility) */
   139 SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc)
   140 {
   141     return IMG_LoadTyped_RW(src, freesrc, NULL);
   142 }
   143 
   144 /* Portable case-insensitive string compare function */
   145 static int IMG_string_equals(const char *str1, const char *str2)
   146 {
   147 	while ( *str1 && *str2 ) {
   148 		if ( toupper((unsigned char)*str1) !=
   149 		     toupper((unsigned char)*str2) )
   150 			break;
   151 		++str1;
   152 		++str2;
   153 	}
   154 	return (!*str1 && !*str2);
   155 }
   156 
   157 /* Load an image from an SDL datasource, optionally specifying the type */
   158 SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, const char *type)
   159 {
   160 	int i;
   161 	SDL_Surface *image;
   162 
   163 	/* Make sure there is something to do.. */
   164 	if ( src == NULL ) {
   165 		IMG_SetError("Passed a NULL data source");
   166 		return(NULL);
   167 	}
   168 
   169 	/* See whether or not this data source can handle seeking */
   170 	if ( SDL_RWseek(src, 0, RW_SEEK_CUR) < 0 ) {
   171 		IMG_SetError("Can't seek in this data source");
   172 		if(freesrc)
   173 			SDL_RWclose(src);
   174 		return(NULL);
   175 	}
   176 
   177 	/* Detect the type of image being loaded */
   178 	image = NULL;
   179 	for ( i=0; i < ARRAYSIZE(supported); ++i ) {
   180 		if(supported[i].is) {
   181 			if(!supported[i].is(src))
   182 				continue;
   183 		} else {
   184 			/* magicless format */
   185 			if(!type
   186 			   || !IMG_string_equals(type, supported[i].type))
   187 				continue;
   188 		}
   189 #ifdef DEBUG_IMGLIB
   190 		fprintf(stderr, "IMGLIB: Loading image as %s\n",
   191 			supported[i].type);
   192 #endif
   193 		image = supported[i].load(src);
   194 		if(freesrc)
   195 			SDL_RWclose(src);
   196 		return image;
   197 	}
   198 
   199 	if ( freesrc ) {
   200 		SDL_RWclose(src);
   201 	}
   202 	IMG_SetError("Unsupported image format");
   203 	return NULL;
   204 }
   205 
   206 SDL_Texture *IMG_LoadTexture(SDL_Renderer *renderer, const char *file)
   207 {
   208     SDL_Texture *texture = NULL;
   209     SDL_Surface *surface = IMG_Load(file);
   210     if (surface) {
   211         texture = SDL_CreateTextureFromSurface(renderer, surface);
   212         SDL_FreeSurface(surface);
   213     }
   214     return texture;
   215 }
   216 
   217 SDL_Texture *IMG_LoadTexture_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc)
   218 {
   219     SDL_Texture *texture = NULL;
   220     SDL_Surface *surface = IMG_Load_RW(src, freesrc);
   221     if (surface) {
   222         texture = SDL_CreateTextureFromSurface(renderer, surface);
   223         SDL_FreeSurface(surface);
   224     }
   225     return texture;
   226 }
   227 
   228 SDL_Texture *IMG_LoadTextureTyped_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc, const char *type)
   229 {
   230     SDL_Texture *texture = NULL;
   231     SDL_Surface *surface = IMG_LoadTyped_RW(src, freesrc, type);
   232     if (surface) {
   233         texture = SDL_CreateTextureFromSurface(renderer, surface);
   234         SDL_FreeSurface(surface);
   235     }
   236     return texture;
   237 }
   238 
   239 /* Invert the alpha of a surface for use with OpenGL
   240    This function is a no-op and only kept for backwards compatibility.
   241  */
   242 int IMG_InvertAlpha(int on)
   243 {
   244     return 1;
   245 }