Refactor tools and increase performance by ~70% - farbfeld - suckless image for… | |
git clone git://git.suckless.org/farbfeld | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit de61085a0413f2f7570a89df345eb875d1a0298c | |
parent 7b03f52a130a12355d87bc05f028db31963112cc | |
Author: FRIGN <[email protected]> | |
Date: Mon, 1 Feb 2016 13:36:55 +0100 | |
Refactor tools and increase performance by ~70% | |
Instead of calling fwrite on each channel, we write one big chunk | |
of a line. | |
This increases performance by around 70% compared to version 1 and | |
the farbfeld tools are now roughly fast as imagemagick's convert. | |
I also refactored the code, removed unnecessary variables and unified | |
the variable naming and error reporting a bit. | |
Inside jpg2ff, the loop didn't need 3 variables. | |
Diffstat: | |
M ff2png.c | 32 ++++++++++++++++-------------… | |
M jpg2ff.c | 80 ++++++++++++++++-------------… | |
M png2ff.c | 30 ++++++++++++------------------ | |
3 files changed, 69 insertions(+), 73 deletions(-) | |
--- | |
diff --git a/ff2png.c b/ff2png.c | |
@@ -9,7 +9,7 @@ | |
#include <png.h> | |
-#define HEADER "farbfeld########" | |
+#define HDR "farbfeld########" | |
static char *argv0; | |
@@ -25,9 +25,9 @@ main(int argc, char *argv[]) | |
{ | |
png_structp pngs; | |
png_infop pngi; | |
- size_t png_row_len, j; | |
+ size_t rowlen; | |
uint32_t width, height, i; | |
- uint16_t tmp16, *png_row; | |
+ uint16_t *row; | |
uint8_t hdr[16]; | |
argv0 = argv[0], argc--, argv++; | |
@@ -38,11 +38,10 @@ main(int argc, char *argv[]) | |
} | |
/* header */ | |
- if (fread(hdr, 1, strlen(HEADER), stdin) != strlen(HEADER)) { | |
- fprintf(stderr, "%s: incomplete header\n", argv0); | |
- return 1; | |
+ if (fread(hdr, 1, sizeof(HDR) - 1, stdin) != sizeof(HDR) - 1) { | |
+ goto readerr; | |
} | |
- if (memcmp("farbfeld", hdr, strlen("farbfeld"))) { | |
+ if (memcmp("farbfeld", hdr, sizeof("farbfeld") - 1)) { | |
fprintf(stderr, "%s: invalid magic value\n", argv0); | |
return 1; | |
} | |
@@ -65,23 +64,24 @@ main(int argc, char *argv[]) | |
png_write_info(pngs, pngi); | |
/* write rows */ | |
- png_row_len = strlen("RGBA") * width * sizeof(uint16_t); | |
- if (!(png_row = malloc(png_row_len))) { | |
+ rowlen = (sizeof("RGBA") - 1) * width; | |
+ if (!(row = malloc(rowlen * sizeof(uint16_t)))) { | |
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, sizeof(uint16_t), 1, stdin) != 1) { | |
- fprintf(stderr, "%s: unexpected EOF\n", argv0); | |
- return 1; | |
- } | |
- png_row[j] = tmp16; | |
+ if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) { | |
+ goto readerr; | |
} | |
- png_write_row(pngs, (uint8_t *)png_row); | |
+ png_write_row(pngs, (uint8_t *)row); | |
} | |
png_write_end(pngs, NULL); | |
png_destroy_write_struct(&pngs, NULL); | |
return 0; | |
+readerr: | |
+ fprintf(stderr, "%s: fread: ", argv0); | |
+ perror(NULL); | |
+ | |
+ return 1; | |
} | |
diff --git a/jpg2ff.c b/jpg2ff.c | |
@@ -12,22 +12,22 @@ | |
static char *argv0; | |
METHODDEF(void) | |
-jpeg_error(j_common_ptr cinfo) | |
+jpeg_error(j_common_ptr js) | |
{ | |
fprintf(stderr, "%s: libjpeg: ", argv0); | |
- (*cinfo->err->output_message)(cinfo); | |
+ (*js->err->output_message)(js); | |
exit(1); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
- struct jpeg_decompress_struct cinfo; | |
+ struct jpeg_decompress_struct js; | |
struct jpeg_error_mgr jerr; | |
- uint32_t width, height, val_be; | |
- uint16_t *ff_row; | |
- size_t jpeg_row_len, ff_row_len, i, dx, sx; | |
- JSAMPARRAY buffer; /* output row buffer */ | |
+ uint32_t width, height, tmp32; | |
+ uint16_t *row; | |
+ size_t rowlen, i; | |
+ JSAMPARRAY jpgrow; | |
argv0 = argv[0], argc--, argv++; | |
@@ -37,61 +37,63 @@ main(int argc, char *argv[]) | |
} | |
/* load jpg */ | |
- cinfo.err = jpeg_std_error(&jerr); | |
+ js.err = jpeg_std_error(&jerr); | |
jerr.error_exit = jpeg_error; | |
- jpeg_create_decompress(&cinfo); | |
+ jpeg_create_decompress(&js); | |
- jpeg_stdio_src(&cinfo, stdin); | |
+ jpeg_stdio_src(&js, stdin); | |
- jpeg_read_header(&cinfo, TRUE); | |
- width = cinfo.image_width; | |
- height = cinfo.image_height; | |
+ jpeg_read_header(&js, 1); | |
+ width = js.image_width; | |
+ height = js.image_height; | |
/* set output format */ | |
- cinfo.output_components = 3; /* color components per pixel */ | |
- cinfo.out_color_space = JCS_RGB; /* input color space */ | |
+ js.output_components = 3; /* color components per pixel */ | |
+ js.out_color_space = JCS_RGB; /* input color space */ | |
- jpeg_start_decompress(&cinfo); | |
- jpeg_row_len = width * cinfo.output_components; | |
+ jpeg_start_decompress(&js); | |
/* create output buffers */ | |
- buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, | |
- JPOOL_IMAGE, jpeg_row_len, 1); | |
- ff_row_len = strlen("RGBA") * width; | |
- if(!(ff_row = malloc(ff_row_len * sizeof(uint16_t)))) { | |
+ jpgrow = (*js.mem->alloc_sarray)((j_common_ptr)&js, | |
+ JPOOL_IMAGE, width * | |
+ js.output_components, 1); | |
+ rowlen = strlen("RGBA") * width; | |
+ if(!(row = malloc(rowlen * sizeof(uint16_t)))) { | |
fprintf(stderr, "%s: malloc: out of memory\n", argv0); | |
return 1; | |
} | |
/* write header */ | |
fprintf(stdout, "farbfeld"); | |
- val_be = htonl(width); | |
- if (fwrite(&val_be, sizeof(uint32_t), 1, stdout) != 1) | |
+ tmp32 = htonl(width); | |
+ if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) | |
goto writerr; | |
- val_be = htonl(height); | |
- if (fwrite(&val_be, sizeof(uint32_t), 1, stdout) != 1) | |
+ tmp32 = htonl(height); | |
+ if (fwrite(&tmp32, 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… | |
- * Here the array is only one element long, but you could ask … | |
- * more than one scanline at a time if that's more convenient.… | |
- jpeg_read_scanlines(&cinfo, buffer, 1); | |
- | |
- for (i = 0, dx = 0, sx = 0; i < width; i++, sx += 3, dx += 4) { | |
- ff_row[dx] = htons(buffer[0][sx] * 257); | |
- ff_row[dx+1] = htons(buffer[0][sx+1] * 257); | |
- ff_row[dx+2] = htons(buffer[0][sx+2] * 257); | |
- ff_row[dx+3] = htons(65535); | |
+ while (js.output_scanline < js.output_height) { | |
+ /* jpeg_read_scanlines expects an array of pointers to | |
+ * scanlines. | |
+ * Here the array is only one element long, but you could | |
+ * ask for more than one scanline at a time if that's more | |
+ * convenient. */ | |
+ jpeg_read_scanlines(&js, jpgrow, 1); | |
+ | |
+ for (i = 0; i < width; ++i) { | |
+ row[4*i + 0] = htons(jpgrow[0][3*i + 0] * 257); | |
+ row[4*i + 1] = htons(jpgrow[0][3*i + 1] * 257); | |
+ row[4*i + 2] = htons(jpgrow[0][3*i + 2] * 257); | |
+ row[4*i + 3] = htons(65535); | |
} | |
/* write data */ | |
- if (fwrite(ff_row, 2, ff_row_len, stdout) != ff_row_len) | |
+ if (fwrite(row, 2, rowlen, stdout) != rowlen) | |
goto writerr; | |
} | |
- jpeg_finish_decompress(&cinfo); | |
- jpeg_destroy_decompress(&cinfo); | |
+ jpeg_finish_decompress(&js); | |
+ jpeg_destroy_decompress(&js); | |
return 0; | |
writerr: | |
diff --git a/png2ff.c b/png2ff.c | |
@@ -23,9 +23,9 @@ main(int argc, char *argv[]) | |
{ | |
png_structp pngs; | |
png_infop pngi; | |
- uint32_t width, height, outrowlen, tmp32, r, i; | |
- uint16_t *outrow; | |
- uint8_t **png_row_p; | |
+ uint32_t width, height, rowlen, tmp32, r, i; | |
+ uint16_t *row; | |
+ uint8_t **pngrows; | |
argv0 = argv[0], argc--, argv++; | |
@@ -54,15 +54,13 @@ main(int argc, char *argv[]) | |
PNG_TRANSFORM_EXPAND, NULL); | |
width = png_get_image_width(pngs, pngi); | |
height = png_get_image_height(pngs, pngi); | |
- png_row_p = png_get_rows(pngs, pngi); | |
- | |
+ pngrows = png_get_rows(pngs, pngi); | |
/* allocate output row buffer */ | |
- outrowlen = width * strlen("RGBA"); | |
- if (!(outrow = malloc(outrowlen * sizeof(uint16_t)))) { | |
+ rowlen = width * strlen("RGBA"); | |
+ if (!(row = malloc(rowlen * sizeof(uint16_t)))) { | |
fprintf(stderr, "%s: malloc: out of memory\n", argv0); | |
return 1; | |
} | |
- | |
/* write header */ | |
fputs("farbfeld", stdout); | |
tmp32 = htonl(width); | |
@@ -71,27 +69,23 @@ main(int argc, char *argv[]) | |
tmp32 = htonl(height); | |
if (fwrite(&tmp32, sizeof(uint32_t), 1, stdout) != 1) | |
goto writerr; | |
- | |
/* write data */ | |
switch(png_get_bit_depth(pngs, pngi)) { | |
case 8: | |
for (r = 0; r < height; ++r) { | |
- for (i = 0; i < outrowlen; i++) { | |
- outrow[i] = htons(257 * png_row_p[r][i]); | |
+ for (i = 0; i < rowlen; i++) { | |
+ row[i] = htons(257 * pngrows[r][i]); | |
} | |
- if (fwrite(outrow, sizeof(uint16_t), outrowlen, | |
- stdout) != outrowlen) { | |
+ if (fwrite(row, sizeof(uint16_t), rowlen, | |
+ stdout) != rowlen) { | |
goto writerr; | |
} | |
} | |
break; | |
case 16: | |
for (r = 0; r < height; ++r) { | |
- for (i = 0; i < outrowlen; ++i) { | |
- outrow[i] = ((uint16_t *)png_row_p[r])[i]; | |
- } | |
- if (fwrite(outrow, sizeof(uint16_t), outrowlen, | |
- stdout) != outrowlen) { | |
+ if (fwrite(pngrows[r], sizeof(uint16_t), | |
+ rowlen, stdout) != rowlen) { | |
goto writerr; | |
} | |
} |