diff options
-rw-r--r-- | ff2jpg.c | 112 | ||||
-rw-r--r-- | jpg2ff.c | 94 |
2 files changed, 92 insertions, 114 deletions
@@ -13,7 +13,7 @@ #include "arg.h" #include "util.h" -METHODDEF(void) +static void jpeg_error(j_common_ptr js) { fprintf(stderr, "%s: libjpeg: ", argv0); @@ -22,6 +22,29 @@ jpeg_error(j_common_ptr js) } static void +jpeg_setup_writer(struct jpeg_compress_struct *s, struct jpeg_error_mgr *e, + uint32_t w, uint32_t h, int quality, int opt) +{ + jpeg_create_compress(s); + e->error_exit = jpeg_error; + s->err = jpeg_std_error(e); + + jpeg_stdio_dest(s, stdout); + s->image_width = w; + s->image_height = h; + s->input_components = 3; /* color components per pixel */ + s->in_color_space = JCS_RGB; /* output color space */ + jpeg_set_defaults(s); + + if (opt) { + s->optimize_coding = 1; + } + jpeg_set_quality(s, quality, 1); + + jpeg_start_compress(s, 1); +} + +static void usage(void) { fprintf(stderr, "usage: %s [-b #rrggbb] [-o] [-q quality]\n", argv0); @@ -31,44 +54,27 @@ usage(void) int main(int argc, char *argv[]) { - JSAMPROW row_pointer[1]; /* pointer to a single row */ - struct jpeg_compress_struct cinfo; + struct jpeg_compress_struct jcomp; struct jpeg_error_mgr jerr; size_t rowlen; uint64_t a; uint32_t width, height, i, j, k, l; uint16_t *row, mask[3] = { 0xffff, 0xffff, 0xffff }; uint8_t *rowout; - char *color, colfmt[] = "%#x%#x%#x"; - unsigned int collen, col[3], colfac, quality = 85, optimize = 0; + int optimize = 0, quality = 85; - argv0 = argv[0]; + /* arguments */ ARGBEGIN { case 'b': - color = EARGF(usage()); - if (color[0] == '#') { - color++; - } - collen = strlen(color); - if (collen != 3 && collen != 6 && collen != 12) { + if (parse_mask(EARGF(usage()), mask)) { usage(); } - colfmt[1] = colfmt[4] = colfmt[7] = ((collen / 3) + '0'); - if (sscanf(color, colfmt, col, col + 1, col + 2) != 3) { - usage(); - } - /* UINT16_MAX / 255 = 257; UINT16_MAX / 15 = 4369 */ - colfac = (collen == 3) ? 4369 : (collen == 6) ? 257 : 1; - for (i = 0; i < 3; i++) { - mask[i] = col[i] * colfac; - } break; case 'o': optimize = 1; break; case 'q': - if ((quality = atoi(EARGF(usage()))) > 100) - usage(); + quality = estrtonum(EARGF(usage()), 0, 100); break; default: usage(); @@ -78,43 +84,24 @@ main(int argc, char *argv[]) usage(); } - read_ff_header(&width, &height); - - if (width > SIZE_MAX / ((sizeof("RGBA") - 1) * sizeof(uint16_t))) { - fprintf(stderr, "%s: row length integer overflow\n", argv0); - return 1; - } + /* prepare */ + ff_read_header(&width, &height); + jpeg_setup_writer(&jcomp, &jerr, width, height, quality, optimize); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); rowlen = width * (sizeof("RGBA") - 1); - if (!(row = malloc(rowlen * sizeof(uint16_t)))) { - fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); - return 1; - } - if (!(rowout = malloc(width * (sizeof("RGB") - 1) * sizeof(uint8_t)))) { - fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno)); - return 1; - } - row_pointer[0] = rowout; - - jerr.error_exit = jpeg_error; - - jpeg_create_compress(&cinfo); - cinfo.err = jpeg_std_error(&jerr); - jpeg_stdio_dest(&cinfo, stdout); - cinfo.image_width = width; - cinfo.image_height = height; - cinfo.input_components = 3; /* color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* output color space */ - jpeg_set_defaults(&cinfo); - if (optimize) - cinfo.optimize_coding = TRUE; - jpeg_set_quality(&cinfo, quality, TRUE); - - jpeg_start_compress(&cinfo, TRUE); + rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); /* write rows */ for (i = 0; i < height; ++i) { if (fread(row, sizeof(uint16_t), rowlen, stdin) != rowlen) { - goto readerr; + if (ferror(stdin)) { + fprintf(stderr, "%s: fread: %s\n", argv0, + strerror(errno)); + } else { + fprintf(stderr, "%s: unexpected end of file\n", + argv0); + } + return 1; } for (j = 0, k = 0; j < rowlen; j += 4, k += 3) { a = ntohs(row[j + 3]); @@ -124,19 +111,12 @@ main(int argc, char *argv[]) (257 * 65535); } } - jpeg_write_scanlines(&cinfo, row_pointer, 1); + jpeg_write_scanlines(&jcomp, &rowout, 1); } - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); + /* clean up */ + jpeg_finish_compress(&jcomp); + jpeg_destroy_compress(&jcomp); return 0; -readerr: - if (ferror(stdin)) { - fprintf(stderr, "%s: fread: %s\n", argv0, strerror(errno)); - } else { - fprintf(stderr, "%s: unexpected end of file\n", argv0); - } - - return 1; } @@ -5,12 +5,13 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <jpeglib.h> #include "util.h" -METHODDEF(void) +static void jpeg_error(j_common_ptr js) { fprintf(stderr, "%s: libjpeg: ", argv0); @@ -18,6 +19,31 @@ jpeg_error(j_common_ptr js) exit(1); } +static void +jpeg_setup_reader(struct jpeg_decompress_struct *s, struct jpeg_error_mgr *e, + uint32_t *w, uint32_t *h) +{ + jpeg_create_decompress(s); + e->error_exit = jpeg_error; + s->err = jpeg_std_error(e); + + jpeg_stdio_src(s, stdin); + jpeg_read_header(s, 1); + *w = s->image_width; + *h = s->image_height; + s->output_components = 3; /* color components per pixel */ + s->out_color_space = JCS_RGB; /* input color space */ + + jpeg_start_decompress(s); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { @@ -25,72 +51,44 @@ main(int argc, char *argv[]) struct jpeg_error_mgr jerr; uint32_t width, height; uint16_t *row; + uint8_t *rowin; size_t rowlen, i; - JSAMPARRAY jpgrow; + /* arguments */ argv0 = argv[0], argc--, argv++; if (argc) { - fprintf(stderr, "usage: %s\n", argv0); - return 1; + usage(); } - /* load jpg */ - js.err = jpeg_std_error(&jerr); - jerr.error_exit = jpeg_error; - - jpeg_create_decompress(&js); - - jpeg_stdio_src(&js, stdin); - - jpeg_read_header(&js, 1); - width = js.image_width; - height = js.image_height; - - /* set output format */ - js.output_components = 3; /* color components per pixel */ - js.out_color_space = JCS_RGB; /* input color space */ - - jpeg_start_decompress(&js); - - /* create output buffers */ - jpgrow = (*js.mem->alloc_sarray)((j_common_ptr)&js, - JPOOL_IMAGE, width * - js.output_components, 1); + /* prepare */ + jpeg_setup_reader(&js, &jerr, &width, &height); + row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); rowlen = width * (sizeof("RGBA") - 1); - if(!(row = malloc(rowlen * sizeof(uint16_t)))) { - fprintf(stderr, "%s: malloc: out of memory\n", argv0); - return 1; - } + rowin = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); /* write data */ - write_ff_header(width, height); + ff_write_header(width, height); 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); + jpeg_read_scanlines(&js, &rowin, 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); + row[4 * i + 0] = htons(rowin[3 * i + 0] * 257); + row[4 * i + 1] = htons(rowin[3 * i + 1] * 257); + row[4 * i + 2] = htons(rowin[3 * i + 2] * 257); + row[4 * i + 3] = htons(65535); } - if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) - goto writerr; + if (fwrite(row, sizeof(uint16_t), rowlen, stdout) != rowlen) { + fprintf(stderr, "%s: fwrite: %s\n", argv0, strerror(errno)); + return 1; + } } + + /* clean up */ jpeg_finish_decompress(&js); jpeg_destroy_decompress(&js); return 0; -writerr: - fprintf(stderr, "%s: fwrite: ", argv0); - perror(NULL); - - return 1; } |