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