Skip to content

Commit

Permalink
implemented avif support for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
CrackedPixel committed Feb 22, 2025
1 parent 99d2119 commit bff841c
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include
SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib
SDL_LIBRARIES ?= -lSDL2 -lSDL2main

# AVIF support: It requires libavif to be provided externally
# WARNING: Library is not included in raylib, it MUST be configured by users
LIBAVIF_ENABLE ?= TRUE
LIBAVIF_ROOT_PATH ?= $(RAYLIB_SRC_PATH)/external/libavif
LIBAVIF_INCLUDE_PATH ?= $(LIBAVIF_ROOT_PATH)/include
LIBAVIF_SRC_PATH ?= $(LIBAVIF_ROOT_PATH)/src
LIBAVIF_LIBRARY_PATH ?= $(LIBAVIF_ROOT_PATH)/lib
LIBAVIF_LIBRARIES ?= -lavif

# Determine if the file has root access (only required to install raylib)
# "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root")
ROOT = $(shell whoami)
Expand Down Expand Up @@ -508,6 +517,11 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
endif
endif

# AVIF
ifeq ($(LIBAVIF_ENABLE),TRUE)
INCLUDE_PATHS += -I$(LIBAVIF_INCLUDE_PATH)
endif

# Define library paths containing required libs: LDFLAGS
# NOTE: This is only required for dynamic library generation
#------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -555,6 +569,11 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
LDFLAGS += -Wl,-undefined,dynamic_lookup
endif

# AVIF
ifeq ($(LIBAVIF_ENABLE),TRUE)
LDFLAGS += -L$(LIBAVIF_LIBRARY_PATH)
endif

# Define libraries required on linking: LDLIBS
# NOTE: This is only required for dynamic library generation
#------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -632,6 +651,11 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm
endif

# AVIF
ifeq ($(LIBAVIF_ENABLE),TRUE)
LDLIBS += $(LIBAVIF_LIBRARIES)
endif

# Define source code object files required
#------------------------------------------------------------------------------------------------
OBJS = rcore.o \
Expand Down Expand Up @@ -785,6 +809,15 @@ endif
android_native_app_glue.o : $(NATIVE_APP_GLUE)/android_native_app_glue.c
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS)

# AVIF
libavif.o : $(LIBAVIF_SRC_PATH)/avif.c
ifeq ($(LIBAVIF_ENABLE),TRUE)
cmake -S $(LIBAVIF_ROOT_PATH) -B $(LIBAVIF_LIBRARY_PATH)
make -C $(LIBAVIF_LIBRARY_PATH)
else
@echo "AVIF support is disabled, skipping AVIF library build."
endif

# Install generated and needed files to desired directories.
# On GNU/Linux and BSDs, there are some standard directories that contain extra
# libraries and header files. These directories (often /usr/local/lib and
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
//#define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_AVIF 1

// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1
Expand Down
99 changes: 99 additions & 0 deletions src/rtextures.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* #define SUPPORT_FILEFORMAT_KTX
* #define SUPPORT_FILEFORMAT_PVR
* #define SUPPORT_FILEFORMAT_ASTC
* #define SUPPORT_FILEFORMAT_AVIF
* Select desired fileformats to be supported for image data loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
Expand Down Expand Up @@ -210,6 +211,11 @@
#include "external/stb_perlin.h" // Required for: stb_perlin_fbm_noise3
#endif

// AVIF
#if defined(SUPPORT_FILEFORMAT_AVIF)
#include "external/libavif/include/avif/avif.h"
#endif

#define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
#define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))

Expand Down Expand Up @@ -546,6 +552,99 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
{
image.data = rl_load_astc_from_memory(fileData, dataSize, &image.width, &image.height, &image.format, &image.mipmaps);
}
#endif
#if defined(SUPPORT_FILEFORMAT_AVIF)
else if ((strcmp(fileType, ".avif") == 0) || (strcmp(fileType, ".AVIF") == 0))
{
avifRGBImage rgb;
avifDecoder* decoder = avifDecoderCreate();
if (!decoder)
{
TRACELOG(LOG_WARNING, "IMAGE: Failed to create AVIF decoder");
return image;
}

avifResult result = avifDecoderSetIOMemory(decoder, fileData, dataSize);
if (result != AVIF_RESULT_OK)
{
TRACELOG(LOG_WARNING, "IMAGE: Cannot set IO on avifDecoder");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

result = avifDecoderParse(decoder);
if (result != AVIF_RESULT_OK)
{
TRACELOG(LOG_WARNING, "IMAGE: Failed to parse AVIF data");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

if (avifDecoderNextImage(decoder) == AVIF_RESULT_OK)
{
avifRGBImageSetDefaults(&rgb, decoder->image);

result = avifRGBImageAllocatePixels(&rgb);
if (result != AVIF_RESULT_OK)
{
TRACELOG(LOG_WARNING, "IMAGE: Allocation of RGB samples failed");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

result = avifImageYUVToRGB(decoder->image, &rgb);
if (result != AVIF_RESULT_OK)
{
TRACELOG(LOG_WARNING, "IMAGE: Conversion from YUV failed");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

image.mipmaps = 1;
image.width = rgb.width;
image.height = rgb.height;

size_t pixelCount = rgb.width * rgb.height * 4;
if (rgb.depth > 8)
{
image.data = RL_MALLOC(pixelCount * sizeof(uint16_t));
if (!image.data)
{
TRACELOG(LOG_WARNING, "IMAGE: Failed to allocate memory for 16-bit image data");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

uint16_t *firstPixel = (uint16_t *)rgb.pixels;
memcpy(image.data, firstPixel, pixelCount * sizeof(uint16_t));
image.format = PIXELFORMAT_UNCOMPRESSED_R16G16B16A16;
}
else
{
image.data = RL_MALLOC(pixelCount * sizeof(uint8_t));
if (!image.data)
{
TRACELOG(LOG_WARNING, "IMAGE: Failed to allocate memory for 8-bit image data");
avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
return image;
}

uint8_t *firstPixel = rgb.pixels;
memcpy(image.data, firstPixel, pixelCount * sizeof(uint8_t));
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
}

avifRGBImageFreePixels(&rgb);
avifDecoderDestroy(decoder);
}
else TRACELOG(LOG_WARNING, "IMAGE: Failed to decode AVIF data");
}
#endif
else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported");

Expand Down

0 comments on commit bff841c

Please sign in to comment.