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