Improve error-handling in the tools - farbfeld - suckless image format with con… | |
git clone git://git.suckless.org/farbfeld | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 295094bbbfecd64b4e6841e5e8093cc1748a2917 | |
parent d17e95f980060bd61439f8658bd0719c26595a2b | |
Author: FRIGN <[email protected]> | |
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: | |
M ff2png.c | 52 +++++++++++++----------------… | |
M jpg2ff.c | 53 +++++++++++------------------… | |
M png2ff.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 scanlin… | |
@@ -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; | |
} |