diff --git a/libc3/window/cairo/configure b/libc3/window/cairo/configure
index 4f6c3ca..4b1b995 100755
--- a/libc3/window/cairo/configure
+++ b/libc3/window/cairo/configure
@@ -44,8 +44,6 @@ config_asan
config_gnu
pkg_config cairo
pkg_config freetype2
-#config_lib IL -lIL -lILU
-config_lib FREEIMAGE -lfreeimage
pkg_config libbsd-overlay
pkg_config xkbcommon
config_lib_have COCOA -framework Cocoa
diff --git a/libc3/window/sdl2/configure b/libc3/window/sdl2/configure
index b33d970..1228de9 100755
--- a/libc3/window/sdl2/configure
+++ b/libc3/window/sdl2/configure
@@ -46,11 +46,10 @@ config_gnu
pkg_config ftgl
pkg_config gl
pkg_config glu
-config_lib IL -lIL -lILU
+pkg_config libpng
pkg_config sdl2
pkg_config libbsd-overlay
config_lib OPENGL -framework OpenGL
-#config_lib SDL2 -framework SDL2
config_define PREFIX "\"${PREFIX}\""
# Address Sanitizer config
diff --git a/libc3/window/sdl2/sdl2_sprite.c b/libc3/window/sdl2/sdl2_sprite.c
index cce8940..5b80aae 100644
--- a/libc3/window/sdl2/sdl2_sprite.c
+++ b/libc3/window/sdl2/sdl2_sprite.c
@@ -25,21 +25,77 @@ void sdl2_sprite_clean (s_sdl2_sprite *sprite)
free(sprite->texture);
}
+static GLenum png_info_to_gl_format (int png_color_type,
+ int png_bit_depth)
+{
+ switch (png_color_type) {
+ case PNG_COLOR_TYPE_GRAY:
+ switch (png_bit_depth) {
+ case 8: return GL_LUMINANCE8;
+ case 16: return GL_LUMINANCE16;
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ switch (png_bit_depth) {
+ case 8: return GL_LUMINANCE8_ALPHA8;
+ case 16: return GL_LUMINANCE16_ALPHA16;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ switch (png_bit_depth) {
+ case 8: return GL_RGB8;
+ case 16: return GL_RGB16;
+ }
+ break;
+ case PNG_COLOR_TYPE_RGBA:
+ switch (png_bit_depth) {
+ case 8: return GL_RGBA8;
+ case 16: return GL_RGBA16;
+ }
+ break;
+ }
+ return 0;
+}
+
+static GLenum png_info_to_gl_type (int png_bit_depth)
+{
+ switch (png_bit_depth) {
+ case 8:
+ return GL_UNSIGNED_BYTE;
+ case 16:
+ return GL_UNSIGNED_SHORT;
+ }
+ return 0;
+}
+
s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
const s8 *path,
uw dim_x, uw dim_y,
uw frame_count)
{
+ u8 *data;
FILE *fp;
+ GLenum gl_format;
+ GLenum gl_type;
uw i;
- png_infop png_info;
+ u8 png_header[8]; // maximum size is 8
+ png_infop png_info;
png_structp png_read;
+ png_bytep *png_row;
+ u32 png_w;
+ u32 png_h;
+ s32 png_bit_depth;
+ s32 png_color_type;
+ u8 *sprite_data;
+ uw sprite_stride;
uw x;
uw y;
+ uw v;
assert(sprite);
assert(path);
assert(dim_x);
assert(dim_y);
+ frame_count = (frame_count > 0) ? frame_count : (dim_x * dim_y);
str_init_copy_1(&sprite->path, path);
if (! file_search(&sprite->path, sym_1("r"), &sprite->real_path)) {
warnx("sdl2_sprite_init: file not found: %s", path);
@@ -68,63 +124,120 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
str_clean(&sprite->real_path);
return NULL;
}
- png_read = png_create_read_struct
- (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-
- if (!png_ptr)
- return ERROR;
- sprite->total_w = ilGetInteger(IL_IMAGE_WIDTH);
- sprite->total_h = ilGetInteger(IL_IMAGE_HEIGHT);
- //bpp = ilGetInteger(IL_IMAGE_BPP);
+ png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
+ NULL);
+ if (!png_read) {
+ warn("sdl2_sprite_init: %s: png_create_read_struct",
+ sprite->real_path.ptr.ps8);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ if (setjmp(png_jmpbuf(png_read))) {
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_init_io(png_read, fp);
+ png_set_sig_bytes(png_read, sizeof(png_header));
+ //png_set_compression_buffer_size(png_read, buffer_size);
+ png_read_png(png_read, png_info,
+ PNG_TRANSFORM_PACKING, NULL);
+ png_get_IHDR(png_read, png_info, &png_w, &png_h,
+ &png_bit_depth, &png_color_type,
+ NULL, NULL, NULL);
+ if (png_color_type == PNG_COLOR_TYPE_PALETTE) {
+ warnx("sdl2_sprite_init: %s: PNG_COLOR_TYPE_PALETTE",
+ sprite->real_path.ptr.ps8);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ png_row = png_get_rows(png_read, png_info);
+ if (! png_row) {
+ warnx("sdl2_sprite_init: %s: png_get_rows => NULL",
+ sprite->real_path.ptr.ps8);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ sprite->total_w = png_w;
+ sprite->total_h = png_h;
sprite->dim_x = dim_x;
sprite->dim_y = dim_y;
sprite->w = sprite->total_w / dim_x;
sprite->h = sprite->total_h / dim_y;
- sprite->frame_count = frame_count ? frame_count : (dim_x * dim_y);
+ sprite->frame_count = frame_count;
sprite->texture = malloc(frame_count * sizeof(GLuint));
if (! sprite->texture) {
warn("sdl2_sprite_init: sprite->texture");
- ilDeleteImages(2, il_image);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ gl_format = png_info_to_gl_format(png_color_type, png_bit_depth);
+ if (! gl_format) {
+ warnx("sdl2_sprite_init: %s: unknown OpenGL format",
+ sprite->real_path.ptr.ps8);
+ free(sprite->texture);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ gl_type = png_info_to_gl_type(png_bit_depth);
+ if (! gl_type) {
+ warnx("sdl2_sprite_init: %s: unknown OpenGL type",
+ sprite->real_path.ptr.ps8);
+ free(sprite->texture);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
+ sprite_stride = sprite->w * (png_bit_depth / 8);
+ data = malloc(sprite->h * sprite_stride);
+ if (! data) {
+ warn("sdl2_sprite_init: %s", sprite->real_path.ptr.ps8);
+ free(sprite->texture);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
str_clean(&sprite->path);
str_clean(&sprite->real_path);
return NULL;
}
- glGenTextures(frame_count, sprite->texture);
- ilBindImage(il_image[1]);
- ilTexImage(sprite->w, sprite->h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE,
- NULL);
- data[1] = ilGetData();
- ilBindImage(il_image[2]);
- sprite->tex_w = 1;
- while (sprite->tex_w < sprite->w)
- sprite->tex_w *= 2;
- sprite->tex_h = 1;
- while (sprite->tex_h < sprite->h)
- sprite->tex_h *= 2;
- ilTexImage(sprite->tex_w, sprite->tex_h, 1, 4, IL_RGBA,
- IL_UNSIGNED_BYTE, NULL);
- data[2] = ilGetData();
- ilBindImage(il_image[0]);
i = 0;
y = 0;
while (i < sprite->frame_count && y < dim_y) {
x = 0;
while (i < sprite->frame_count && x < dim_x) {
- ilCopyPixels(x * sprite->w, y * sprite->h, 0,
- sprite->w, sprite->h, 1, IL_RGBA, IL_UNSIGNED_BYTE,
- data[1]);
- iluImageParameter(ILU_FILTER, ILU_SCALE_MITCHELL);
- ilBlit(il_image[1], 0, 0, 0, 0, 0, 0,
- sprite->tex_w, sprite->tex_h, 1);
+ sprite_data = data;
+ v = 0;
+ while (v < sprite->h) {
+ memcpy(sprite_data, png_row[v], sprite_stride);
+ v++;
+ }
glBindTexture(GL_TEXTURE_2D, sprite->texture[i]);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- sprite->tex_w, sprite->tex_h, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, data[2]);
+ glTexImage2D(GL_TEXTURE_2D, 0, gl_format, sprite->w, sprite->h,
+ 0, gl_format, gl_type, data);
i++;
x++;
}
y++;
}
- ilDeleteImages(3, il_image);
+ free(data);
+ png_destroy_read_struct(&png_read, &png_info, NULL);
+ fclose(fp);
return sprite;
}