ff2jpg.c (2477B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <arpa/inet.h> 3 4 #include <errno.h> 5 #include <inttypes.h> 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include <jpeglib.h> 12 13 #include "arg.h" 14 #include "util.h" 15 16 static void 17 jpeg_error(j_common_ptr js) 18 { 19 fprintf(stderr, "%s: libjpeg: ", argv0); 20 (*js->err->output_message)(js); 21 exit(1); 22 } 23 24 static void 25 jpeg_setup_writer(struct jpeg_compress_struct *s, struct jpeg_error_mgr *e, 26 uint32_t w, uint32_t h, int quality, int opt) 27 { 28 jpeg_create_compress(s); 29 e->error_exit = jpeg_error; 30 s->err = jpeg_std_error(e); 31 32 jpeg_stdio_dest(s, stdout); 33 s->image_width = w; 34 s->image_height = h; 35 s->input_components = 3; /* color components per pixel */ 36 s->in_color_space = JCS_RGB; /* output color space */ 37 jpeg_set_defaults(s); 38 39 if (opt) { 40 s->optimize_coding = 1; 41 } 42 jpeg_set_quality(s, quality, 1); 43 44 jpeg_start_compress(s, 1); 45 } 46 47 static void 48 usage(void) 49 { 50 die("usage: %s [-b colour] [-o] [-q quality]", argv0); 51 } 52 53 int 54 main(int argc, char *argv[]) 55 { 56 struct jpeg_compress_struct jcomp; 57 struct jpeg_error_mgr jerr; 58 size_t rowlen; 59 uint64_t a; 60 uint32_t width, height, i, j, k, l; 61 uint16_t *row, mask[3] = { 0xffff, 0xffff, 0xffff }; 62 uint8_t *rowout; 63 int optimize = 0, quality = 85; 64 65 /* arguments */ 66 ARGBEGIN { 67 case 'b': 68 if (parse_mask(EARGF(usage()), mask)) { 69 usage(); 70 } 71 break; 72 case 'o': 73 optimize = 1; 74 break; 75 case 'q': 76 quality = estrtonum(EARGF(usage()), 0, 100); 77 break; 78 default: 79 usage(); 80 } ARGEND 81 82 if (argc) { 83 usage(); 84 } 85 86 /* prepare */ 87 ff_read_header(&width, &height); 88 jpeg_setup_writer(&jcomp, &jerr, width, height, quality, optimize); 89 row = ereallocarray(NULL, width, (sizeof("RGBA") - 1) * sizeof(uint16_t)); 90 rowlen = width * (sizeof("RGBA") - 1); 91 rowout = ereallocarray(NULL, width, (sizeof("RGB") - 1) * sizeof(uint8_t)); 92 93 /* write data */ 94 for (i = 0; i < height; ++i) { 95 efread(row, sizeof(uint16_t), rowlen, stdin); 96 for (j = 0, k = 0; j < rowlen; j += 4, k += 3) { 97 a = ntohs(row[j + 3]); 98 for (l = 0; l < 3; l++) { 99 /* alpha blending and 8-bit-reduction */ 100 rowout[k + l] = (a * ntohs(row[j + l]) + 101 (UINT16_MAX - a) * mask[l]) / 102 (UINT16_MAX * 103 (UINT16_MAX / UINT8_MAX)); 104 } 105 } 106 jpeg_write_scanlines(&jcomp, &rowout, 1); 107 } 108 109 /* clean up */ 110 jpeg_finish_compress(&jcomp); 111 jpeg_destroy_compress(&jcomp); 112 113 return fshut(stdout, "<stdout>"); 114 }