farbfeld

suckless image format with conversion tools
git clone git://git.suckless.org/farbfeld
Log | Files | Refs | README | LICENSE

commit 5bb4be011b6d2857466a2730bb208cad6b839133
parent 1c801ebeaacd92d08b0225dd7e8c8e7963aa59d8
Author: FRIGN <dev@frign.de>
Date:   Mon,  4 Jan 2016 17:31:10 +0100

png2ff: Convert 16-Bit PNG's losslessly

It took me quite a while to figure out that libpng already gives you
big endian values.
I also tweaked the library functions a bit more to really make sure
that all PNG-types (grayscale, palette, ...) are converted to RGBA
properly.

Diffstat:
Mpng2ff.c | 36++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/png2ff.c b/png2ff.c @@ -32,10 +32,14 @@ main(int argc, char *argv[]) return 1; } png_init_io(png_struct_p, stdin); - png_set_add_alpha(png_struct_p, 255, PNG_FILLER_AFTER); + if (png_get_valid(png_struct_p, png_info_p, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_struct_p); + png_set_add_alpha(png_struct_p, 255*257, PNG_FILLER_AFTER); + png_set_expand_gray_1_2_4_to_8(png_struct_p); png_set_gray_to_rgb(png_struct_p); - png_read_png(png_struct_p, png_info_p, PNG_TRANSFORM_STRIP_16 | - PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); + png_set_packing(png_struct_p); + png_read_png(png_struct_p, png_info_p, PNG_TRANSFORM_PACKING | + PNG_TRANSFORM_EXPAND, NULL); png_get_IHDR(png_struct_p, png_info_p, &width, &height, &depth, &color, &interlace, NULL, NULL); png_row_len = png_get_rowbytes(png_struct_p, png_info_p); @@ -49,16 +53,28 @@ main(int argc, char *argv[]) fwrite(&tmp32, sizeof(uint32_t), 1, stdout); /* write data */ - /* TODO: allow 16 bit PNGs to be converted losslessly */ - for (r = 0; r < height; ++r) { - for (i = 0; i < png_row_len; i++) { - /* ((2^16-1) / 255) == 257 */ - tmp16 = htons(257 * png_row_p[r][i]); - fwrite(&tmp16, sizeof(uint16_t), 1, stdout); + if (depth == 8) { + for (r = 0; r < height; ++r) { + for (i = 0; i < png_row_len; i++) { + /* ((2^16-1) / 255) == 257 */ + tmp16 = htons(257 * png_row_p[r][i]); + fwrite(&tmp16, sizeof(uint16_t), 1, stdout); + } } + } else if (depth == 16) { + for (r = 0; r < height; ++r) { + for (i = 0; i < png_row_len / 2; i++) { + tmp16 = *((uint16_t *) + (png_row_p[r] + 2 * i)); + fwrite(&tmp16, sizeof(uint16_t), 1, stdout); + } + } + fprintf(stderr, "written r=%d, i=%d\n", r, i); + } else { + fprintf(stderr, "format error\n"); + return 1; } - /* cleanup */ png_destroy_read_struct(&png_struct_p, &png_info_p, NULL); return 0;