IMG_tif.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@0
     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@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@53
    20
*/
slouken@0
    21
slouken@508
    22
#if !(defined(__APPLE__) || defined(SDL_IMAGE_USE_WIC_BACKEND)) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
slouken@237
    23
slouken@0
    24
/* This is a TIFF image file loading framework */
slouken@0
    25
slouken@0
    26
#include "SDL_image.h"
slouken@0
    27
slouken@0
    28
#ifdef LOAD_TIF
slouken@0
    29
slouken@0
    30
#include <tiffio.h>
slouken@0
    31
slouken@143
    32
static struct {
slouken@368
    33
    int loaded;
slouken@368
    34
    void *handle;
slouken@368
    35
    TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
slouken@368
    36
    void (*TIFFClose)(TIFF*);
slouken@368
    37
    int (*TIFFGetField)(TIFF*, ttag_t, ...);
slouken@493
    38
    int (*TIFFReadRGBAImageOriented)(TIFF*, uint32, uint32, uint32*, int, int);
slouken@368
    39
    TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
slouken@143
    40
} lib;
slouken@143
    41
slouken@143
    42
#ifdef LOAD_TIF_DYNAMIC
slouken@537
    43
#define FUNCTION_LOADER(FUNC, SIG) \
slouken@537
    44
    lib.FUNC = (SIG) SDL_LoadFunction(lib.handle, #FUNC); \
slouken@537
    45
    if (lib.FUNC == NULL) { SDL_UnloadObject(lib.handle); return -1; }
slouken@537
    46
#else
slouken@537
    47
#define FUNCTION_LOADER(FUNC, SIG) \
slouken@537
    48
    lib.FUNC = FUNC;
slouken@537
    49
#endif
slouken@537
    50
slouken@205
    51
int IMG_InitTIF()
slouken@143
    52
{
slouken@368
    53
    if ( lib.loaded == 0 ) {
slouken@537
    54
#ifdef LOAD_TIF_DYNAMIC
slouken@368
    55
        lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
slouken@368
    56
        if ( lib.handle == NULL ) {
slouken@368
    57
            return -1;
slouken@368
    58
        }
slouken@537
    59
#endif
slouken@537
    60
        FUNCTION_LOADER(TIFFClientOpen, TIFF * (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
slouken@537
    61
        FUNCTION_LOADER(TIFFClose, void (*)(TIFF*))
slouken@537
    62
        FUNCTION_LOADER(TIFFGetField, int (*)(TIFF*, ttag_t, ...))
slouken@537
    63
        FUNCTION_LOADER(TIFFReadRGBAImageOriented, int (*)(TIFF*, uint32, uint32, uint32*, int, int))
slouken@537
    64
        FUNCTION_LOADER(TIFFSetErrorHandler, TIFFErrorHandler (*)(TIFFErrorHandler))
slouken@368
    65
    }
slouken@368
    66
    ++lib.loaded;
slouken@143
    67
slouken@368
    68
    return 0;
slouken@143
    69
}
slouken@205
    70
void IMG_QuitTIF()
slouken@143
    71
{
slouken@368
    72
    if ( lib.loaded == 0 ) {
slouken@368
    73
        return;
slouken@368
    74
    }
slouken@368
    75
    if ( lib.loaded == 1 ) {
slouken@537
    76
#ifdef LOAD_TIF_DYNAMIC
slouken@368
    77
        SDL_UnloadObject(lib.handle);
slouken@537
    78
#endif
slouken@368
    79
    }
slouken@368
    80
    --lib.loaded;
slouken@143
    81
}
slouken@143
    82
slouken@0
    83
/*
slouken@0
    84
 * These are the thunking routine to use the SDL_RWops* routines from
slouken@0
    85
 * libtiff's internals.
slouken@0
    86
*/
slouken@0
    87
slouken@0
    88
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
    89
{
slouken@537
    90
    return (tsize_t)SDL_RWread((SDL_RWops*)fd, buf, 1, size);
slouken@0
    91
}
slouken@0
    92
slouken@0
    93
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
slouken@0
    94
{
slouken@368
    95
    return SDL_RWseek((SDL_RWops*)fd, offset, origin);
slouken@0
    96
}
slouken@0
    97
slouken@0
    98
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
slouken@0
    99
{
slouken@537
   100
    return (tsize_t)SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
slouken@0
   101
}
slouken@0
   102
slouken@0
   103
static int tiff_close(thandle_t fd)
slouken@0
   104
{
slouken@368
   105
    /*
slouken@368
   106
     * We don't want libtiff closing our SDL_RWops*, but if it's not given
slouken@0
   107
         * a routine to try, and if the image isn't a TIFF, it'll segfault.
slouken@368
   108
     */
slouken@368
   109
    return 0;
slouken@0
   110
}
slouken@0
   111
slouken@167
   112
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
slouken@167
   113
{
slouken@368
   114
    return (0);
slouken@167
   115
}
slouken@167
   116
slouken@167
   117
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
slouken@167
   118
{
slouken@368
   119
    return;
slouken@167
   120
}
slouken@167
   121
slouken@0
   122
static toff_t tiff_size(thandle_t fd)
slouken@0
   123
{
slouken@368
   124
    Sint64 save_pos;
slouken@368
   125
    toff_t size;
slouken@0
   126
slouken@368
   127
    save_pos = SDL_RWtell((SDL_RWops*)fd);
slouken@368
   128
    SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
aschiffler@343
   129
    size = SDL_RWtell((SDL_RWops*)fd);
slouken@368
   130
    SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
slouken@368
   131
    return size;
slouken@0
   132
}
slouken@0
   133
slouken@0
   134
int IMG_isTIF(SDL_RWops* src)
slouken@0
   135
{
slouken@368
   136
    Sint64 start;
slouken@368
   137
    int is_TIF;
slouken@368
   138
    Uint8 magic[4];
slouken@0
   139
slouken@368
   140
    if ( !src )
slouken@368
   141
        return 0;
slouken@368
   142
    start = SDL_RWtell(src);
slouken@368
   143
    is_TIF = 0;
slouken@368
   144
    if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
slouken@368
   145
        if ( (magic[0] == 'I' &&
slouken@167
   146
                      magic[1] == 'I' &&
slouken@368
   147
              magic[2] == 0x2a &&
slouken@167
   148
                      magic[3] == 0x00) ||
slouken@368
   149
             (magic[0] == 'M' &&
slouken@167
   150
                      magic[1] == 'M' &&
slouken@368
   151
              magic[2] == 0x00 &&
slouken@167
   152
                      magic[3] == 0x2a) ) {
slouken@368
   153
            is_TIF = 1;
slouken@368
   154
        }
slouken@368
   155
    }
slouken@368
   156
    SDL_RWseek(src, start, RW_SEEK_SET);
slouken@368
   157
    return(is_TIF);
slouken@0
   158
}
slouken@0
   159
slouken@0
   160
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
slouken@0
   161
{
slouken@368
   162
    Sint64 start;
slouken@492
   163
    TIFF* tiff = NULL;
slouken@368
   164
    SDL_Surface* surface = NULL;
slouken@368
   165
    Uint32 img_width, img_height;
slouken@368
   166
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@0
   167
slouken@368
   168
    if ( !src ) {
slouken@368
   169
        /* The error message has been set in SDL_RWFromFile */
slouken@368
   170
        return NULL;
slouken@368
   171
    }
slouken@368
   172
    start = SDL_RWtell(src);
slouken@0
   173
slouken@490
   174
    if ( (IMG_Init(IMG_INIT_TIF) & IMG_INIT_TIF) == 0 ) {
slouken@368
   175
        return NULL;
slouken@368
   176
    }
slouken@143
   177
slouken@368
   178
    /* turn off memory mapped access with the m flag */
slouken@368
   179
    tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
slouken@368
   180
        tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
slouken@368
   181
    if(!tiff)
slouken@368
   182
        goto error;
slouken@0
   183
slouken@368
   184
    /* Retrieve the dimensions of the image from the TIFF tags */
slouken@368
   185
    lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
slouken@368
   186
    lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
slouken@0
   187
slouken@368
   188
    Rmask = 0x000000FF;
slouken@368
   189
    Gmask = 0x0000FF00;
slouken@368
   190
    Bmask = 0x00FF0000;
slouken@368
   191
    Amask = 0xFF000000;
slouken@368
   192
    surface = SDL_CreateRGBSurface(SDL_SWSURFACE, img_width, img_height, 32,
slouken@368
   193
        Rmask, Gmask, Bmask, Amask);
slouken@368
   194
    if(!surface)
slouken@368
   195
        goto error;
slouken@0
   196
slouken@493
   197
    if(!lib.TIFFReadRGBAImageOriented(tiff, img_width, img_height, (uint32 *)surface->pixels, ORIENTATION_TOPLEFT, 0))
slouken@368
   198
        goto error;
slouken@368
   199
slouken@368
   200
    lib.TIFFClose(tiff);
slouken@368
   201
slouken@368
   202
    return surface;
slouken@118
   203
slouken@118
   204
error:
slouken@368
   205
    SDL_RWseek(src, start, RW_SEEK_SET);
slouken@492
   206
    if (surface) {
slouken@368
   207
        SDL_FreeSurface(surface);
slouken@368
   208
    }
slouken@492
   209
    if (tiff) {
slouken@492
   210
        lib.TIFFClose(tiff);
slouken@492
   211
    }
slouken@368
   212
    return NULL;
slouken@0
   213
}
slouken@0
   214
slouken@0
   215
#else
slouken@0
   216
slouken@205
   217
int IMG_InitTIF()
slouken@205
   218
{
slouken@368
   219
    IMG_SetError("TIFF images are not supported");
slouken@368
   220
    return(-1);
slouken@205
   221
}
slouken@205
   222
slouken@205
   223
void IMG_QuitTIF()
slouken@205
   224
{
slouken@205
   225
}
slouken@205
   226
slouken@0
   227
/* See if an image is contained in a data source */
slouken@0
   228
int IMG_isTIF(SDL_RWops *src)
slouken@0
   229
{
slouken@368
   230
    return(0);
slouken@0
   231
}
slouken@0
   232
slouken@0
   233
/* Load a TIFF type image from an SDL datasource */
slouken@0
   234
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
slouken@0
   235
{
slouken@368
   236
    return(NULL);
slouken@0
   237
}
slouken@0
   238
slouken@0
   239
#endif /* LOAD_TIF */
slouken@237
   240
slouken@237
   241
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */