yuv.c (4323B)
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 Rawimage** readyuv(int fd, int colorspace); 26 27 void 28 eresized(int new) 29 { 30 Rectangle r; 31 32 if(new && getwindow(display, Refnone) < 0){ 33 fprint(2, "yuv: can't reattach to window\n"); 34 exits("resize"); 35 } 36 if(image == nil) 37 return; 38 r = insetrect(screen->clipr, Edge+Border); 39 r.max.x = r.min.x+Dx(image->r); 40 r.max.y = r.min.y+Dy(image->r); 41 border(screen, r, -Border, nil, ZP); 42 draw(screen, r, image, nil, image->r.min); 43 flushimage(display, 1); 44 } 45 46 void 47 usage(void) 48 { 49 fprint(2, "usage: yuv -39cdektv -W winsize [file.yuv ...]\n"); 50 exits("usage"); 51 } 52 53 void 54 main(int argc, char *argv[]) 55 { 56 int fd, i; 57 char *err; 58 59 ARGBEGIN{ 60 case 'W': 61 winsize = EARGF(usage()); 62 break; 63 case '3': /* produce encoded, compressed, three-color bitmap file; no display by default */ 64 threeflag++; 65 /* fall through */ 66 case 't': /* produce encoded, compressed, true-color bitmap file; no display by default */ 67 cflag++; 68 dflag++; 69 output++; 70 defaultcolor = 0; 71 outchan = RGB24; 72 break; 73 case 'c': /* produce encoded, compressed, bitmap file; no display by default */ 74 cflag++; 75 dflag++; 76 output++; 77 if(defaultcolor) 78 outchan = CMAP8; 79 break; 80 case 'd': /* suppress display of image */ 81 dflag++; 82 break; 83 case 'e': /* disable floyd-steinberg error diffusion */ 84 eflag++; 85 break; 86 case 'k': /* force black and white */ 87 defaultcolor = 0; 88 outchan = GREY8; 89 break; 90 case 'v': /* force RGBV */ 91 defaultcolor = 0; 92 outchan = CMAP8; 93 break; 94 case '9': /* produce plan 9, uncompressed, bitmap file; no display by default */ 95 nineflag++; 96 dflag++; 97 output++; 98 if(defaultcolor) 99 outchan = CMAP8; 100 break; 101 default: 102 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, "yuv: 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, "yuv: 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, "yuv: 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 = readyuv(fd, CYCbCr); 152 if(array == nil || array[0]==nil){ 153 fprint(2, "yuv: 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 else 169 c = totruecolor(r, CRGB24); 170 } 171 if(c == nil){ 172 fprint(2, "yuv: converting %s to local format failed: %r\n", name); 173 return "torgbv"; 174 } 175 if(!dflag){ 176 if(r->chandesc == CY) 177 i = allocimage(display, c->r, GREY8, 0, 0); 178 else 179 i = allocimage(display, c->r, outchan, 0, 0); 180 if(i == nil){ 181 fprint(2, "yuv: allocimage %s failed: %r\n", name); 182 return "allocimage"; 183 } 184 if(loadimage(i, i->r, c->chans[0], c->chanlen) < 0){ 185 fprint(2, "yuv: loadimage %s failed: %r\n", name); 186 return "loadimage"; 187 } 188 image = i; 189 eresized(0); 190 if((ch=ekbd())=='q' || ch==0x7F || ch==0x04) 191 exits(nil); 192 draw(screen, screen->clipr, display->white, nil, ZP); 193 image = nil; 194 freeimage(i); 195 } 196 if(nineflag){ 197 chantostr(buf, outchan); 198 print("%11s %11d %11d %11d %11d ", buf, 199 c->r.min.x, c->r.min.y, c->r.max.x, c->r.max.y); 200 if(write(1, c->chans[0], c->chanlen) != c->chanlen){ 201 fprint(2, "yuv: %s: write error %r\n", name); 202 return "write"; 203 } 204 }else if(cflag){ 205 if(writerawimage(1, c) < 0){ 206 fprint(2, "yuv: %s: write error: %r\n", name); 207 return "write"; 208 } 209 } 210 for(j=0; j<r->nchans; j++) 211 free(r->chans[j]); 212 free(r->cmap); 213 free(r); 214 free(array); 215 if(c){ 216 free(c->chans[0]); 217 free(c); 218 } 219 return nil; 220 }