ff2jpg.c - farbfeld - suckless image format with conversion tools
(HTM) git clone git://git.suckless.org/farbfeld
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
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 }