From e07985e898d77a52125ba5a4931c75d9579f0f67 Mon Sep 17 00:00:00 2001 From: Eduardo Lima Mitev Date: Mon, 29 Oct 2018 11:24:58 +0100 Subject: [PATCH] Add an example program that loads a PNG or JPEG image into a GL texture --- gl-image-loader/.dir-locals.el | 13 ++ gl-image-loader/Makefile | 30 +++ gl-image-loader/igalia-white-text.png | Bin 0 -> 78969 bytes gl-image-loader/image.c | 101 ++++++++++ gl-image-loader/image.h | 43 +++++ gl-image-loader/jpeg.c | 139 ++++++++++++++ gl-image-loader/jpeg.h | 82 ++++++++ gl-image-loader/main.c | 258 ++++++++++++++++++++++++++ gl-image-loader/png.c | 148 +++++++++++++++ gl-image-loader/png.h | 45 +++++ 10 files changed, 859 insertions(+) create mode 100644 gl-image-loader/.dir-locals.el create mode 100644 gl-image-loader/Makefile create mode 100644 gl-image-loader/igalia-white-text.png create mode 100644 gl-image-loader/image.c create mode 100644 gl-image-loader/image.h create mode 100644 gl-image-loader/jpeg.c create mode 100644 gl-image-loader/jpeg.h create mode 100644 gl-image-loader/main.c create mode 100644 gl-image-loader/png.c create mode 100644 gl-image-loader/png.h diff --git a/gl-image-loader/.dir-locals.el b/gl-image-loader/.dir-locals.el new file mode 100644 index 0000000..d9a374c --- /dev/null +++ b/gl-image-loader/.dir-locals.el @@ -0,0 +1,13 @@ +((prog-mode + (indent-tabs-mode . nil) + (tab-width . 8) + (c-basic-offset . 3) + (c-file-style . "stroustrup") + (fill-column . 78) + (eval . (progn + (c-set-offset 'case-label '0) + (c-set-offset 'innamespace '0) + (c-set-offset 'inline-open '0))) + ) + (makefile-mode (indent-tabs-mode . t)) + ) diff --git a/gl-image-loader/Makefile b/gl-image-loader/Makefile new file mode 100644 index 0000000..049d406 --- /dev/null +++ b/gl-image-loader/Makefile @@ -0,0 +1,30 @@ +.PHONY: all clean + +CFLAGS = -std=c99 -g -ggdb -O0 -Wall + +LDFLAGS = -lm + +PKG_CONFIG_LIBS = \ + glfw3 \ + glesv2 \ + libpng \ + libjpeg \ + $(NULL) + +CFLAGS += $(shell pkg-config --cflags $(PKG_CONFIG_LIBS)) +LDFLAGS += $(shell pkg-config --libs $(PKG_CONFIG_LIBS)) + +OBJS = png.o jpeg.o image.o + +all: gl-image-loader + +png.o: png.c png.h +jpeg.o: jpeg.c jpeg.h +image.o: image.c image.h + +gl-image-loader: main.c $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + rm -f ./*.o + rm -f gl-image-loader diff --git a/gl-image-loader/igalia-white-text.png b/gl-image-loader/igalia-white-text.png new file mode 100644 index 0000000000000000000000000000000000000000..5c42ecb3ef611f66c43c0923637912c80aeaccd9 GIT binary patch literal 78969 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%0AC&xYyqutC+B?S4u0&il<^ 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 literal 0 HcmV?d00001 diff --git a/gl-image-loader/image.c b/gl-image-loader/image.c new file mode 100644 index 0000000..543a065 --- /dev/null +++ b/gl-image-loader/image.c @@ -0,0 +1,101 @@ +#include +#include +#include "image.h" + +bool +o_image_init_from_filename (struct o_image *self, + const char *filename) +{ + assert (self != NULL); + assert (filename != NULL); + + /* Try PNG. */ + bool ok = png_decoder_init_from_filename (&self->png, filename); + if (ok) { + self->type = O_IMAGE_TYPE_PNG; + self->width = self->png.width; + self->height = self->png.height; + + switch (self->png.format) { + case PNG_COLOR_TYPE_RGB: + self->format = O_IMAGE_FORMAT_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + self->format = O_IMAGE_FORMAT_RGBA; + break; + default: + assert (!"PNG image format not handled\n"); + } + } else { + png_clear (&self->png); + + /* Try JPEG. */ + bool ok = jpeg_decoder_init_from_filename (&self->jpeg, filename); + if (ok) { + assert (self->jpeg.status == JPEG_STATUS_DECODE_READY); + + self->type = O_IMAGE_TYPE_JPEG; + self->width = self->jpeg.width; + self->height = self->jpeg.height; + + switch (self->jpeg.format) { + case JPEG_FORMAT_RGB: + case JPEG_FORMAT_EXT_RGB: + self->format = O_IMAGE_FORMAT_RGB; + break; + case JPEG_FORMAT_EXT_RGBA: + self->format = O_IMAGE_FORMAT_RGBA; + break; + default: + printf ("JPEG format: %d\n", self->jpeg.format); + assert (!"JPEG image format not handled\n"); + } + } else { + printf ("Unknown or unhandled image format.\n"); + return false; + } + } + + return true; +} + +void +o_image_clear (struct o_image *self) +{ + assert (self != NULL); + + if (self->type == O_IMAGE_TYPE_PNG) + png_clear (&self->png); + else if (self->type == O_IMAGE_TYPE_JPEG) + jpeg_clear (&self->jpeg); +} + +ssize_t +o_image_read (struct o_image *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows) +{ + assert (self != NULL); + + switch (self->type) { + case O_IMAGE_TYPE_PNG: + return png_read (&self->png, + buffer, + size, + first_row, + num_rows); + + case O_IMAGE_TYPE_JPEG: + return jpeg_read (&self->jpeg, + buffer, + size, + first_row, + num_rows); + + default: + errno = ENXIO; + return -1; + } +} diff --git a/gl-image-loader/image.h b/gl-image-loader/image.h new file mode 100644 index 0000000..afb5c82 --- /dev/null +++ b/gl-image-loader/image.h @@ -0,0 +1,43 @@ +#pragma once + +#include "jpeg.h" +#include "png.h" +#include +#include + +enum o_image_format { + O_IMAGE_FORMAT_INVALID, + O_IMAGE_FORMAT_RGB, + O_IMAGE_FORMAT_RGBA, +}; + +enum o_image_type { + O_IMAGE_TYPE_INVALID, + O_IMAGE_TYPE_PNG, + O_IMAGE_TYPE_JPEG, +}; + +struct o_image { + uint32_t width; + uint32_t height; + + uint8_t type; + uint32_t format; + + struct png_ctx png; + struct jpeg_ctx jpeg; +}; + +bool +o_image_init_from_filename (struct o_image *self, + const char *filename); + +void +o_image_clear (struct o_image *self); + +ssize_t +o_image_read (struct o_image *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows); diff --git a/gl-image-loader/jpeg.c b/gl-image-loader/jpeg.c new file mode 100644 index 0000000..3e7c85e --- /dev/null +++ b/gl-image-loader/jpeg.c @@ -0,0 +1,139 @@ +#include +#include +#include "jpeg.h" +#include + +static void +handle_error_exit (j_common_ptr cinfo) +{ + struct jpeg_error_handler *err_handler = + (struct jpeg_error_handler *) cinfo->err; + + /* Display the message. */ + (*cinfo->err->output_message) (cinfo); + + err_handler->ctx->status = JPEG_STATUS_ERROR; + + longjmp (err_handler->setjmp_buffer, 1); +} + +/* public API */ + +bool +jpeg_decoder_init_from_filename (struct jpeg_ctx *self, + const char *filename) +{ + assert (self != NULL); + assert (filename != NULL); + + memset (self, 0x00, sizeof (struct jpeg_ctx)); + + self->file_obj = fopen (filename, "rb"); + if (self->file_obj == NULL) + return false; + + /* Set an error manager. */ + self->cinfo.err = + jpeg_std_error (&self->err_handler.jpeg_error_mgr); + self->err_handler.jpeg_error_mgr.error_exit = + handle_error_exit; + + self->err_handler.ctx = self; + + if (setjmp (self->err_handler.setjmp_buffer) != 0) { + /* @FIXME: check the error code and fill errno accordingly */ + jpeg_clear (self); + return false; + } + + /* Create and set up the decompression object. */ + jpeg_create_decompress (&self->cinfo); + jpeg_stdio_src (&self->cinfo, self->file_obj); + + /* Read JPEG header. */ + int result = jpeg_read_header (&self->cinfo, true); + if (result != JPEG_HEADER_OK) { + jpeg_clear (self); + return false; + } + + jpeg_start_decompress (&self->cinfo); + + self->row_stride = self->cinfo.output_width * self->cinfo.output_components; + self->width = self->cinfo.output_width; + self->height = self->cinfo.output_height; + self->format = self->cinfo.out_color_space; + + self->status = JPEG_STATUS_DECODE_READY; + + return true; +} + +void +jpeg_clear (struct jpeg_ctx *self) +{ + if (self->file_obj != NULL) { + fclose (self->file_obj); + self->file_obj = NULL; + } + + if (self->status != JPEG_STATUS_NONE) + jpeg_destroy_decompress (&self->cinfo); + + self->status = JPEG_STATUS_NONE; +} + +ssize_t +jpeg_read (struct jpeg_ctx *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows) +{ + assert (self != NULL); + assert (self->status == JPEG_STATUS_DECODE_READY || + self->status == JPEG_STATUS_DONE); + assert (size == 0 || buffer != NULL); + assert (self->row_stride > 0 && size >= self->row_stride); + + size_t _num_rows = 0; + size_t _first_row = 0; + size_t result = 0; + + if (self->status == JPEG_STATUS_DONE) + goto out; + + _first_row = self->cinfo.output_scanline; + + uint32_t lines = size / self->row_stride; + for (int32_t i = 0; i < lines; i++) { + uint8_t *rowptr[1]; + rowptr[0] = buffer + self->row_stride * i; + + jpeg_read_scanlines (&self->cinfo, rowptr, 1); + if (self->status == JPEG_STATUS_ERROR) { + /* @FIXME: handle exit errors here */ + return -1; + } + + _num_rows++; + } + + _num_rows = self->cinfo.output_scanline - _first_row; + + if (self->cinfo.output_scanline == self->cinfo.output_height) { + jpeg_finish_decompress (&self->cinfo); + self->status = JPEG_STATUS_DONE; + } + + result = _num_rows * self->row_stride; + + out: + if (first_row != NULL) + *first_row = _first_row; + + if (num_rows != NULL) + *num_rows = _num_rows; + + return result; +} diff --git a/gl-image-loader/jpeg.h b/gl-image-loader/jpeg.h new file mode 100644 index 0000000..20d24cf --- /dev/null +++ b/gl-image-loader/jpeg.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +enum jpeg_status { + JPEG_STATUS_NONE = 0, + JPEG_STATUS_DECODE_READY, + JPEG_STATUS_ENCODE_READY, + JPEG_STATUS_ERROR, + JPEG_STATUS_DONE, +}; + +enum jpeg_format { + JPEG_FORMAT_UNKNOWN, /* error/unspecified */ + JPEG_FORMAT_GRAYSCALE, /* monochrome */ + JPEG_FORMAT_RGB, /* red/green/blue as specified by the RGB_RED, + RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ + JPEG_FORMAT_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JPEG_FORMAT_CMYK, /* C/M/Y/K */ + JPEG_FORMAT_YCCK, /* Y/Cb/Cr/K */ + JPEG_FORMAT_EXT_RGB, /* red/green/blue */ + JPEG_FORMAT_EXT_RGBX, /* red/green/blue/x */ + JPEG_FORMAT_EXT_BGR, /* blue/green/red */ + JPEG_FORMAT_EXT_BGRX, /* blue/green/red/x */ + JPEG_FORMAT_EXT_XBGR, /* x/blue/green/red */ + JPEG_FORMAT_EXT_XRGB, /* x/red/green/blue */ + /* When out_color_space is set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, + or JCS_EXT_XRGB during decompression, the X byte is undefined, and in + order to ensure the best performance, libjpeg-turbo can set that byte to + whatever value it wishes. Use the following colorspace constants to + ensure that the X byte is set to 0xFF, so that it can be interpreted as an + opaque alpha channel. */ + JPEG_FORMAT_EXT_RGBA, /* red/green/blue/alpha */ + JPEG_FORMAT_EXT_BGRA, /* blue/green/red/alpha */ + JPEG_FORMAT_EXT_ABGR, /* alpha/blue/green/red */ + JPEG_FORMAT_EXT_ARGB, /* alpha/red/green/blue */ + JPEG_FORMAT_RGB565 /* 5-bit red/6-bit green/5-bit blue */ +}; + +struct jpeg_ctx; + +struct jpeg_error_handler { + struct jpeg_error_mgr jpeg_error_mgr; + + struct jpeg_ctx *ctx; + jmp_buf setjmp_buffer; +}; + +struct jpeg_ctx { + FILE *file_obj; + struct jpeg_decompress_struct cinfo; + + struct jpeg_error_mgr err_manager; + + enum jpeg_status status; + + uint32_t width; + uint32_t height; + uint32_t row_stride; + enum jpeg_format format; + + struct jpeg_error_handler err_handler; +}; + +bool +jpeg_decoder_init_from_filename (struct jpeg_ctx *self, + const char *filename); + +void +jpeg_clear (struct jpeg_ctx *self); + +ssize_t +jpeg_read (struct jpeg_ctx *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows); diff --git a/gl-image-loader/main.c b/gl-image-loader/main.c new file mode 100644 index 0000000..4ef1589 --- /dev/null +++ b/gl-image-loader/main.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "image.h" + +#define IMAGE_FILENAME_DEFAULT "./igalia-white-text.png" + +static bool +gl_utils_print_shader_log (GLuint shader) +{ + GLint length; + char buffer[4096] = {0}; + GLint success; + + glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &length); + if (length == 0) + return true; + + glGetShaderInfoLog (shader, 4096, NULL, buffer); + if (strlen (buffer) > 0) + printf ("Shader compilation log: %s\n", buffer); + + glGetShaderiv (shader, GL_COMPILE_STATUS, &success); + + return success == GL_TRUE; +} + +static GLuint +gl_utils_load_shader (const char *shader_source, GLenum type) +{ + GLuint shader = glCreateShader (type); + + glShaderSource (shader, 1, &shader_source, NULL); + assert (glGetError () == GL_NO_ERROR); + glCompileShader (shader); + assert (glGetError () == GL_NO_ERROR); + + gl_utils_print_shader_log (shader); + + return shader; +} + +static GLuint +create_shader_program (void) +{ + const char *VERTEX_SOURCE = + "attribute vec2 pos;\n" + "attribute vec2 texture;\n" + "varying vec2 v_texture;\n" + "void main() {\n" + " v_texture = texture;\n" + " gl_Position = vec4(pos, 0, 1);\n" + "}\n"; + + const char *FRAGMENT_SOURCE = + "precision mediump float;\n" + "uniform sampler2D u_tex;\n" + "varying vec2 v_texture;\n" + "void main() {\n" + " gl_FragColor = texture2D(u_tex, v_texture);\n" + "}\n"; + + GLuint vertex_shader = gl_utils_load_shader (VERTEX_SOURCE, + GL_VERTEX_SHADER); + assert (vertex_shader >= 0); + assert (glGetError () == GL_NO_ERROR); + + GLuint fragment_shader = gl_utils_load_shader (FRAGMENT_SOURCE, + GL_FRAGMENT_SHADER); + assert (fragment_shader >= 0); + assert (glGetError () == GL_NO_ERROR); + + GLuint program = glCreateProgram (); + assert (glGetError () == GL_NO_ERROR); + glAttachShader (program, vertex_shader); + assert (glGetError () == GL_NO_ERROR); + glAttachShader (program, fragment_shader); + assert (glGetError () == GL_NO_ERROR); + + glBindAttribLocation (program, 0, "pos"); + glBindAttribLocation (program, 1, "texture"); + + glLinkProgram (program); + assert (glGetError () == GL_NO_ERROR); + + glDeleteShader (vertex_shader); + glDeleteShader (fragment_shader); + + return program; +} + +int32_t +main (int32_t argc, char *argv[]) +{ + printf ("Usage: %s \n", argv[0]); + + /* Load an decode an image. */ + static struct o_image image; + + const char *image_url; + if (argc > 1) + image_url = argv[1]; + else + image_url = IMAGE_FILENAME_DEFAULT; + + /* This loads the image header (metadata), but doesn't load any pixel + * data or do any decoding. + */ + if (! o_image_init_from_filename (&image, image_url)) + return -1; + + GLFWwindow* window; + + /* Initialize GLFW. */ + if (! glfwInit ()) + return -1; + + /* Select an OpenGL-ES 2.0 profile. */ + glfwWindowHint (GLFW_CLIENT_API, GLFW_OPENGL_ES_API); + glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 0); + + /* Create a windowed mode window and its OpenGL context */ + window = glfwCreateWindow (image.width, + image.height, + "GL Image Loader", + NULL, + NULL); + if (window == NULL) { + glfwTerminate (); + return -1; + } + + /* Make the window's context current */ + glfwMakeContextCurrent (window); + + /* Dump some GL capabilities. */ + const GLubyte *gles_version = glGetString (GL_VERSION); + printf ("%s\n", (char *) gles_version); + + /* Create a texture for the image. */ + GLuint tex; + glGenTextures (1, &tex); + assert (glGetError () == GL_NO_ERROR); + assert (tex > 0); + glBindTexture (GL_TEXTURE_2D, tex); + assert (glGetError () == GL_NO_ERROR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + /* Load the image into the texture, progressively in chunks of max + * BLOCK_SIZE bytes. */ +#define BLOCK_SIZE (8192 * 1) + uint8_t buf[BLOCK_SIZE] = {0, }; + size_t first_row; + size_t num_rows; + + GLuint format = image.format == O_IMAGE_FORMAT_RGB ? + GL_RGB : GL_RGBA; + + /* Allocate the texture size. */ + glTexImage2D (GL_TEXTURE_2D, + 0, + format, + image.width, image.height, + 0, + format, + GL_UNSIGNED_BYTE, + NULL); + assert (glGetError () == GL_NO_ERROR); + + ssize_t size_read; + do { + size_read = o_image_read (&image, + buf, + BLOCK_SIZE, + &first_row, + &num_rows); + assert (size_read >= 0); + if (size_read > 0) { + glTexSubImage2D (GL_TEXTURE_2D, + 0, + 0, first_row, + image.width, num_rows, + format, + GL_UNSIGNED_BYTE, + buf); + assert (glGetError () == GL_NO_ERROR); + } + } while (size_read > 0); + + glBindTexture (GL_TEXTURE_2D, 0); +#undef BLOCK_SIZE + + /* Create shader program to sample the texture. */ + GLuint program = create_shader_program (); + glUseProgram (program); + assert (glGetError () == GL_NO_ERROR); + + /* Loop until the user closes the window */ + while (! glfwWindowShouldClose (window)) { + /* Render here */ + glClearColor (0.25, 0.25, 0.25, 0.5); + glClear (GL_COLOR_BUFFER_BIT); + + /* Bind the texture. */ + glActiveTexture (GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, tex); + assert (glGetError () == GL_NO_ERROR); + + /* Enable blending for transparent PNGs. */ + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* Draw a quad. */ + static const GLfloat s_vertices[4][2] = { + { -1.0, 1.0 }, + { 1.0, 1.0 }, + { -1.0, -1.0 }, + { 1.0, -1.0 }, + }; + + static const GLfloat s_texturePos[4][2] = { + { 0, 0 }, + { 1, 0 }, + { 0, 1 }, + { 1, 1 }, + }; + + glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, s_vertices); + glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, s_texturePos); + + glEnableVertexAttribArray (0); + glEnableVertexAttribArray (1); + + glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray (0); + glDisableVertexAttribArray (1); + + /* Swap front and back buffers */ + glfwSwapBuffers (window); + + /* Poll and process events */ + glfwPollEvents (); + } + + glfwTerminate (); + + return 0; +} diff --git a/gl-image-loader/png.c b/gl-image-loader/png.c new file mode 100644 index 0000000..bd901f7 --- /dev/null +++ b/gl-image-loader/png.c @@ -0,0 +1,148 @@ +#include +#include +#include "png.h" +#include +#include + +bool +png_decoder_init_from_filename (struct png_ctx *self, + const char *filename) +{ + assert (self != NULL); + assert (filename != NULL); + + memset (self, 0x00, sizeof (struct png_ctx)); + + self->file_obj = fopen (filename, "rb"); + if (self->file_obj == NULL) + return false; + + /* Check PNG signature. */ + uint8_t header[8]; + ssize_t read_size = fread (header, 1, 8, self->file_obj); + assert (read_size > 0); + + if (png_sig_cmp ((png_const_bytep) header, 0, 8) != 0) { + png_clear (self); + errno = EINVAL; + return false; + } + + /* Create the PNG decoder object. */ + self->png_ptr = + png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (self->png_ptr == NULL) { + png_clear (self); + errno = ENOMEM; + return false; + } + + /* Create the PNG info object. */ + self->info_ptr = png_create_info_struct (self->png_ptr); + if (self->info_ptr == NULL) { + png_clear (self); + errno = ENOMEM; + return false; + } + + /* Initialize error handling. */ + if (setjmp (png_jmpbuf (self->png_ptr)) != 0) { + png_clear (self); + errno = ENOMEM; + return false; + } + + png_init_io (self->png_ptr, self->file_obj); + png_set_sig_bytes (self->png_ptr, 8); + + /* @FIXME: does this generates errors? */ + png_read_info (self->png_ptr, self->info_ptr); + + self->width = png_get_image_width (self->png_ptr, self->info_ptr); + self->height = png_get_image_height (self->png_ptr, self->info_ptr); + assert (self->width > 0 && self->height > 0); + + self->format = png_get_color_type (self->png_ptr, self->info_ptr); + self->row_stride = png_get_rowbytes (self->png_ptr, self->info_ptr); + + self->status = PNG_STATUS_DECODE_READY; + + return true; +} + +void +png_clear (struct png_ctx *self) +{ + assert (self != NULL); + + if (self->png_ptr != NULL) { + if (self->info_ptr != NULL) + png_destroy_info_struct (self->png_ptr, &self->info_ptr); + + png_destroy_read_struct (&self->png_ptr, &self->info_ptr, NULL); + } + + if (self->file_obj != NULL) { + fclose (self->file_obj); + self->file_obj = NULL; + } + + self->status = PNG_STATUS_NONE; +} + +ssize_t +png_read (struct png_ctx *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows) +{ + assert (self != NULL); + assert (self->status == PNG_STATUS_DECODE_READY || + self->status == PNG_STATUS_DONE); + assert (size == 0 || buffer != NULL); + assert (self->row_stride > 0 && size >= self->row_stride); + + size_t _num_rows = 0; + size_t _first_row = 0; + size_t result = 0; + + if (self->status == PNG_STATUS_DONE) + goto out; + + _first_row = self->last_decoded_row; + uint32_t max_read_rows = size / self->row_stride; + +#define MIN(a,b) (a > b ? b : a) + _num_rows = MIN (self->height - self->last_decoded_row, + max_read_rows); +#undef MIN + + png_bytepp rows = calloc (_num_rows, sizeof (png_bytep)); + for (int32_t i = 0; i < _num_rows; i++) + rows[i] = buffer + (i * self->row_stride); + + png_read_rows (self->png_ptr, + rows, + NULL, + _num_rows); + free (rows); + + self->last_decoded_row += _num_rows; + result = _num_rows * self->row_stride; + + if (self->last_decoded_row == self->height) { + png_read_end (self->png_ptr, self->info_ptr); + + self->status = PNG_STATUS_DONE; + } + + out: + if (first_row != NULL) + *first_row = _first_row; + + if (num_rows != NULL) + *num_rows = _num_rows; + + return result; +} diff --git a/gl-image-loader/png.h b/gl-image-loader/png.h new file mode 100644 index 0000000..3d46c60 --- /dev/null +++ b/gl-image-loader/png.h @@ -0,0 +1,45 @@ +#pragma once + +#define PNG_DEBUG 3 +#include +#include +#include +#include + +enum png_status { + PNG_STATUS_NONE = 0, + PNG_STATUS_DECODE_READY, + PNG_STATUS_ENCODE_READY, + PNG_STATUS_ERROR, + PNG_STATUS_DONE, +}; + +struct png_ctx { + FILE *file_obj; + + png_structp png_ptr; + png_infop info_ptr; + + enum png_status status; + + uint32_t width; + uint32_t height; + size_t row_stride; + uint8_t format; + + uint32_t last_decoded_row; +}; + +bool +png_decoder_init_from_filename (struct png_ctx *self, + const char *filename); + +void +png_clear (struct png_ctx *self); + +ssize_t +png_read (struct png_ctx *self, + void *buffer, + size_t size, + size_t *first_row, + size_t *num_rows);