farbfeld

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

commit 295094bbbfecd64b4e6841e5e8093cc1748a2917
parent d17e95f980060bd61439f8658bd0719c26595a2b
Author: FRIGN <dev@frign.de>
Date:   Wed,  6 Jan 2016 15:15:06 +0100

Improve error-handling in the tools

We don't need the jumps, but rather pass a nice function pointer to
libpng. The jump in libjpg was also useless.
We check each fwrite-call so there's an early bailout in case the output
file is full.
Flushing at the end worked as well, but it took too long for complex
images. We don't want to "block" a pipe here and the approach in jpg2ff
was better.
The iHDR-read was useless. Rather use the get*-functions in libpng,
saves us 2 local variables as well.

Diffstat:
Mff2png.c | 52++++++++++++++++++++++------------------------------
Mjpg2ff.c | 53+++++++++++++++++++----------------------------------
Mpng2ff.c | 66++++++++++++++++++++++++++++++++++++------------------------------
3 files changed, 77 insertions(+), 94 deletions(-)

diff --git a/ff2png.c b/ff2png.c @@ -2,7 +2,6 @@ #include <arpa/inet.h> #include <errno.h> -#include <setjmp.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -12,6 +11,15 @@ #define HEADER "farbfeld########" +static char *argv0; + +void +pngerr(png_structp png_struct_p, png_const_charp msg) +{ + fprintf(stderr, "%s: libpng: %s\n", argv0, msg); + exit(1); +} + int main(int argc, char *argv[]) { @@ -19,38 +27,37 @@ main(int argc, char *argv[]) png_infop png_info_p; png_size_t png_row_len, j; png_uint_32 width, height, i; - int ret = 0; uint16_t tmp16, *png_row; uint8_t hdr[16]; - if (argc > 1) { - fprintf(stderr, "usage: %s\n", argv[0]); + argv0 = argv[0], argc--, argv++; + + if (argc) { + fprintf(stderr, "usage: %s\n", argv0); return 1; } /* header */ if (fread(hdr, 1, strlen(HEADER), stdin) != strlen(HEADER)) { - fprintf(stderr, "%s: incomplete header\n", argv[0]); + fprintf(stderr, "%s: incomplete header\n", argv0); return 1; } if (memcmp("farbfeld", hdr, strlen("farbfeld"))) { - fprintf(stderr, "%s: invalid magic value\n", argv[0]); + fprintf(stderr, "%s: invalid magic value\n", argv0); return 1; } width = ntohl(*((uint32_t *)(hdr + 8))); height = ntohl(*((uint32_t *)(hdr + 12))); /* load png */ - png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); + png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, + pngerr, NULL); png_info_p = png_create_info_struct(png_struct_p); if (!png_struct_p || !png_info_p) { - fprintf(stderr, "%s: failed to initialize libpng\n", argv[0]); + fprintf(stderr, "%s: failed to initialize libpng\n", argv0); return 1; } - if (setjmp(png_jmpbuf(png_struct_p))) - return 1; png_init_io(png_struct_p, stdout); png_set_IHDR(png_struct_p, png_info_p, width, height, 16, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, @@ -60,15 +67,13 @@ main(int argc, char *argv[]) /* write rows */ png_row_len = strlen("RGBA") * width * sizeof(uint16_t); if (!(png_row = malloc(png_row_len))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv[0]); + fprintf(stderr, "%s: malloc: out of memory\n", argv0); return 1; } for (i = 0; i < height; ++i) { for (j = 0; j < png_row_len / sizeof(uint16_t); ++j) { - if (fread(&tmp16, 1, sizeof(uint16_t), stdin) != - sizeof(uint16_t)) { - fprintf(stderr, "%s: unexpected EOF\n", - argv[0]); + if (fread(&tmp16, sizeof(uint16_t), 1, stdin) != 1) { + fprintf(stderr, "%s: unexpected EOF\n", argv0); return 1; } png_row[j] = tmp16; @@ -76,20 +81,7 @@ main(int argc, char *argv[]) png_write_row(png_struct_p, (uint8_t *)png_row); } png_write_end(png_struct_p, NULL); - png_destroy_write_struct(&png_struct_p, NULL); - /* flush output */ - if (fflush(stdout)) { - fprintf(stderr, "%s: fflush stdout: ", argv[0]); - perror(NULL); - ret = 1; - } - if (fclose(stdout) && !ret) { - fprintf(stderr, "%s: fclose stdout: ", argv[0]); - perror(NULL); - ret = 1; - } - - return ret; + return 0; } diff --git a/jpg2ff.c b/jpg2ff.c @@ -6,17 +6,17 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <setjmp.h> #include <jpeglib.h> -static jmp_buf error_jump; +static char *argv0; METHODDEF(void) jpeg_error(j_common_ptr cinfo) { + fprintf(stderr, "%s: libjpeg: ", argv0); (*cinfo->err->output_message)(cinfo); - longjmp(error_jump, 1); + exit(1); } int @@ -25,23 +25,20 @@ main(int argc, char *argv[]) struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; uint32_t width, height, val_be; - uint16_t *ff_row = NULL; + uint16_t *ff_row; size_t jpeg_row_len, ff_row_len, i, dx, sx; - int ret = 1; JSAMPARRAY buffer; /* output row buffer */ + argv0 = argv[0], argc--, argv++; + if (argc > 1) { - fprintf(stderr, "usage: %s\n", argv[0]); + fprintf(stderr, "usage: %s\n", argv0); return 1; } /* load jpg */ cinfo.err = jpeg_std_error(&jerr); - jerr.error_exit = jpeg_error; - if (setjmp(error_jump)) { - goto cleanup; - } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, stdin); @@ -62,16 +59,18 @@ main(int argc, char *argv[]) JPOOL_IMAGE, jpeg_row_len, 1); ff_row_len = strlen("RGBA") * sizeof(uint16_t) * width; if(!(ff_row = malloc(ff_row_len))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv[0]); + fprintf(stderr, "%s: malloc: out of memory\n", argv0); return 1; } /* write header */ fprintf(stdout, "farbfeld"); val_be = htonl(width); - fwrite(&val_be, sizeof(uint32_t), 1, stdout); + if (fwrite(&val_be, sizeof(uint32_t), 1, stdout) != 1) + goto writerr; val_be = htonl(height); - fwrite(&val_be, sizeof(uint32_t), 1, stdout); + if (fwrite(&val_be, sizeof(uint32_t), 1, stdout) != 1) + goto writerr; while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. @@ -87,29 +86,15 @@ main(int argc, char *argv[]) } /* write data */ - if (fwrite(ff_row, 1, ff_row_len, stdout) != ff_row_len) { - fprintf(stderr, "%s: fwrite: ", argv[0]); - perror(NULL); - goto cleanup; - } + if (fwrite(ff_row, 1, ff_row_len, stdout) != ff_row_len) + goto writerr; } jpeg_finish_decompress(&cinfo); - ret = 0; - - /* flush output */ - if (fflush(stdout)) { - fprintf(stderr, "%s: fflush stdout: ", argv[0]); - perror(NULL); - ret = 1; - } - if (fclose(stdout) && !ret) { - fprintf(stderr, "%s: fclose stdout: ", argv[0]); - perror(NULL); - ret = 1; - } -cleanup: - free(ff_row); jpeg_destroy_decompress(&cinfo); - return ret; + return 0; +writerr: + fprintf(stderr, "%s: fwrite: ", argv0); + perror(NULL); + return 1; } diff --git a/png2ff.c b/png2ff.c @@ -2,39 +2,46 @@ #include <arpa/inet.h> #include <errno.h> -#include <setjmp.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <png.h> +static char *argv0; + +void +pngerr(png_structp png_struct_p, png_const_charp msg) +{ + fprintf(stderr, "%s: libpng: %s\n", argv0, msg); + exit(1); +} + int main(int argc, char *argv[]) { png_structp png_struct_p; png_infop png_info_p; png_bytepp png_row_p; - int depth, color, ret = 0; uint32_t width, height, png_row_len, tmp32, r, i; uint16_t tmp16; - if (argc > 1) { - fprintf(stderr, "usage: %s\n", argv[0]); + argv0 = argv[0], argc--, argv++; + + if (argc) { + fprintf(stderr, "usage: %s\n", argv0); return 1; } /* load png */ png_struct_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL); + pngerr, NULL); png_info_p = png_create_info_struct(png_struct_p); if (!png_struct_p || !png_info_p) { - fprintf(stderr, "%s: failed to initialize libpng\n", argv[0]); + fprintf(stderr, "%s: failed to initialize libpng\n", argv0); return 1; } - if (setjmp(png_jmpbuf(png_struct_p))) - return 1; png_init_io(png_struct_p, stdin); if (png_get_valid(png_struct_p, png_info_p, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_struct_p); @@ -44,56 +51,55 @@ main(int argc, char *argv[]) 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, NULL, NULL, NULL); + width = png_get_image_width(png_struct_p, png_info_p); + height = png_get_image_height(png_struct_p, png_info_p); png_row_len = png_get_rowbytes(png_struct_p, png_info_p); png_row_p = png_get_rows(png_struct_p, png_info_p); /* write header */ fputs("farbfeld", stdout); tmp32 = htonl(width); - fwrite(&tmp32, sizeof(uint32_t), 1, stdout); + if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) + goto writerr; tmp32 = htonl(height); - fwrite(&tmp32, sizeof(uint32_t), 1, stdout); + if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) + goto writerr; /* write data */ - switch(depth) { + switch(png_get_bit_depth(png_struct_p, png_info_p)) { case 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); + if (fwrite(&tmp16, sizeof(uint16_t), 1, + stdout) != 1) + goto writerr; } } break; case 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); + tmp16 = *((uint16_t *)(png_row_p[r] + + 2 * i)); + if (fwrite(&tmp16, sizeof(uint16_t), 1, + stdout) != 1) + goto writerr; } } break; default: - fprintf(stderr, "%s: format error\n", argv[0]); + fprintf(stderr, "%s: invalid bit-depth\n", argv0); return 1; } png_destroy_read_struct(&png_struct_p, &png_info_p, NULL); - /* flush output */ - if (fflush(stdout)) { - fprintf(stderr, "%s: fflush stdout: ", argv[0]); - perror(NULL); - ret = 1; - } - if (fclose(stdout) && !ret) { - fprintf(stderr, "%s: fclose stdout: ", argv[0]); - perror(NULL); - ret = 1; - } + return 0; +writerr: + fprintf(stderr, "%s: fwrite: ", argv0); + perror(NULL); - return ret; + return 1; }