IMG.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 26 Sep 2018 15:19:34 -0400
changeset 587 32a18ca05935
parent 575 36e9e2255178
child 638 e3e9d7430674
permissions -rw-r--r--
pnm: Don't get into infinite loops on truncated files.
     1 /*
     2   SDL_image:  An example image loading library for use with SDL
     3   Copyright (C) 1997-2018 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 "SDL_image.h"
    25 
    26 #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
    27 
    28 /* Table of image detection and loading functions */
    29 static struct {
    30     const char *type;
    31     int (SDLCALL *is)(SDL_RWops *src);
    32     SDL_Surface *(SDLCALL *load)(SDL_RWops *src);
    33 } supported[] = {
    34     /* keep magicless formats first */
    35     { "TGA", NULL,      IMG_LoadTGA_RW },
    36     { "CUR", IMG_isCUR, IMG_LoadCUR_RW },
    37     { "ICO", IMG_isICO, IMG_LoadICO_RW },
    38     { "BMP", IMG_isBMP, IMG_LoadBMP_RW },
    39     { "GIF", IMG_isGIF, IMG_LoadGIF_RW },
    40     { "JPG", IMG_isJPG, IMG_LoadJPG_RW },
    41     { "LBM", IMG_isLBM, IMG_LoadLBM_RW },
    42     { "PCX", IMG_isPCX, IMG_LoadPCX_RW },
    43     { "PNG", IMG_isPNG, IMG_LoadPNG_RW },
    44     { "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
    45     { "SVG", IMG_isSVG, IMG_LoadSVG_RW },
    46     { "TIF", IMG_isTIF, IMG_LoadTIF_RW },
    47     { "XCF", IMG_isXCF, IMG_LoadXCF_RW },
    48     { "XPM", IMG_isXPM, IMG_LoadXPM_RW },
    49     { "XV",  IMG_isXV,  IMG_LoadXV_RW  },
    50     { "WEBP", IMG_isWEBP, IMG_LoadWEBP_RW },
    51 };
    52 
    53 const SDL_version *IMG_Linked_Version(void)
    54 {
    55     static SDL_version linked_version;
    56     SDL_IMAGE_VERSION(&linked_version);
    57     return(&linked_version);
    58 }
    59 
    60 extern int IMG_InitJPG(void);
    61 extern void IMG_QuitJPG(void);
    62 extern int IMG_InitPNG(void);
    63 extern void IMG_QuitPNG(void);
    64 extern int IMG_InitTIF(void);
    65 extern void IMG_QuitTIF(void);
    66 
    67 extern int IMG_InitWEBP(void);
    68 extern void IMG_QuitWEBP(void);
    69 
    70 static int initialized = 0;
    71 
    72 int IMG_Init(int flags)
    73 {
    74     int result = 0;
    75 
    76     /* Passing 0 returns the currently initialized loaders */
    77     if (!flags) {
    78         return initialized;
    79     }
    80 
    81     if (flags & IMG_INIT_JPG) {
    82         if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
    83             result |= IMG_INIT_JPG;
    84         }
    85     }
    86     if (flags & IMG_INIT_PNG) {
    87         if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {
    88             result |= IMG_INIT_PNG;
    89         }
    90     }
    91     if (flags & IMG_INIT_TIF) {
    92         if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) {
    93             result |= IMG_INIT_TIF;
    94         }
    95     }
    96     if (flags & IMG_INIT_WEBP) {
    97         if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) {
    98             result |= IMG_INIT_WEBP;
    99         }
   100     }
   101     initialized |= result;
   102 
   103     return result;
   104 }
   105 
   106 void IMG_Quit()
   107 {
   108     if (initialized & IMG_INIT_JPG) {
   109         IMG_QuitJPG();
   110     }
   111     if (initialized & IMG_INIT_PNG) {
   112         IMG_QuitPNG();
   113     }
   114     if (initialized & IMG_INIT_TIF) {
   115         IMG_QuitTIF();
   116     }
   117     if (initialized & IMG_INIT_WEBP) {
   118         IMG_QuitWEBP();
   119     }
   120     initialized = 0;
   121 }
   122 
   123 #if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
   124 /* Load an image from a file */
   125 SDL_Surface *IMG_Load(const char *file)
   126 {
   127     SDL_RWops *src = SDL_RWFromFile(file, "rb");
   128     const char *ext = SDL_strrchr(file, '.');
   129     if(ext) {
   130         ext++;
   131     }
   132     if(!src) {
   133         /* The error message has been set in SDL_RWFromFile */
   134         return NULL;
   135     }
   136     return IMG_LoadTyped_RW(src, 1, ext);
   137 }
   138 #endif
   139 
   140 /* Load an image from an SDL datasource (for compatibility) */
   141 SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc)
   142 {
   143     return IMG_LoadTyped_RW(src, freesrc, NULL);
   144 }
   145 
   146 /* Portable case-insensitive string compare function */
   147 static int IMG_string_equals(const char *str1, const char *str2)
   148 {
   149     while ( *str1 && *str2 ) {
   150         if ( SDL_toupper((unsigned char)*str1) !=
   151              SDL_toupper((unsigned char)*str2) )
   152             break;
   153         ++str1;
   154         ++str2;
   155     }
   156     return (!*str1 && !*str2);
   157 }
   158 
   159 /* Load an image from an SDL datasource, optionally specifying the type */
   160 SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, const char *type)
   161 {
   162     int i;
   163     SDL_Surface *image;
   164 
   165     /* Make sure there is something to do.. */
   166     if ( src == NULL ) {
   167         IMG_SetError("Passed a NULL data source");
   168         return(NULL);
   169     }
   170 
   171     /* See whether or not this data source can handle seeking */
   172     if ( SDL_RWseek(src, 0, RW_SEEK_CUR) < 0 ) {
   173         IMG_SetError("Can't seek in this data source");
   174         if(freesrc)
   175             SDL_RWclose(src);
   176         return(NULL);
   177     }
   178 
   179     /* Detect the type of image being loaded */
   180     image = NULL;
   181     for ( i=0; i < ARRAYSIZE(supported); ++i ) {
   182         if(supported[i].is) {
   183             if(!supported[i].is(src))
   184                 continue;
   185         } else {
   186             /* magicless format */
   187             if(!type
   188                || !IMG_string_equals(type, supported[i].type))
   189                 continue;
   190         }
   191 #ifdef DEBUG_IMGLIB
   192         fprintf(stderr, "IMGLIB: Loading image as %s\n",
   193             supported[i].type);
   194 #endif
   195         image = supported[i].load(src);
   196         if(freesrc)
   197             SDL_RWclose(src);
   198         return image;
   199     }
   200 
   201     if ( freesrc ) {
   202         SDL_RWclose(src);
   203     }
   204     IMG_SetError("Unsupported image format");
   205     return NULL;
   206 }
   207 
   208 #if SDL_VERSION_ATLEAST(2,0,0)
   209 SDL_Texture *IMG_LoadTexture(SDL_Renderer *renderer, const char *file)
   210 {
   211     SDL_Texture *texture = NULL;
   212     SDL_Surface *surface = IMG_Load(file);
   213     if (surface) {
   214         texture = SDL_CreateTextureFromSurface(renderer, surface);
   215         SDL_FreeSurface(surface);
   216     }
   217     return texture;
   218 }
   219 
   220 SDL_Texture *IMG_LoadTexture_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc)
   221 {
   222     SDL_Texture *texture = NULL;
   223     SDL_Surface *surface = IMG_Load_RW(src, freesrc);
   224     if (surface) {
   225         texture = SDL_CreateTextureFromSurface(renderer, surface);
   226         SDL_FreeSurface(surface);
   227     }
   228     return texture;
   229 }
   230 
   231 SDL_Texture *IMG_LoadTextureTyped_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc, const char *type)
   232 {
   233     SDL_Texture *texture = NULL;
   234     SDL_Surface *surface = IMG_LoadTyped_RW(src, freesrc, type);
   235     if (surface) {
   236         texture = SDL_CreateTextureFromSurface(renderer, surface);
   237         SDL_FreeSurface(surface);
   238     }
   239     return texture;
   240 }
   241 #endif /* SDL 2.0 */