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 }