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