summaryrefslogtreecommitdiffstats
path: root/libdimension/png.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/png.c')
-rw-r--r--libdimension/png.c118
1 files changed, 56 insertions, 62 deletions
diff --git a/libdimension/png.c b/libdimension/png.c
index 8348e5f..24f8afa 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -30,7 +30,6 @@
#include <stdlib.h>
#include <stdint.h>
-/* Optimize canvas for PNG exporting */
int
dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
{
@@ -38,14 +37,14 @@ dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
return 0;
}
-/** Payload type for PNG write thread callback. */
+/// Payload type for PNG write thread callback.
typedef struct {
dmnsn_future *future;
const dmnsn_canvas *canvas;
FILE *file;
} dmnsn_png_write_payload;
-/** Payload type for PNG read thread callback. */
+/// Payload type for PNG read thread callback.
typedef struct {
dmnsn_future *future;
dmnsn_canvas **canvas;
@@ -53,13 +52,11 @@ typedef struct {
FILE *file;
} dmnsn_png_read_payload;
-/** PNG write thread callback. */
+/// PNG write thread callback.
static int dmnsn_png_write_canvas_thread(void *ptr);
-/** PNG read thread callback. */
+/// PNG read thread callback.
static int dmnsn_png_read_canvas_thread(void *ptr);
-/* Write a canvas to a png file, using libpng. Return 0 on success, nonzero on
- failure. */
int
dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file)
{
@@ -67,7 +64,6 @@ dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file)
return dmnsn_future_join(future);
}
-/* Write a canvas to a png file in the background */
dmnsn_future *
dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file)
{
@@ -78,13 +74,13 @@ dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file)
payload->canvas = canvas;
payload->file = file;
- /* Create the worker thread */
+ // Create the worker thread
dmnsn_new_thread(future, dmnsn_png_write_canvas_thread, payload);
return future;
}
-/* Read a canvas from the PNG file `file'. Return NULL on error. */
+// Read a canvas from the PNG file `file'. Return NULL on error.
dmnsn_canvas *
dmnsn_png_read_canvas(dmnsn_pool *pool, FILE *file)
{
@@ -94,7 +90,7 @@ dmnsn_png_read_canvas(dmnsn_pool *pool, FILE *file)
return canvas;
}
-/* Read a canvas from a png file in the background */
+// Read a canvas from a png file in the background
dmnsn_future *
dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, dmnsn_pool *pool, FILE *file)
{
@@ -107,17 +103,17 @@ dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, dmnsn_pool *pool, FILE *file)
payload->pool = pool;
payload->file = file;
- /* Create the worker thread */
+ // Create the worker thread
dmnsn_new_thread(future, dmnsn_png_read_canvas_thread, payload);
return future;
}
-/*
- * Thread callbacks
- */
+//////////////////////
+// Thread callbacks //
+//////////////////////
-/* Write a PNG file */
+// Write a PNG file
static int
dmnsn_png_write_canvas_thread(void *ptr)
{
@@ -131,74 +127,74 @@ dmnsn_png_write_canvas_thread(void *ptr)
png_structp png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
- /* Couldn't create libpng write struct */
+ // Couldn't create libpng write struct
dmnsn_free(payload);
return -1;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
- /* Couldn't create libpng info struct */
+ // Couldn't create libpng info struct
png_destroy_write_struct(&png_ptr, NULL);
dmnsn_free(payload);
return -1;
}
- /* libpng will longjmp here if it encounters an error from here on */
+ // libpng will longjmp here if it encounters an error from here on
uint16_t *row = NULL;
if (setjmp(png_jmpbuf(png_ptr))) {
- /* libpng error */
+ // libpng error
dmnsn_free(row);
png_destroy_write_struct(&png_ptr, &info_ptr);
dmnsn_free(payload);
return -1;
}
- /* Associate file with the libpng write struct */
+ // Associate file with the libpng write struct
png_init_io(png_ptr, payload->file);
- /* Set header correctly for 16-bit sRGB image */
+ // Set header correctly for 16-bit sRGB image
png_set_IHDR(png_ptr, info_ptr, width, height, 16,
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, PNG_sRGB_INTENT_ABSOLUTE);
- /* We think of transparency in the opposite way that PNG does */
+ // We think of transparency in the opposite way that PNG does
png_set_invert_alpha(png_ptr);
- /* Write the info struct */
+ // Write the info struct
png_write_info(png_ptr, info_ptr);
if (dmnsn_is_little_endian()) {
- /* We are little-endian; swap the byte order of the pixels */
+ // We are little-endian; swap the byte order of the pixels
png_set_swap(png_ptr);
}
- /* Check if we can optimize this */
+ // Check if we can optimize this
dmnsn_canvas_optimizer *optimizer =
dmnsn_canvas_find_optimizer(payload->canvas, dmnsn_rgba16_optimizer_fn);
if (optimizer) {
for (size_t y = 0; y < height; ++y) {
- /* Invert the rows. PNG coordinates are fourth quadrant. */
+ // Invert the rows. PNG coordinates are fourth quadrant.
uint16_t *row_opt = (uint16_t *)optimizer->ptr + 4*(height - y - 1)*width;
png_write_row(png_ptr, (png_bytep)row_opt);
dmnsn_future_increment(payload->future);
}
- /* Finish the PNG file */
+ // Finish the PNG file
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
dmnsn_free(payload);
return 0;
}
- /* Allocate the temporary row of RGBA values */
+ // Allocate the temporary row of RGBA values
row = dmnsn_malloc(4*sizeof(uint16_t)*width);
- /* Write the pixels */
+ // Write the pixels
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
- /* Invert the rows. PNG coordinates are fourth quadrant. */
+ // Invert the rows. PNG coordinates are fourth quadrant.
dmnsn_tcolor tcolor = dmnsn_canvas_get_pixel(payload->canvas,
x, height - y - 1);
tcolor = dmnsn_tcolor_remove_filter(tcolor);
@@ -211,12 +207,12 @@ dmnsn_png_write_canvas_thread(void *ptr)
row[4*x + 3] = lround(tcolor.T*UINT16_MAX);
}
- /* Write the row */
+ // Write the row
png_write_row(png_ptr, (png_bytep)row);
dmnsn_future_increment(payload->future);
}
- /* Finish the PNG file */
+ // Finish the PNG file
png_write_end(png_ptr, info_ptr);
dmnsn_free(row);
@@ -225,18 +221,18 @@ dmnsn_png_write_canvas_thread(void *ptr)
return 0;
}
-/** Thread-specific pointer to the appropriate dmnsn_future* for
- dmnsn_png_read_row_callback. */
+/// Thread-specific pointer to the appropriate dmnsn_future* for
+/// dmnsn_png_read_row_callback.
static __thread dmnsn_future *dmnsn_tl_png_read_future;
-/** Callback to increment the progress after a row has been read. */
+/// Callback to increment the progress after a row has been read.
static void
dmnsn_png_read_row_callback(png_structp png_ptr, png_uint_32 row, int pass)
{
dmnsn_future_increment(dmnsn_tl_png_read_future);
}
-/* Read a PNG file */
+// Read a PNG file
static int
dmnsn_png_read_canvas_thread(void *ptr)
{
@@ -249,13 +245,13 @@ dmnsn_png_read_canvas_thread(void *ptr)
return -1;
}
if (png_sig_cmp(header, 0, 8)) {
- /* payload->file is not a PNG file */
+ // payload->file is not a PNG file
dmnsn_free(payload);
errno = EINVAL;
return -1;
}
- /* Create the libpng read struct */
+ // Create the libpng read struct
png_structp png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
@@ -263,7 +259,7 @@ dmnsn_png_read_canvas_thread(void *ptr)
return -1;
}
- /* Create the libpng info struct */
+ // Create the libpng info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
@@ -271,11 +267,11 @@ dmnsn_png_read_canvas_thread(void *ptr)
return -1;
}
- /* libpng will longjmp here if it encounters an error from here on */
+ // libpng will longjmp here if it encounters an error from here on
png_bytep image = NULL;
png_bytep *row_pointers = NULL;
if (setjmp(png_jmpbuf(png_ptr))) {
- /* libpng error */
+ // libpng error
dmnsn_free(row_pointers);
dmnsn_free(image);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
@@ -283,15 +279,15 @@ dmnsn_png_read_canvas_thread(void *ptr)
return -1;
}
- /* Associate the read struct with the file, and tell it we've already checked
- 8 bytes of signature */
+ // Associate the read struct with the file, and tell it we've already checked
+ // 8 bytes of signature
png_init_io(png_ptr, payload->file);
png_set_sig_bytes(png_ptr, 8);
- /* Read the PNG header into info struct */
+ // Read the PNG header into info struct
png_read_info(png_ptr, info_ptr);
- /* Get useful information from the info struct */
+ // Get useful information from the info struct
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, compression_type, filter_method;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
@@ -301,12 +297,10 @@ dmnsn_png_read_canvas_thread(void *ptr)
dmnsn_future_set_total(payload->future, (number_of_passes + 1)*height);
png_set_read_status_fn(png_ptr, dmnsn_png_read_row_callback);
- /*
- * - Convert paletted images to RGB.
- * - Convert a tRNS chunk to an alpha channel
- * - Convert grayscale to RGB
- * - Invert the alpha channel
- */
+ // - Convert paletted images to RGB.
+ // - Convert a tRNS chunk to an alpha channel
+ // - Convert grayscale to RGB
+ // - Invert the alpha channel
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
@@ -320,32 +314,32 @@ dmnsn_png_read_canvas_thread(void *ptr)
}
png_set_invert_alpha(png_ptr);
- /* Update the info struct */
+ // Update the info struct
png_read_update_info(png_ptr, info_ptr);
- /* Get bytes/image row */
+ // Get bytes/image row
png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
- /* Allocate the temporary image buffer */
+ // Allocate the temporary image buffer
image = dmnsn_malloc(rowbytes*height);
- /* Allocate and set an array of pointers to rows in image */
+ // Allocate and set an array of pointers to rows in image
row_pointers = dmnsn_malloc(sizeof(png_bytep)*height);
for (size_t y = 0; y < height; ++y) {
row_pointers[y] = image + y*rowbytes;
}
- /* Read the image to memory all at once. At the expense of greater memory
- use, this handles interlacing for us. */
+ // Read the image to memory all at once. At the expense of greater memory
+ // use, this handles interlacing for us.
png_read_image(png_ptr, row_pointers);
- /* Allocate the canvas */
+ // Allocate the canvas
*payload->canvas = dmnsn_new_canvas(payload->pool, width, height);
- /* Now we convert the image to our canvas format. This depends on the image
- bit depth (which has been scaled up to at least 8 or 16), and the presence
- of an alpha channel. */
+ // Now we convert the image to our canvas format. This depends on the image
+ // bit depth (which has been scaled up to at least 8 or 16), and the presence
+ // of an alpha channel.
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
dmnsn_tcolor tcolor;