From 00b71a12a5b0ea376a890fbcdd22475ae9694a39 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 9 May 2022 12:44:16 -0700
Subject: [PATCH] Added support for AVIF images
(https://github.com/AOMediaCodec/libavif)
Fixes https://github.com/libsdl-org/SDL_image/issues/188
---
.gitmodules | 8 ++
CHANGES.txt | 2 +
IMG.c | 11 ++
IMG_avif.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++
Makefile.am | 1 +
Makefile.in | 45 ++++---
SDL_image.h | 13 +-
configure | 278 +++++++++++++++++++++++++++++++++++++--
configure.ac | 58 +++++++++
external/dav1d | 1 +
external/libavif | 1 +
11 files changed, 712 insertions(+), 38 deletions(-)
create mode 100644 IMG_avif.c
create mode 160000 external/dav1d
create mode 160000 external/libavif
diff --git a/.gitmodules b/.gitmodules
index 88ed07b..5b93a7f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -22,3 +22,11 @@
path = external/libjxl
url = https://github.com/libsdl-org/libjxl.git
branch = v0.6.1-SDL
+[submodule "external/libavif"]
+ path = external/libavif
+ url = https://github.com/libsdl-org/libavif.git
+ branch = v0.10.1-SDL
+[submodule "external/dav1d"]
+ path = external/dav1d
+ url = https://github.com/libsdl-org/dav1d.git
+ branch = 1.0.0-SDL
diff --git a/CHANGES.txt b/CHANGES.txt
index 7b1a1c4..70c3a90 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,6 @@
2.0.6:
+Sam Lantinga - Mon May 9 12:42:05 PDT 2022
+ * Added support for AVIF images (https://github.com/AOMediaCodec/libavif)
Sylvain Becker - Sun May 8 21:59:27 PDT 2022
* Added IMG_ReadXPMFromArrayToRGB888()
Sam Lantinga - Sun May 8 14:31:27 PDT 2022
diff --git a/IMG.c b/IMG.c
index 68b7992..e48ed24 100644
--- a/IMG.c
+++ b/IMG.c
@@ -58,6 +58,7 @@ static struct {
} supported[] = {
/* keep magicless formats first */
{ "TGA", NULL, IMG_LoadTGA_RW },
+ { "AVIF",IMG_isAVIF,IMG_LoadAVIF_RW },
{ "CUR", IMG_isCUR, IMG_LoadCUR_RW },
{ "ICO", IMG_isICO, IMG_LoadICO_RW },
{ "BMP", IMG_isBMP, IMG_LoadBMP_RW },
@@ -94,6 +95,8 @@ const SDL_version *IMG_Linked_Version(void)
return(&linked_version);
}
+extern int IMG_InitAVIF(void);
+extern void IMG_QuitAVIF(void);
extern int IMG_InitJPG(void);
extern void IMG_QuitJPG(void);
extern int IMG_InitJXL(void);
@@ -112,6 +115,11 @@ int IMG_Init(int flags)
{
int result = 0;
+ if (flags & IMG_INIT_AVIF) {
+ if ((initialized & IMG_INIT_AVIF) || IMG_InitAVIF() == 0) {
+ result |= IMG_INIT_AVIF;
+ }
+ }
if (flags & IMG_INIT_JPG) {
if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
result |= IMG_INIT_JPG;
@@ -144,6 +152,9 @@ int IMG_Init(int flags)
void IMG_Quit()
{
+ if (initialized & IMG_INIT_AVIF) {
+ IMG_QuitAVIF();
+ }
if (initialized & IMG_INIT_JPG) {
IMG_QuitJPG();
}
diff --git a/IMG_avif.c b/IMG_avif.c
new file mode 100644
index 0000000..940850b
--- /dev/null
+++ b/IMG_avif.c
@@ -0,0 +1,332 @@
+/*
+ SDL_image: An example image loading library for use with SDL
+ Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* This is a AVIF image file loading framework */
+
+#include "SDL_image.h"
+
+#ifdef LOAD_AVIF
+
+#include <avif/avif.h>
+
+
+static struct {
+ int loaded;
+ void *handle;
+ avifBool (*avifPeekCompatibleFileType)(const avifROData * input);
+ avifDecoder * (*avifDecoderCreate)(void);
+ void (*avifDecoderDestroy)(avifDecoder * decoder);
+ void (*avifDecoderSetIO)(avifDecoder * decoder, avifIO * io);
+ avifResult (*avifDecoderParse)(avifDecoder * decoder);
+ avifResult (*avifDecoderNextImage)(avifDecoder * decoder);
+ avifResult (*avifImageYUVToRGB)(const avifImage * image, avifRGBImage * rgb);
+} lib;
+
+#ifdef LOAD_AVIF_DYNAMIC
+#define FUNCTION_LOADER(FUNC, SIG) \
+ lib.FUNC = (SIG) SDL_LoadFunction(lib.handle, #FUNC); \
+ if (lib.FUNC == NULL) { SDL_UnloadObject(lib.handle); return -1; }
+#else
+#define FUNCTION_LOADER(FUNC, SIG) \
+ lib.FUNC = FUNC; \
+ if (lib.FUNC == NULL) { IMG_SetError("Missing avif.framework"); return -1; }
+#endif
+
+int IMG_InitAVIF()
+{
+ if ( lib.loaded == 0 ) {
+#ifdef LOAD_AVIF_DYNAMIC
+ lib.handle = SDL_LoadObject(LOAD_AVIF_DYNAMIC);
+ if ( lib.handle == NULL ) {
+ return -1;
+ }
+#endif
+ FUNCTION_LOADER(avifPeekCompatibleFileType, avifBool (*)(const avifROData * input))
+ FUNCTION_LOADER(avifDecoderCreate, avifDecoder *(*)(void))
+ FUNCTION_LOADER(avifDecoderDestroy, void (*)(avifDecoder * decoder))
+ FUNCTION_LOADER(avifDecoderSetIO, void (*)(avifDecoder * decoder, avifIO * io))
+ FUNCTION_LOADER(avifDecoderParse, avifResult (*)(avifDecoder * decoder))
+ FUNCTION_LOADER(avifDecoderNextImage, avifResult (*)(avifDecoder * decoder))
+ FUNCTION_LOADER(avifImageYUVToRGB, avifResult (*)(const avifImage * image, avifRGBImage * rgb))
+ }
+ ++lib.loaded;
+
+ return 0;
+}
+void IMG_QuitAVIF()
+{
+ if ( lib.loaded == 0 ) {
+ return;
+ }
+ if ( lib.loaded == 1 ) {
+#ifdef LOAD_AVIF_DYNAMIC
+ SDL_UnloadObject(lib.handle);
+#endif
+ }
+ --lib.loaded;
+}
+
+static SDL_bool ReadAVIFHeader(SDL_RWops *src, Uint8 **header_data, size_t *header_size)
+{
+ Uint8 magic[16];
+ size_t size;
+ size_t read = 0;
+ Uint8 *data;
+
+ *header_data = NULL;
+ *header_size = 0;
+
+ if (!SDL_RWread(src, magic, 8, 1)) {
+ return SDL_FALSE;
+ }
+ read += 8;
+
+ if (SDL_memcmp(&magic[4], "ftyp", 4) != 0) {
+ return SDL_FALSE;
+ }
+
+ size = (((size_t)magic[0] << 24) |
+ ((size_t)magic[1] << 16) |
+ ((size_t)magic[2] << 8) |
+ ((size_t)magic[3] << 0));
+ if (size == 1) {
+ /* 64-bit header size */
+ if (!SDL_RWread(src, &magic[8], 8, 1)) {
+ return SDL_FALSE;
+ }
+ read += 8;
+
+ size = (((size_t)magic[8] << 56) |
+ ((size_t)magic[9] << 48) |
+ ((size_t)magic[10] << 40) |
+ ((size_t)magic[11] << 32) |
+ ((size_t)magic[12] << 24) |
+ ((size_t)magic[13] << 16) |
+ ((size_t)magic[14] << 8) |
+ ((size_t)magic[15] << 0));
+ }
+
+ if (size <= read) {
+ return SDL_FALSE;
+ }
+
+ /* Read in the header */
+ data = (Uint8 *)SDL_malloc(size);
+ if (!data) {
+ return SDL_FALSE;
+ }
+ SDL_memcpy(data, magic, read);
+
+ if (!SDL_RWread(src, &data[read], (size - read), 1)) {
+ SDL_free(data);
+ return SDL_FALSE;
+ }
+ *header_data = data;
+ *header_size = size;
+ return SDL_TRUE;
+}
+
+/* See if an image is contained in a data source */
+int IMG_isAVIF(SDL_RWops *src)
+{
+ Sint64 start;
+ int is_AVIF;
+ Uint8 *data;
+ size_t size;
+
+ if ( !src )
+ return 0;
+
+ start = SDL_RWtell(src);
+ is_AVIF = 0;
+ if (ReadAVIFHeader(src, &data, &size)) {
+ /* This might be AVIF, do more thorough checks */
+ if ((IMG_Init(IMG_INIT_AVIF) & IMG_INIT_AVIF) != 0) {
+ avifROData header;
+
+ header.data = data;
+ header.size = size;
+ is_AVIF = lib.avifPeekCompatibleFileType(&header);
+ }
+ SDL_free(data);
+ }
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ return(is_AVIF);
+}
+
+/* Context for AFIF I/O operations */
+typedef struct
+{
+ SDL_RWops *src;
+ Uint64 start;
+ uint8_t *data;
+ size_t size;
+} avifIOContext;
+
+static avifResult ReadAVIFIO(struct avifIO * io, uint32_t readFlags, uint64_t offset, size_t size, avifROData * out)
+{
+ avifIOContext *context = (avifIOContext *)io->data;
+
+ /* The AVIF reader bounces all over, so always seek to the correct offset */
+ if (SDL_RWseek(context->src, context->start + offset, RW_SEEK_SET) < 0) {
+ return AVIF_RESULT_IO_ERROR;
+ }
+
+ if (size > context->size) {
+ uint8_t *data = (uint8_t *)SDL_realloc(context->data, size);
+ if (!data) {
+ return AVIF_RESULT_IO_ERROR;
+ }
+ context->data = data;
+ context->size = size;
+ }
+
+ out->data = context->data;
+ out->size = SDL_RWread(context->src, context->data, 1, size);
+ if (out->size == 0) {
+ return AVIF_RESULT_IO_ERROR;
+ }
+
+ return AVIF_RESULT_OK;
+}
+
+static void DestroyAVIFIO(struct avifIO * io)
+{
+ avifIOContext *context = (avifIOContext *)io->data;
+
+ if (context->data) {
+ SDL_free(context->data);
+ context->data = NULL;
+ }
+}
+
+/* Load a AVIF type image from an SDL datasource */
+SDL_Surface *IMG_LoadAVIF_RW(SDL_RWops *src)
+{
+ Sint64 start;
+ avifDecoder *decoder = NULL;
+ avifIO io;
+ avifIOContext context;
+ avifRGBImage rgb;
+ avifResult result;
+ SDL_Surface *surface = NULL;
+
+ if (!src) {
+ /* The error message has been set in SDL_RWFromFile */
+ return NULL;
+ }
+ start = SDL_RWtell(src);
+
+ if ((IMG_Init(IMG_INIT_AVIF) & IMG_INIT_AVIF) == 0) {
+ return NULL;
+ }
+
+ SDL_zero(context);
+ SDL_zero(io);
+ SDL_zero(rgb);
+
+ decoder = lib.avifDecoderCreate();
+ if (!decoder) {
+ IMG_SetError("Couldn't create AVIF decoder");
+ goto done;
+ }
+
+ context.src = src;
+ context.start = start;
+ io.destroy = DestroyAVIFIO;
+ io.read = ReadAVIFIO;
+ io.data = &context;
+ lib.avifDecoderSetIO(decoder, &io);
+
+ result = lib.avifDecoderParse(decoder);
+ if (result != AVIF_RESULT_OK) {
+ IMG_SetError("Couldn't parse AVIF image: %d", result);
+ goto done;
+ }
+
+ result = lib.avifDecoderNextImage(decoder);
+ if (result != AVIF_RESULT_OK) {
+ IMG_SetError("Couldn't get AVIF image: %d", result);
+ goto done;
+ }
+
+ surface = SDL_CreateRGBSurfaceWithFormat(0, decoder->image->width, decoder->image->height, 0, SDL_PIXELFORMAT_ARGB8888);
+ if (!surface) {
+ goto done;
+ }
+
+ /* Convert the YUV image to RGB */
+ rgb.width = surface->w;
+ rgb.height = surface->h;
+ rgb.depth = 8;
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ rgb.format = AVIF_RGB_FORMAT_BGRA;
+#else
+ rgb.format = AVIF_RGB_FORMAT_ARGB;
+#endif
+ rgb.pixels = (uint8_t *)surface->pixels;
+ rgb.rowBytes = (uint32_t)surface->pitch;
+ result = lib.avifImageYUVToRGB(decoder->image, &rgb);
+ if (result != AVIF_RESULT_OK) {
+ IMG_SetError("Couldn't convert AVIF image to RGB: %d", result);
+ SDL_FreeSurface(surface);
+ surface = NULL;
+ goto done;
+ }
+
+done:
+ if (decoder) {
+ lib.avifDecoderDestroy(decoder);
+ }
+ if (!surface) {
+ SDL_RWseek(src, start, RW_SEEK_SET);
+ }
+ return surface;
+}
+
+#else
+#if _MSC_VER >= 1300
+#pragma warning(disable : 4100) /* warning C4100: 'op' : unreferenced formal parameter */
+#endif
+
+int IMG_InitAVIF()
+{
+ IMG_SetError("AVIF images are not supported");
+ return(-1);
+}
+
+void IMG_QuitAVIF()
+{
+}
+
+/* See if an image is contained in a data source */
+int IMG_isAVIF(SDL_RWops *src)
+{
+ return(0);
+}
+
+/* Load a AVIF type image from an SDL datasource */
+SDL_Surface *IMG_LoadAVIF_RW(SDL_RWops *src)
+{
+ return(NULL);
+}
+
+#endif /* LOAD_AVIF */
diff --git a/Makefile.am b/Makefile.am
index 77a61a2..11b8a0a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,6 +13,7 @@ endif
libSDL2_image_la_SOURCES = \
IMG.c \
+ IMG_avif.c \
IMG_bmp.c \
IMG_gif.c \
IMG_jpg.c \
diff --git a/Makefile.in b/Makefile.in
index 57b42f5..60e4b95 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -145,16 +145,17 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
"$(DESTDIR)$(libSDL2_imageincludedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
-am__libSDL2_image_la_SOURCES_DIST = IMG.c IMG_bmp.c IMG_gif.c \
- IMG_jpg.c IMG_jxl.c IMG_lbm.c IMG_pcx.c IMG_png.c IMG_pnm.c \
- IMG_qoi.c IMG_svg.c IMG_tga.c IMG_tif.c IMG_xcf.c IMG_xpm.c \
- IMG_xv.c IMG_webp.c IMG_WIC.c IMG_ImageIO.m miniz.h nanosvg.h \
- nanosvgrast.h qoi.h
+am__libSDL2_image_la_SOURCES_DIST = IMG.c IMG_avif.c IMG_bmp.c \
+ IMG_gif.c IMG_jpg.c IMG_jxl.c IMG_lbm.c IMG_pcx.c IMG_png.c \
+ IMG_pnm.c IMG_qoi.c IMG_svg.c IMG_tga.c IMG_tif.c IMG_xcf.c \
+ IMG_xpm.c IMG_xv.c IMG_webp.c IMG_WIC.c IMG_ImageIO.m miniz.h \
+ nanosvg.h nanosvgrast.h qoi.h
@USE_IMAGEIO_TRUE@am__objects_1 = IMG_ImageIO.lo
-am_libSDL2_image_la_OBJECTS = IMG.lo IMG_bmp.lo IMG_gif.lo IMG_jpg.lo \
- IMG_jxl.lo IMG_lbm.lo IMG_pcx.lo IMG_png.lo IMG_pnm.lo \
- IMG_qoi.lo IMG_svg.lo IMG_tga.lo IMG_tif.lo IMG_xcf.lo \
- IMG_xpm.lo IMG_xv.lo IMG_webp.lo IMG_WIC.lo $(am__objects_1)
+am_libSDL2_image_la_OBJECTS = IMG.lo IMG_avif.lo IMG_bmp.lo IMG_gif.lo \
+ IMG_jpg.lo IMG_jxl.lo IMG_lbm.lo IMG_pcx.lo IMG_png.lo \
+ IMG_pnm.lo IMG_qoi.lo IMG_svg.lo IMG_tga.lo IMG_tif.lo \
+ IMG_xcf.lo IMG_xpm.lo IMG_xv.lo IMG_webp.lo IMG_WIC.lo \
+ $(am__objects_1)
libSDL2_image_la_OBJECTS = $(am_libSDL2_image_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -185,16 +186,16 @@ DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/IMG.Plo ./$(DEPDIR)/IMG_ImageIO.Plo \
- ./$(DEPDIR)/IMG_WIC.Plo ./$(DEPDIR)/IMG_bmp.Plo \
- ./$(DEPDIR)/IMG_gif.Plo ./$(DEPDIR)/IMG_jpg.Plo \
- ./$(DEPDIR)/IMG_jxl.Plo ./$(DEPDIR)/IMG_lbm.Plo \
- ./$(DEPDIR)/IMG_pcx.Plo ./$(DEPDIR)/IMG_png.Plo \
- ./$(DEPDIR)/IMG_pnm.Plo ./$(DEPDIR)/IMG_qoi.Plo \
- ./$(DEPDIR)/IMG_svg.Plo ./$(DEPDIR)/IMG_tga.Plo \
- ./$(DEPDIR)/IMG_tif.Plo ./$(DEPDIR)/IMG_webp.Plo \
- ./$(DEPDIR)/IMG_xcf.Plo ./$(DEPDIR)/IMG_xpm.Plo \
- ./$(DEPDIR)/IMG_xv.Plo ./$(DEPDIR)/showanim.Po \
- ./$(DEPDIR)/showimage.Po
+ ./$(DEPDIR)/IMG_WIC.Plo ./$(DEPDIR)/IMG_avif.Plo \
+ ./$(DEPDIR)/IMG_bmp.Plo ./$(DEPDIR)/IMG_gif.Plo \
+ ./$(DEPDIR)/IMG_jpg.Plo ./$(DEPDIR)/IMG_jxl.Plo \
+ ./$(DEPDIR)/IMG_lbm.Plo ./$(DEPDIR)/IMG_pcx.Plo \
+ ./$(DEPDIR)/IMG_png.Plo ./$(DEPDIR)/IMG_pnm.Plo \
+ ./$(DEPDIR)/IMG_qoi.Plo ./$(DEPDIR)/IMG_svg.Plo \
+ ./$(DEPDIR)/IMG_tga.Plo ./$(DEPDIR)/IMG_tif.Plo \
+ ./$(DEPDIR)/IMG_webp.Plo ./$(DEPDIR)/IMG_xcf.Plo \
+ ./$(DEPDIR)/IMG_xpm.Plo ./$(DEPDIR)/IMG_xv.Plo \
+ ./$(DEPDIR)/showanim.Po ./$(DEPDIR)/showimage.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -320,6 +321,8 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
+LIBAVIF_CFLAGS = @LIBAVIF_CFLAGS@
+LIBAVIF_LIBS = @LIBAVIF_LIBS@
LIBJPEG_CFLAGS = @LIBJPEG_CFLAGS@
LIBJPEG_LIBS = @LIBJPEG_LIBS@
LIBJXL_CFLAGS = @LIBJXL_CFLAGS@
@@ -444,6 +447,7 @@ libSDL2_imageinclude_HEADERS = \
@USE_IMAGEIO_TRUE@IMAGEIO_SOURCE = IMG_ImageIO.m
libSDL2_image_la_SOURCES = \
IMG.c \
+ IMG_avif.c \
IMG_bmp.c \
IMG_gif.c \
IMG_jpg.c \
@@ -598,6 +602,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_ImageIO.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_WIC.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_avif.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_bmp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_gif.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_jpg.Plo@am__quote@ # am--include-marker
@@ -996,6 +1001,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/IMG.Plo
-rm -f ./$(DEPDIR)/IMG_ImageIO.Plo
-rm -f ./$(DEPDIR)/IMG_WIC.Plo
+ -rm -f ./$(DEPDIR)/IMG_avif.Plo
-rm -f ./$(DEPDIR)/IMG_bmp.Plo
-rm -f ./$(DEPDIR)/IMG_gif.Plo
-rm -f ./$(DEPDIR)/IMG_jpg.Plo
@@ -1065,6 +1071,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/IMG.Plo
-rm -f ./$(DEPDIR)/IMG_ImageIO.Plo
-rm -f ./$(DEPDIR)/IMG_WIC.Plo
+ -rm -f ./$(DEPDIR)/IMG_avif.Plo
-rm -f ./$(DEPDIR)/IMG_bmp.Plo
-rm -f ./$(DEPDIR)/IMG_gif.Plo
-rm -f ./$(DEPDIR)/IMG_jpg.Plo
diff --git a/SDL_image.h b/SDL_image.h
index b03c752..3808cf5 100644
--- a/SDL_image.h
+++ b/SDL_image.h
@@ -79,11 +79,12 @@ extern DECLSPEC const SDL_version * SDLCALL IMG_Linked_Version(void);
typedef enum
{
- IMG_INIT_JPG = 0x00000001,
- IMG_INIT_PNG = 0x00000002,
- IMG_INIT_TIF = 0x00000004,
- IMG_INIT_WEBP = 0x00000008,
- IMG_INIT_JXL = 0x00000010
+ IMG_INIT_JPG = 0x00000001,
+ IMG_INIT_PNG = 0x00000002,
+ IMG_INIT_TIF = 0x00000004,
+ IMG_INIT_WEBP = 0x00000008,
+ IMG_INIT_JXL = 0x00000010,
+ IMG_INIT_AVIF = 0x00000020
} IMG_InitFlags;
/* Loads dynamic libraries and prepares them for use. Flags should be
@@ -117,6 +118,7 @@ extern DECLSPEC SDL_Texture * SDLCALL IMG_LoadTextureTyped_RW(SDL_Renderer *rend
#endif /* SDL 2.0 */
/* Functions to detect a file type, given a seekable source */
+extern DECLSPEC int SDLCALL IMG_isAVIF(SDL_RWops *src);
extern DECLSPEC int SDLCALL IMG_isICO(SDL_RWops *src);
extern DECLSPEC int SDLCALL IMG_isCUR(SDL_RWops *src);
extern DECLSPEC int SDLCALL IMG_isBMP(SDL_RWops *src);
@@ -136,6 +138,7 @@ extern DECLSPEC int SDLCALL IMG_isXV(SDL_RWops *src);
extern DECLSPEC int SDLCALL IMG_isWEBP(SDL_RWops *src);
/* Individual loading functions */
+extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadAVIF_RW(SDL_RWops *src);
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_RW(SDL_RWops *src);
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_RW(SDL_RWops *src);
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_RW(SDL_RWops *src);
diff --git a/configure b/configure
index 32a8543..0b4e874 100755
--- a/configure
+++ b/configure
@@ -788,6 +788,8 @@ LIBJXL_LIBS
LIBJXL_CFLAGS
LIBJPEG_LIBS
LIBJPEG_CFLAGS
+LIBAVIF_LIBS
+LIBAVIF_CFLAGS
SDL2_CONFIG
SDL_LIBS
SDL_CFLAGS
@@ -941,6 +943,8 @@ enable_libtool_lock
enable_dependency_tracking
enable_silent_rules
enable_imageio
+enable_avif
+enable_avif_shared
enable_bmp
enable_gif
enable_jpg
@@ -983,6 +987,8 @@ PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
SDL_CFLAGS
SDL_LIBS
+LIBAVIF_CFLAGS
+LIBAVIF_LIBS
LIBJPEG_CFLAGS
LIBJPEG_LIBS
LIBJXL_CFLAGS
@@ -1624,6 +1630,8 @@ Optional Features:
--disable-silent-rules verbose build output (undo: "make V=0")
--enable-imageio use native Mac OS X frameworks for loading images
[default=yes]
+ --enable-avif support loading AVIF images [default=yes]
+ --enable-avif-shared dynamically load AVIF support [default=yes]
--enable-bmp support loading BMP/ICO/CUR images [default=yes]
--enable-gif support loading GIF images [default=yes]
--enable-jpg support loading JPG images [default=yes]
@@ -1676,6 +1684,10 @@ Some influential environment variables:
path overriding pkg-config's built-in search path
SDL_CFLAGS C compiler flags for SDL, overriding pkg-config
SDL_LIBS linker flags for SDL, overriding pkg-config
+ LIBAVIF_CFLAGS
+ C compiler flags for LIBAVIF, overriding pkg-config
+ LIBAVIF_LIBS
+ linker flags for LIBAVIF, overriding pkg-config
LIBJPEG_CFLAGS
C compiler flags for LIBJPEG, overriding pkg-config
LIBJPEG_LIBS
@@ -4096,13 +4108,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:4099: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:4111: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:4102: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:4114: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:4105: output\"" >&5)
+ (eval echo "\"\$as_me:4117: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5316,7 +5328,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5319 "configure"' > conftest.$ac_ext
+ echo '#line 5331 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7141,11 +7153,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7144: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7156: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7148: \$? = $ac_status" >&5
+ echo "$as_me:7160: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7490,11 +7502,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7493: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7505: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7497: \$? = $ac_status" >&5
+ echo "$as_me:7509: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7595,11 +7607,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7598: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7610: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7602: \$? = $ac_status" >&5
+ echo "$as_me:7614: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7650,11 +7662,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7653: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7665: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7657: \$? = $ac_status" >&5
+ echo "$as_me:7669: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10085,7 +10097,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10088 "configure"
+#line 10100 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10181,7 +10193,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10184 "configure"
+#line 10196 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12783,6 +12795,20 @@ $as_echo "$have_gcc_fvisibility" >&6; }
fi
}
+# Check whether --enable-avif was given.
+if test "${enable_avif+set}" = set; then :
+ enableval=$enable_avif;
+else
+ enable_avif=yes
+fi
+
+# Check whether --enable-avif-shared was given.
+if test "${enable_avif_shared+set}" = set; then :
+ enableval=$enable_avif_shared;
+else
+ enable_avif_shared=yes
+fi
+
# Check whether --enable-bmp was given.
if test "${enable_bmp+set}" = set; then :
enableval=$enable_bmp;
@@ -13262,6 +13288,213 @@ rm -f core conftest.err conftest.$ac_objext \
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
+if test x$enable_avif = xyes; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libavif" >&5
+$as_echo_n "checking for libavif... " >&6; }
+
+if test -n "$LIBAVIF_CFLAGS"; then
+ pkg_cv_LIBAVIF_CFLAGS="$LIBAVIF_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavif\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libavif") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBAVIF_CFLAGS=`$PKG_CONFIG --cflags "libavif" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBAVIF_LIBS"; then
+ pkg_cv_LIBAVIF_LIBS="$LIBAVIF_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavif\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libavif") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBAVIF_LIBS=`$PKG_CONFIG --libs "libavif" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ LIBAVIF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavif" 2>&1`
+ else
+ LIBAVIF_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavif" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBAVIF_PKG_ERRORS" >&5
+
+ ac_fn_c_check_header_mongrel "$LINENO" "avif/avif.h" "ac_cv_header_avif_avif_h" "$ac_includes_default"
+if test "x$ac_cv_header_avif_avif_h" = xyes; then :
+
+ have_avif_hdr=yes
+ LIBAVIF_CFLAGS=""
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avifVersion in -lavif" >&5
+$as_echo_n "checking for avifVersion in -lavif... " >&6; }
+if ${ac_cv_lib_avif_avifVersion+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lavif $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char avifVersion ();
+int
+main ()
+{
+return avifVersion ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_avif_avifVersion=yes
+else
+ ac_cv_lib_avif_avifVersion=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avif_avifVersion" >&5
+$as_echo "$ac_cv_lib_avif_avifVersion" >&6; }
+if test "x$ac_cv_lib_avif_avifVersion" = xyes; then :
+
+ have_avif_lib=yes
+ LIBAVIF_LIBS="-lavif"
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ac_fn_c_check_header_mongrel "$LINENO" "avif/avif.h" "ac_cv_header_avif_avif_h" "$ac_includes_default"
+if test "x$ac_cv_header_avif_avif_h" = xyes; then :
+
+ have_avif_hdr=yes
+ LIBAVIF_CFLAGS=""
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avifVersion in -lavif" >&5
+$as_echo_n "checking for avifVersion in -lavif... " >&6; }
+if ${ac_cv_lib_avif_avifVersion+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lavif $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char avifVersion ();
+int
+main ()
+{
+return avifVersion ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_avif_avifVersion=yes
+else
+ ac_cv_lib_avif_avifVersion=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avif_avifVersion" >&5
+$as_echo "$ac_cv_lib_avif_avifVersion" >&6; }
+if test "x$ac_cv_lib_avif_avifVersion" = xyes; then :
+
+ have_avif_lib=yes
+ LIBAVIF_LIBS="-lavif"
+
+fi
+
+
+else
+ LIBAVIF_CFLAGS=$pkg_cv_LIBAVIF_CFLAGS
+ LIBAVIF_LIBS=$pkg_cv_LIBAVIF_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ have_avif_hdr=yes
+ have_avif_lib=yes
+ have_avif_pc=yes
+
+fi
+ if test x$have_avif_hdr = xyes -a x$have_avif_lib = xyes; then
+ if test x$enable_avif = xyes; then
+ $as_echo "#define LOAD_AVIF 1" >>confdefs.h
+
+ fi
+
+ case "$host" in
+ *-*-darwin*)
+ avif_lib=`find_lib libavif.dylib`
+ ;;
+ *-*-cygwin* | *-*-mingw*)
+ avif_lib=`find_lib "libavif*.dll"`
+ ;;
+ *)
+ avif_lib=`find_lib "libavif[0-9]*.so.*"`
+ if test x$avif_lib = x; then
+ avif_lib=`find_lib "libavif.so.*"`
+ fi
+ ;;
+ esac
+ elif test x$enable_avif = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Unable to find AVIF library (https://github.com/AOMediaCodec/libavif)" >&5
+$as_echo "$as_me: WARNING: *** Unable to find AVIF library (https://github.com/AOMediaCodec/libavif)" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: AVIF image loading disabled" >&5
+$as_echo "$as_me: WARNING: AVIF image loading disabled" >&2;}
+ fi
+fi
+
if (test x$enable_jpg = xyes || test x$enable_tif = xyes) && test x$enable_imageio != xyes; then
pkg_failed=no
@@ -14373,6 +14606,23 @@ _ACEOF
fi
fi
+if test x$enable_avif = xyes -a x$have_avif_hdr = xyes -a x$have_avif_lib = xyes; then
+ CFLAGS="$LIBAVIF_CFLAGS $CFLAGS
(Patch may be truncated, please check the link at the top of this post.)