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