IMG_xv.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.
slouken@119
     1
/*
slouken@280
     2
  SDL_image:  An example image loading library for use with SDL
slouken@575
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
slouken@119
     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@119
     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@119
    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@119
    20
*/
slouken@119
    21
slouken@121
    22
/* This is a XV thumbnail image file loading framework */
slouken@119
    23
slouken@119
    24
#include "SDL_image.h"
slouken@119
    25
slouken@119
    26
#ifdef LOAD_XV
slouken@119
    27
slouken@119
    28
static int get_line(SDL_RWops *src, char *line, int size)
slouken@119
    29
{
slouken@368
    30
    while ( size > 0 ) {
slouken@368
    31
        if ( SDL_RWread(src, line, 1, 1) <= 0 ) {
slouken@368
    32
            return -1;
slouken@368
    33
        }
slouken@368
    34
        if ( *line == '\r' ) {
slouken@368
    35
            continue;
slouken@368
    36
        }
slouken@368
    37
        if ( *line == '\n' ) {
slouken@368
    38
            *line = '\0';
slouken@368
    39
            return 0;
slouken@368
    40
        }
slouken@368
    41
        ++line;
slouken@368
    42
        --size;
slouken@368
    43
    }
slouken@368
    44
    /* Out of space for the line */
slouken@368
    45
    return -1;
slouken@119
    46
}
slouken@119
    47
slouken@119
    48
static int get_header(SDL_RWops *src, int *w, int *h)
slouken@119
    49
{
slouken@368
    50
    char line[1024];
slouken@119
    51
slouken@368
    52
    *w = 0;
slouken@368
    53
    *h = 0;
slouken@119
    54
slouken@368
    55
    /* Check the header magic */
slouken@368
    56
    if ( (get_line(src, line, sizeof(line)) < 0) ||
slouken@368
    57
         (SDL_memcmp(line, "P7 332", 6) != 0) ) {
slouken@368
    58
        return -1;
slouken@368
    59
    }
slouken@119
    60
slouken@368
    61
    /* Read the header */
slouken@368
    62
    while ( get_line(src, line, sizeof(line)) == 0 ) {
slouken@368
    63
        if ( SDL_memcmp(line, "#BUILTIN:", 9) == 0 ) {
slouken@368
    64
            /* Builtin image, no data */
slouken@368
    65
            break;
slouken@368
    66
        }
slouken@368
    67
        if ( SDL_memcmp(line, "#END_OF_COMMENTS", 16) == 0 ) {
slouken@368
    68
            if ( get_line(src, line, sizeof(line)) == 0 ) {
slouken@368
    69
                SDL_sscanf(line, "%d %d", w, h);
slouken@368
    70
                if ( *w >= 0 && *h >= 0 ) {
slouken@368
    71
                    return 0;
slouken@368
    72
                }
slouken@368
    73
            }
slouken@368
    74
            break;
slouken@368
    75
        }
slouken@368
    76
    }
slouken@368
    77
    /* No image data */
slouken@368
    78
    return -1;
slouken@119
    79
}
slouken@119
    80
slouken@119
    81
/* See if an image is contained in a data source */
slouken@119
    82
int IMG_isXV(SDL_RWops *src)
slouken@119
    83
{
slouken@368
    84
    Sint64 start;
slouken@368
    85
    int is_XV;
slouken@368
    86
    int w, h;
slouken@119
    87
slouken@368
    88
    if ( !src )
slouken@368
    89
        return 0;
slouken@368
    90
    start = SDL_RWtell(src);
slouken@368
    91
    is_XV = 0;
slouken@368
    92
    if ( get_header(src, &w, &h) == 0 ) {
slouken@368
    93
        is_XV = 1;
slouken@368
    94
    }
slouken@368
    95
    SDL_RWseek(src, start, RW_SEEK_SET);
slouken@368
    96
    return(is_XV);
slouken@119
    97
}
slouken@119
    98
slouken@119
    99
/* Load a XV thumbnail image from an SDL datasource */
slouken@119
   100
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
slouken@119
   101
{
slouken@368
   102
    Sint64 start;
slouken@368
   103
    const char *error = NULL;
slouken@368
   104
    SDL_Surface *surface = NULL;
slouken@368
   105
    int w, h;
slouken@368
   106
    Uint8 *pixels;
slouken@119
   107
slouken@368
   108
    if ( !src ) {
slouken@368
   109
        /* The error message has been set in SDL_RWFromFile */
slouken@368
   110
        return NULL;
slouken@368
   111
    }
slouken@368
   112
    start = SDL_RWtell(src);
slouken@119
   113
slouken@368
   114
    /* Read the header */
slouken@368
   115
    if ( get_header(src, &w, &h) < 0 ) {
slouken@368
   116
        error = "Unsupported image format";
slouken@368
   117
        goto done;
slouken@368
   118
    }
slouken@119
   119
slouken@368
   120
    /* Create the 3-3-2 indexed palette surface */
slouken@368
   121
    surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0xe0, 0x1c, 0x03, 0);
slouken@368
   122
    if ( surface == NULL ) {
slouken@368
   123
        error = "Out of memory";
slouken@368
   124
        goto done;
slouken@368
   125
    }
slouken@119
   126
slouken@368
   127
    /* Load the image data */
slouken@368
   128
    for ( pixels = (Uint8 *)surface->pixels; h > 0; --h ) {
slouken@368
   129
        if ( SDL_RWread(src, pixels, w, 1) <= 0 ) {
slouken@368
   130
            error = "Couldn't read image data";
slouken@368
   131
            goto done;
slouken@368
   132
        }
slouken@368
   133
        pixels += surface->pitch;
slouken@368
   134
    }
slouken@119
   135
slouken@119
   136
done:
slouken@368
   137
    if ( error ) {
slouken@368
   138
        SDL_RWseek(src, start, RW_SEEK_SET);
slouken@368
   139
        if ( surface ) {
slouken@368
   140
            SDL_FreeSurface(surface);
slouken@368
   141
            surface = NULL;
slouken@368
   142
        }
slouken@451
   143
        IMG_SetError("%s", error);
slouken@368
   144
    }
slouken@368
   145
    return surface;
slouken@119
   146
}
slouken@119
   147
slouken@119
   148
#else
slouken@119
   149
slouken@119
   150
/* See if an image is contained in a data source */
slouken@119
   151
int IMG_isXV(SDL_RWops *src)
slouken@119
   152
{
slouken@368
   153
    return(0);
slouken@119
   154
}
slouken@119
   155
slouken@119
   156
/* Load a XXX type image from an SDL datasource */
slouken@119
   157
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
slouken@119
   158
{
slouken@368
   159
    return(NULL);
slouken@119
   160
}
slouken@119
   161
slouken@119
   162
#endif /* LOAD_XV */