]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/jpg/tif.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / jpg / tif.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 #include <event.h>
6 #include <keyboard.h>
7 #include "imagefile.h"
8
9 int cflag = 0;
10 int dflag = 0;
11 int eflag = 0;
12 int nineflag = 0;
13 int threeflag = 0;
14 int output = 0;
15 Image *image;
16 int defaultcolor = 1;
17
18 enum {
19         Border = 2,
20         Edge = 5
21 };
22
23 int init(void);
24 char *show(int, char *, int);
25
26 Rectangle
27 imager(Image *i)
28 {
29         Point p1, p2;
30
31         p1 = addpt(divpt(subpt(i->r.max, i->r.min), 2), i->r.min);
32         p2 = addpt(divpt(subpt(screen->clipr.max, screen->clipr.min), 2), screen->clipr.min);
33         return rectaddpt(i->r, subpt(p2, p1));
34 }
35
36 void
37 eresized(int new)
38 {
39         Rectangle r;
40
41         if(new && getwindow(display, Refnone) < 0)
42                 sysfatal("getwindow: %r");
43         if(image == nil)
44                 return;
45         r = imager(image);
46         border(screen, r, -Border, nil, ZP);
47         drawop(screen, r, image, nil, image->r.min, S);
48         flushimage(display, 1);
49 }
50
51 void
52 usage(void)
53 {
54         fprint(2, "usage: %s [-39cdektv] [file.tif ...]\n", argv0);
55         exits("usage");
56 }
57
58 void
59 main(int argc, char *argv[])
60 {
61         int fd, i;
62         char *err;
63         ulong outchan;
64
65         outchan = CMAP8;
66         ARGBEGIN {
67         /*
68         * produce encoded, compressed, bitmap file;
69         * no display by default
70         */
71         case 'c':
72                 cflag++;
73                 dflag++;
74                 output++;
75                 if(defaultcolor)
76                         outchan = CMAP8;
77                 break;
78         /* suppress display of image */
79         case 'd':
80                 dflag++;
81                 break;
82         /* disable floyd-steinberg error diffusion */
83         case 'e':
84                 eflag++;
85                 break;
86         /* force black and white */
87         case 'k':
88                 defaultcolor = 0;
89                 outchan = GREY8;
90                 break;
91         /*
92         * produce encoded, compressed, three-color
93         * bitmap file; no display by default
94         */
95         case '3':
96                 threeflag++;
97                 /* fall through */
98         /*
99         * produce encoded, compressed, true-color
100         * bitmap file; no display by default
101         */
102         case 't':
103                 cflag++;
104                 dflag++;
105                 output++;
106                 defaultcolor = 0;
107                 outchan = RGB24;
108                 break;
109         /* force RGBV */
110         case 'v':
111                 defaultcolor = 0;
112                 outchan = CMAP8;
113                 break;
114         /*
115         * produce plan 9, uncompressed, bitmap file;
116         * no display by default
117         */
118         case '9':
119                 nineflag++;
120                 dflag++;
121                 output++;
122                 if(defaultcolor)
123                         outchan = CMAP8;
124                 break;
125         default:
126                 usage();
127         } ARGEND
128
129         if(argc <= 0)
130                 exits(show(0, "<stdin>", outchan));
131         err = nil;
132         for(i = 0; i < argc; i++) {
133                 if((fd = open(argv[i], OREAD)) < 0) {
134                         fprint(2, "%s: open %s: %r\n",
135                                 argv0, argv[i]);
136                         err = "open";
137                 } else {
138                         err = show(fd, argv[i], outchan);
139                         close(fd);
140                 }
141                 if((nineflag || cflag) && argc > 1 && err == nil) {
142                         fprint(2, "%s: exiting after one file\n",
143                                 argv0);
144                         break;
145                 }
146         }
147         exits(err);
148 }
149
150 int
151 init(void)
152 {
153         static int inited = 0;
154
155         if(!inited) {
156                 if(initdraw(0, 0, 0) < 0) {
157                         fprint(2, "%s: initdraw: %r", argv0);
158                         return -1;
159                 }
160                 einit(Ekeyboard|Emouse);
161                 inited++;
162         }
163         return 0;
164 }
165
166 char *
167 show(int fd, char *name, int outchan)
168 {
169         Rawimage **array, *r, *c;
170         Image *i;
171         int j, ch;
172         Biobuf b;
173         char buf[32];
174
175         if(Binit(&b, fd, OREAD) < 0)
176                 return nil;
177         array = Breadtif(&b, CRGB24);
178         if(array == nil || array[0] == nil) {
179                 if(array != nil)
180                         free(array);
181                 fprint(2, "%s: decode %s failed: %r\n",
182                         argv0, name);
183                 return "decode";
184         }
185         Bterm(&b);
186         if(!dflag) {
187                 if(init() < 0)
188                         return "initdraw";
189                 if(defaultcolor && screen->depth > 8)
190                         outchan = RGB24;
191         }
192         r = array[0];
193         if(outchan != CMAP8) {
194                 switch(r->chandesc) {
195                 case CY:
196                         outchan = GREY8;
197                         break;
198                 case CRGB24:
199                         outchan = RGB24;
200                         break;
201                 }
202                 c = r;
203         } else if((c = torgbv(r, !eflag)) == nil) {
204                 fprint(2, "%s: conversion of %s failed: %r\n",
205                         argv0, name);
206                 return "torgbv";
207         }
208         if(!dflag) {
209                 i = allocimage(display, c->r, outchan, 0, 0);
210                 if(i == nil) {
211                         fprint(2, "%s: allocimage %s: %r\n",
212                                 argv0, name);
213                         return "allocimage";
214                 }
215                 if(loadimage(i, i->r, c->chans[0],
216                         c->chanlen) < 0) {
217                         fprint(2, "%s: loadimage %s: %r\n",
218                                 argv0, name);
219                         return "loadimage";
220                 }
221                 image = i;
222                 eresized(0);
223                 ch = ekbd();
224                 if(ch == 'q' || ch == Kdel || ch == Keof)
225                         exits(nil);
226                 draw(screen, screen->clipr, display->white,
227                         nil, ZP);
228                 image = nil;
229                 freeimage(i);
230         }
231         if(nineflag) {
232                 chantostr(buf, outchan);
233                 print("%11s %11d %11d %11d %11d ", buf,
234                         c->r.min.x, c->r.min.y,
235                         c->r.max.x, c->r.max.y);
236                 if(write(1, c->chans[0], c->chanlen) !=
237                         c->chanlen) {
238                         fprint(2, "%s: %s: write error: %r\n",
239                                 argv0, name);
240                         return "write";
241                 }
242         } else if(cflag && writerawimage(1, c) < 0) {
243                 fprint(2, "%s: %s: write error: %r\n",
244                         argv0, name);
245                 return "write";
246         }
247         if(c != nil && c != r) {
248                 free(c->chans[0]);
249                 free(c);
250         }
251         for(j = 0; j < r->nchans; j++)
252                 free(r->chans[j]);
253         free(r);
254         free(array);
255         return nil;
256 }