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