Use filename extensions for determining image format rather than magic

This commit is contained in:
ROllerozxa 2026-06-19 00:13:04 +02:00
commit d623a95857
8 changed files with 37 additions and 184 deletions

View file

@ -19,34 +19,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
/* A simple library to load images of various formats as SDL surfaces */
#include <SDL_image.h>
SDL_Surface *IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type);
/* Load an image from a file */
SDL_Surface *IMG_Load(const char *file)
{
SDL_IOStream *src = SDL_IOFromFile(file, "rb");
if (!src) {
/* The error message has been set in SDL_IOFromFile */
return NULL;
}
const char *ext = SDL_strrchr(file, '.');
if (ext) {
ext++;
}
return IMG_LoadTyped_IO(src, true, ext);
}
/* Load an image from an SDL datasource (for compatibility) */
SDL_Surface *IMG_Load_IO(SDL_IOStream *src, bool closeio)
{
return IMG_LoadTyped_IO(src, closeio, NULL);
}
/* Load an image from an SDL datasource, optionally specifying the type */
SDL_Surface *IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type)
{
@ -67,21 +41,21 @@ SDL_Surface *IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type)
return NULL;
}
/* Detect the type of image being loaded */
if (IMG_isJPG(src)) {
image = IMG_LoadJPG_IO(src);
if (closeio) {
SDL_CloseIO(src);
if (type) {
if (SDL_strcasecmp(type, "JPEG") == 0 || SDL_strcasecmp(type, "JPG") == 0) {
image = IMG_LoadJPG_IO(src);
if (closeio) {
SDL_CloseIO(src);
}
return image;
}
return image;
}
if (IMG_isPNG(src)) {
image = IMG_LoadPNG_IO(src);
if (closeio) {
SDL_CloseIO(src);
if (SDL_strcasecmp(type, "PNG") == 0) {
image = IMG_LoadPNG_IO(src);
if (closeio) {
SDL_CloseIO(src);
}
return image;
}
return image;
}
if (closeio) {
@ -90,3 +64,19 @@ SDL_Surface *IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type)
SDL_SetError("Unsupported image format");
return NULL;
}
/* Load an image from a file */
SDL_Surface *IMG_Load(const char *file)
{
SDL_IOStream *src = SDL_IOFromFile(file, "rb");
if (!src) {
/* The error message has been set in SDL_IOFromFile */
return NULL;
}
const char *ext = SDL_strrchr(file, '.');
if (ext) {
ext++;
}
return IMG_LoadTyped_IO(src, true, ext);
}

View file

@ -28,73 +28,6 @@
#include <jpeglib.h>
/* Define this for fast loading and not as good image quality */
/*#define FAST_JPEG*/
/* See if an image is contained in a data source */
bool IMG_isJPG(SDL_IOStream *src)
{
Sint64 start;
bool is_JPG;
bool in_scan;
Uint8 magic[4];
/* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
/* Blame me, not Sam, if this doesn't work right. */
/* And don't forget to report the problem to the the sdl list too! */
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_JPG = false;
in_scan = false;
if (SDL_ReadIO(src, magic, 2) == 2) {
if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
is_JPG = true;
while (is_JPG) {
if (SDL_ReadIO(src, magic, 2) != 2) {
is_JPG = false;
} else if ( (magic[0] != 0xFF) && !in_scan ) {
is_JPG = false;
} else if ( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
/* Extra padding in JPEG (legal) */
/* or this is data and we are scanning */
SDL_SeekIO(src, -1, SDL_IO_SEEK_CUR);
} else if (magic[1] == 0xD9) {
/* Got to end of good JPEG */
break;
} else if ( in_scan && (magic[1] == 0x00) ) {
/* This is an encoded 0xFF within the data */
} else if ( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
/* These have nothing else */
} else if (SDL_ReadIO(src, magic+2, 2) != 2) {
is_JPG = false;
} else {
/* Yes, it's big-endian */
Sint64 innerStart;
Uint32 size;
Sint64 end;
innerStart = SDL_TellIO(src);
size = (magic[2] << 8) + magic[3];
end = SDL_SeekIO(src, size-2, SDL_IO_SEEK_CUR);
if ( end != innerStart + size - 2 ) {
is_JPG = false;
}
if ( magic[1] == 0xDA ) {
/* Now comes the actual JPEG meat */
/* Ok, I'm convinced. It is a JPEG. */
break;
}
}
}
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_JPG;
}
#define INPUT_BUFFER_SIZE 4096
typedef struct {
struct jpeg_source_mgr pub;
@ -266,12 +199,6 @@ static bool LIBJPEG_LoadJPG_IO(SDL_IOStream *src, struct loadjpeg_vars *vars)
/* Set 24-bit RGB output */
vars->cinfo.out_color_space = JCS_RGB;
vars->cinfo.quantize_colors = FALSE;
#ifdef FAST_JPEG
vars->cinfo.scale_num = 1;
vars->cinfo.scale_denom = 1;
vars->cinfo.dct_method = JDCT_FASTEST;
vars->cinfo.do_fancy_upsampling = FALSE;
#endif
jpeg_calc_output_dimensions(&vars->cinfo);
/* Allocate an output surface to hold the image */

View file

@ -24,46 +24,6 @@
#include <SDL_image.h>
#include <png.h>
extern bool IMG_InitPNG(void);
extern SDL_Surface *IMG_LoadPNG_LIBPNG(SDL_IOStream *src);
extern bool IMG_SavePNG_LIBPNG(SDL_Surface *surface, SDL_IOStream *dst, bool closeio);
/* See if an image is contained in a data source */
bool IMG_isPNG(SDL_IOStream *src)
{
Sint64 start;
bool is_PNG;
Uint8 magic[4];
if (!src) {
return false;
}
start = SDL_TellIO(src);
is_PNG = false;
if (SDL_ReadIO(src, magic, sizeof(magic)) == sizeof(magic)) {
if (magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G') {
is_PNG = true;
}
}
SDL_SeekIO(src, start, SDL_IO_SEEK_SET);
return is_PNG;
}
typedef png_const_structrp png_noconst15_structrp;
typedef png_const_inforp png_noconst15_inforp;
typedef png_inforp png_noconst16_inforp;
#define libpng_get_uint_32(buf) \
(((png_uint_32)( *(buf) ) << 24) + \
((png_uint_32)(*((buf) + 1)) << 16) + \
((png_uint_32)(*((buf) + 2)) << 8) + \
((png_uint_32)(*((buf) + 3))))
static void png_read_data(png_structp png_ptr, png_bytep area, png_size_t size)
{
SDL_IOStream *src = (SDL_IOStream *)png_get_io_ptr(png_ptr);

View file

@ -38,17 +38,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file);
/**
* Load an image from an SDL data source into a software surface.
*/
extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_Load_IO(SDL_IOStream *src, bool closeio);
/**
* Detect JPG image data on a readable/seekable SDL_IOStream.
*/
extern SDL_DECLSPEC bool SDLCALL IMG_isJPG(SDL_IOStream *src);
/**
* Detect PNG image data on a readable/seekable SDL_IOStream.
*/
extern SDL_DECLSPEC bool SDLCALL IMG_isPNG(SDL_IOStream *src);
extern SDL_DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_IO(SDL_IOStream *src, bool closeio, const char *type);
/**
* Load a JPG image directly.

View file

@ -483,7 +483,7 @@ _get_featured_levels(void *_num)
lb.r_buf(thumb, thumb_len);
tms::texture *tex = new tms::texture();
tex->load_mem2(thumb, thumb_len, 0);
tex->load_mem2(thumb, thumb_len, 0, "jpg");
tex->flip_y();
tex->add_alpha(1.f);

View file

@ -145,13 +145,8 @@ tms_texture_load(struct tms_texture *tex, const char *filename)
tex->gamma_corrected = 0;
tex->width = s->w;
tex->height = s->h;
//tex->num_channels = 3 + s->format->Amask?1:0;
tex->num_channels = SDL_GetPixelFormatDetails(s->format)->bytes_per_pixel;
//tms_infof("bpp %d", s->format->BytesPerPixel);
//tms_assertf(tex->num_channels == s->format->BytesPerPixel, "unsupported texture type BLAH");
tex->data = malloc(tex->width*tex->height*tex->num_channels);
for (int y=0; y<s->h; y++) {
@ -163,7 +158,6 @@ tms_texture_load(struct tms_texture *tex, const char *filename)
}
SDL_DestroySurface(s);
//SDL_RWclose(rw);
return T_OK;
}
@ -207,7 +201,7 @@ tms_texture_load_mem(struct tms_texture *tex, const char *buf,
* @relates tms_texture
**/
int
tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int freesrc)
tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int freesrc, const char *type)
{
int status;
@ -218,10 +212,10 @@ tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int
return T_COULD_NOT_OPEN;
}
SDL_Surface *s = IMG_Load_IO(rw, freesrc);
SDL_Surface *s = IMG_LoadTyped_IO(rw, freesrc, type);
if (!s) {
tms_errorf("Error calling IMG_Load_IO: %s", SDL_GetError());
tms_errorf("Error loading image: %s", SDL_GetError());
return T_COULD_NOT_OPEN;
}
@ -230,15 +224,8 @@ tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int
tex->gamma_corrected = 0;
tex->width = s->w;
tex->height = s->h;
//tex->num_channels = 3 + s->format->Amask?1:0;
// fix this for SDL3
//tex->num_channels = s->format->BytesPerPixel;
tex->num_channels = SDL_GetPixelFormatDetails(s->format)->bytes_per_pixel;
//tms_infof("bpp %d", s->format->BytesPerPixel);
//tms_assertf(tex->num_channels == s->format->BytesPerPixel, "unsupported texture type BLAH");
tex->data = malloc(tex->width*tex->height*tex->num_channels);
for (int y=0; y<s->h; y++) {
@ -250,7 +237,6 @@ tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int
}
SDL_DestroySurface(s);
//SDL_RWclose(rw);
return T_OK;
}

View file

@ -44,7 +44,7 @@ int tms_texture_clear_buffer(struct tms_texture *tex, unsigned char clear_value)
int tms_texture_free_buffer(struct tms_texture *tex);
int tms_texture_load(struct tms_texture *tex, const char *filename);
int tms_texture_load_mem(struct tms_texture *tex, const char *buf, int width, int height, int num_channels);
int tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int freesrc);
int tms_texture_load_mem2(struct tms_texture *tex, const char *buf, size_t size, int freesrc, const char *type);
int tms_texture_upload(struct tms_texture *tex);
int tms_texture_bind(struct tms_texture *tex);
int tms_texture_flip_y(struct tms_texture *tex);

View file

@ -91,8 +91,8 @@ namespace tms {
return tms_texture_load(this, filename);
}
inline int load_mem2(const char *buf, size_t size, int freesrc) {
return tms_texture_load_mem2(this, buf, size, freesrc);
inline int load_mem2(const char *buf, size_t size, int freesrc, const char *type) {
return tms_texture_load_mem2(this, buf, size, freesrc, type);
}
inline int upload() {