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