#if !(defined(__APPLE__) || defined(SDL_IMAGE_USE_WIC_BACKEND)) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
#include <SDL3_image/SDL_image.h>
#ifdef LOAD_TIF
#include <tiffio.h>
#if defined(LOAD_TIF_DYNAMIC) && defined(SDL_ELF_NOTE_DLOPEN)
SDL_ELF_NOTE_DLOPEN(
"tiff",
"Support for TIFF images using libtiff",
SDL_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
LOAD_TIF_DYNAMIC
)
#endif
static struct {
int loaded;
void *handle;
TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
void (*TIFFClose)(TIFF*);
int (*TIFFGetField)(TIFF*, ttag_t, ...);
int (*TIFFReadRGBAImageOriented)(TIFF*, Uint32, Uint32, Uint32*, int, int);
TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
} lib;
#ifdef LOAD_TIF_DYNAMIC
#define FUNCTION_LOADER(FUNC, SIG) \
lib.FUNC = (SIG) SDL_LoadFunction(lib.handle, #FUNC); \
if (lib.FUNC == NULL) { SDL_UnloadObject(lib.handle); return false; }
#else
#define FUNCTION_LOADER(FUNC, SIG) \
lib.FUNC = FUNC;
#endif
static bool IMG_InitTIF(void)
{
if ( lib.loaded == 0 ) {
#ifdef LOAD_TIF_DYNAMIC
lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
if ( lib.handle == NULL ) {
return false;
}
#endif
FUNCTION_LOADER(TIFFClientOpen, TIFF * (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
FUNCTION_LOADER(TIFFClose, void (*)(TIFF*))
FUNCTION_LOADER(TIFFGetField, int (*)(TIFF*, ttag_t, ...))
FUNCTION_LOADER(TIFFReadRGBAImageOriented, int (*)(TIFF*, Uint32, Uint32, Uint32*, int, int))
FUNCTION_LOADER(TIFFSetErrorHandler, TIFFErrorHandler (*)(TIFFErrorHandler))
}
++lib.loaded;
return true;
}
#if 0#endif
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
{
return SDL_ReadIO((SDL_IOStream*)fd, buf, size);
}
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
{
return SDL_SeekIO((SDL_IOStream*)fd, offset, origin);
}
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
{
return SDL_WriteIO((SDL_IOStream*)fd, buf, size);
}
static int tiff_close(thandle_t fd)
{
return 0;
}
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
{
return (0);
}
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
{
return;
}
static toff_t tiff_size(thandle_t fd)
{
Sint64 save_pos;
toff_t size;
save_pos = SDL_TellIO((SDL_IOStream*)fd);
SDL_SeekIO((SDL_IOStream*)fd, 0, SDL_IO_SEEK_END);
size = SDL_TellIO((SDL_IOStream*)fd);
SDL_SeekIO((SDL_IOStream*)fd, save_pos, SDL_IO_SEEK_SET);
return size;
}
bool IMG_isTIF(SDL_IOStream * src)
{
Sint64 start;
bool is_TIF;
Uint8 magic[4];
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_TIF = false;
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic) ) {
if ( (magic[0] == 'I' &&
magic[1] == 'I' &&
magic[2] == 0x2a &&
magic[3] == 0x00) ||
(magic[0] == 'M' &&
magic[1] == 'M' &&
magic[2] == 0x00 &&
magic[3] == 0x2a) ) {
is_TIF = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_TIF;
}
SDL_Surface* IMG_LoadTIF_IO(SDL_IOStream * src)
{
Sint64 start;
TIFF* tiff = NULL;
SDL_Surface* surface = NULL;
Uint32 img_width, img_height;
Uint16 img_orientation = 1;
if ( !src ) {
return NULL;
}
start = SDL_TellIO(src);
if (!IMG_InitTIF()) {
return NULL;
}
tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
if(!tiff)
goto error;
lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
lib.TIFFGetField(tiff, TIFFTAG_ORIENTATION, &img_orientation);
surface = SDL_CreateSurface(img_width, img_height, SDL_PIXELFORMAT_ABGR8888);
if(!surface)
goto error;
int load_orientation;
switch (img_orientation) {
case 5:
case 6:
case 7:
case 8:
load_orientation = ORIENTATION_TOPRIGHT;
break;
default:
load_orientation = ORIENTATION_TOPLEFT;
break;
}
if(!lib.TIFFReadRGBAImageOriented(tiff, img_width, img_height, (Uint32 *)surface->pixels, load_orientation, 0)) {
goto error;
}
lib.TIFFClose(tiff);
SDL_Surface *rotated;
switch (img_orientation) {
case 5:
case 7:
rotated = SDL_RotateSurface(surface, 270.0f);
if (!rotated) {
goto error;
}
SDL_DestroySurface(surface);
surface = rotated;
break;
case 6:
case 8:
rotated = SDL_RotateSurface(surface, 90.0f);
if (!rotated) {
goto error;
}
SDL_DestroySurface(surface);
surface = rotated;
break;
default:
break;
}
return surface;
error:
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
if (surface) {
SDL_DestroySurface(surface);
}
if (tiff) {
lib.TIFFClose(tiff);
}
return NULL;
}
#else
bool IMG_isTIF(SDL_IOStream *src)
{
return false;
}
SDL_Surface *IMG_LoadTIF_IO(SDL_IOStream *src)
{
SDL_SetError("SDL_image built without TIFF support");
return NULL;
}
#endif
#endif