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