]> mj.ucw.cz Git - libucw.git/blob - images/image-tool.c
Merge with git+ssh://cvs.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / images / image-tool.c
1 /*
2  *      Simple image manupulation utility
3  *
4  *      (c) 2006 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/getopt.h"
12 #include "lib/fastbuf.h"
13 #include "images/images.h"
14 #include <stdlib.h>
15 #include <fcntl.h>
16
17 static void NONRET
18 usage(void)
19 {
20   fputs("\
21 Usage: image-tool [options] infile [outfile]\n\
22 \n\
23 -q --quiet          no progress messages\n\
24 -f --input-format   input image format (jpeg, gif, png)\n\
25 -F --output-format  output image format\n\
26 -s --size           force output dimensions (100x200)\n\
27 -b --fit-box        scale to fit the box (100x200)\n\
28 -c --colorspace     force output colorspace (gray, grayalpha, rgb, rgbalpha)\n\
29 ", stderr);
30   exit(1);
31 }
32
33 static char *shortopts = "qf:F:s:b:c:" CF_SHORT_OPTS;
34 static struct option longopts[] =
35 {
36   CF_LONG_OPTS
37   { "quiet",            0, 0, 'q' },
38   { "input-format",     0, 0, 'f' },
39   { "output-format",    0, 0, 'F' },
40   { "size",             0, 0, 's' },
41   { "fit-box",          0, 0, 'b' },
42   { "colorspace",       0, 0, 'c' },
43   { NULL,               0, 0, 0 }
44 };
45                                                           
46 static uns verbose = 1;
47 static byte *input_file_name;
48 static enum image_format input_format;
49 static byte *output_file_name;
50 static enum image_format output_format;
51 static uns cols;
52 static uns rows;
53 static uns fit_box;
54 static uns channels_format;
55
56 #define MSG(x...) do{ if (verbose) log(L_INFO, ##x); }while(0)
57
58 int
59 main(int argc, char **argv)
60 {
61   log_init(argv[0]);
62   int opt;
63   while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0)
64     switch (opt)
65       {
66         case 'q':
67           verbose = 0;
68           break;
69         case 'f':
70           if (!(input_format = image_extension_to_format(optarg)))
71             usage();
72           break;
73         case 'F':
74           if (!(output_format = image_extension_to_format(optarg)))
75             usage();
76           break;
77         case 's':
78           {
79             byte *r = strchr(optarg, 'x');
80             if (!r)
81               usage();
82             *r++ = 0;
83             if (!(cols = atoi(optarg)) || !(rows = atoi(r)))
84               usage();
85             fit_box = 0;
86             break;
87           }
88         case 'b':
89           {
90             byte *r = strchr(optarg, 'x');
91             if (!r)
92               usage();
93             *r++ = 0;
94             if (!(cols = atoi(optarg)) || !(rows = atoi(r)))
95               usage();
96             fit_box = 1;
97             break;
98           }
99         case 'c':
100           if (!(channels_format = image_name_to_channels_format(optarg)))
101             usage();
102           break;
103         default:
104           usage();
105       }
106
107   if (argc != optind + 1 && argc != optind + 2)
108     usage();
109   input_file_name = argv[optind++];
110   if (argc > optind)
111     output_file_name = argv[optind];
112   
113 #define TRY(x) do{ if (!(x)) die("Error: %s", it.err_msg); }while(0)
114   MSG("Initializing image library");
115   struct image_thread it;
116   struct image_io io;
117   image_thread_init(&it);
118   image_io_init(&it, &io);
119
120   MSG("Reading %s", input_file_name);
121   io.fastbuf = bopen(input_file_name, O_RDONLY, 1 << 18);
122   io.format = input_format ? : image_file_name_to_format(input_file_name);
123   TRY(image_io_read_header(&io));
124   if (!output_file_name)
125     {
126       bclose(io.fastbuf);
127       printf("Format:      %s\n", image_format_to_extension(io.format) ? : (byte *)"?");
128       printf("Dimensions:  %dx%d\n", io.cols, io.rows);
129       printf("Colorspace:  %s\n", image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT));
130     }
131   else
132     {
133       MSG("%s %dx%d %s", image_format_to_extension(io.format) ? : (byte *)"?", io.cols, io.rows,
134           image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT));
135       if (cols)
136         if (fit_box)
137           {
138             image_dimensions_fit_to_box(&io.cols, &io.rows, MIN(cols, 0xffff), MIN(rows, 0xffff), 0);
139           }
140         else
141           {
142             io.cols = cols;
143             io.rows = rows;
144           }
145       if (channels_format)
146         io.flags = io.flags & ~IMAGE_PIXEL_FORMAT | channels_format;
147       TRY(image_io_read_data(&io, 0));
148       bclose(io.fastbuf);
149       MSG("Writing %s", output_file_name);
150       io.fastbuf = bopen(output_file_name, O_WRONLY | O_CREAT | O_TRUNC, 1 << 18);
151       io.format = output_format ? : image_file_name_to_format(output_file_name);
152       MSG("%s %dx%d %s", image_format_to_extension(io.format) ? : (byte *)"?", io.cols, io.rows,
153           image_channels_format_to_name(io.flags & IMAGE_CHANNELS_FORMAT));
154       TRY(image_io_write(&io));
155       bclose(io.fastbuf);
156     }
157   
158   image_io_cleanup(&io);
159   image_thread_cleanup(&it);
160   MSG("Done.");
161   return 0;
162 }