URI: 
       tjpg.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tjpg.c (7459B)
       ---
            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                jflag = 0;
           12 int                fflag = 0;
           13 int                Fflag = 0;
           14 int                nineflag = 0;
           15 int                threeflag = 0;
           16 int                colorspace = CYCbCr;        /* default for 8-bit displays: combine color rotation with dither */
           17 int                output = 0;
           18 ulong        outchan = CMAP8;
           19 Image        *image;
           20 int                defaultcolor = 1;
           21 
           22 enum{
           23         Border        = 2,
           24         Edge                = 5
           25 };
           26 
           27 char        *show(int, char*, int);
           28 
           29 void
           30 eresized(int new)
           31 {
           32         Rectangle r;
           33 
           34         if(new && getwindow(display, Refnone) < 0){
           35                 fprint(2, "jpg: can't reattach to window\n");
           36                 exits("resize");
           37         }
           38         if(image == nil)
           39                 return;
           40         r = rectaddpt(image->clipr, subpt(screen->r.min, image->clipr.min));
           41         if(!new && !winsize)
           42                 drawresizewindow(r);
           43         draw(screen, r, image, nil, image->r.min);
           44         flushimage(display, 1);
           45 }
           46 
           47 void
           48 usage(void)
           49 {
           50         fprint(2, "usage: jpg -39cdefFkJrtv -W winsize [file.jpg ...]\n");
           51         exits("usage");
           52 }
           53 
           54 void
           55 main(int argc, char *argv[])
           56 {
           57         int fd, i, yflag;
           58         char *err;
           59         char buf[12+1];
           60 
           61         yflag = 0;
           62         ARGBEGIN{
           63         case 'W':
           64                 winsize = EARGF(usage());
           65                 break;
           66         case 'c':                /* produce encoded, compressed, bitmap file; no display by default */
           67                 cflag++;
           68                 dflag++;
           69                 output++;
           70                 if(defaultcolor)
           71                         outchan = CMAP8;
           72                 break;
           73         case 'd':                /* suppress display of image */
           74                 dflag++;
           75                 break;
           76         case 'e':                /* disable floyd-steinberg error diffusion */
           77                 eflag++;
           78                 break;
           79         case 'F':
           80                 Fflag++;        /* make a movie */
           81                 fflag++;        /* merge two fields per image */
           82                 break;
           83         case 'f':
           84                 fflag++;        /* merge two fields per image */
           85                 break;
           86         case 'J':                /* decode jpeg only; no display or remap (for debugging, etc.) */
           87                 jflag++;
           88                 break;
           89         case 'k':                /* force black and white */
           90                 defaultcolor = 0;
           91                 outchan = GREY8;
           92                 break;
           93         case 'r':
           94                 colorspace = CRGB;
           95                 break;
           96         case '3':                /* produce encoded, compressed, three-color bitmap file; no display by default */
           97                 threeflag++;
           98                 /* fall through */
           99         case 't':                /* produce encoded, compressed, true-color bitmap file; no display by default */
          100                 cflag++;
          101                 dflag++;
          102                 output++;
          103                 defaultcolor = 0;
          104                 outchan = RGB24;
          105                 break;
          106         case 'v':                /* force RGBV */
          107                 defaultcolor = 0;
          108                 outchan = CMAP8;
          109                 break;
          110         case 'y':        /* leave it in CYCbCr; for debugging only */
          111                 yflag = 1;
          112                 colorspace = CYCbCr;
          113                 break;
          114         case '9':                /* produce plan 9, uncompressed, bitmap file; no display by default */
          115                 nineflag++;
          116                 dflag++;
          117                 output++;
          118                 if(defaultcolor)
          119                         outchan = CMAP8;
          120                 break;
          121         default:
          122                 usage();
          123         }ARGEND;
          124 
          125         if(yflag==0 && dflag==0 && colorspace==CYCbCr){        /* see if we should convert right to RGB */
          126                 fd = open("/dev/screen", OREAD);
          127                 if(fd > 0){
          128                         buf[12] = '\0';
          129                         if(read(fd, buf, 12)==12 && chantodepth(strtochan(buf))>8)
          130                                 colorspace = CRGB;
          131                         close(fd);
          132                 }
          133         }
          134 
          135         err = nil;
          136         if(argc == 0)
          137                 err = show(0, "<stdin>", outchan);
          138         else{
          139                 for(i=0; i<argc; i++){
          140                         fd = open(argv[i], OREAD);
          141                         if(fd < 0){
          142                                 fprint(2, "jpg: can't open %s: %r\n", argv[i]);
          143                                 err = "open";
          144                         }else{
          145                                 err = show(fd, argv[i], outchan);
          146                                 close(fd);
          147                         }
          148                         if((nineflag || cflag) && argc>1 && err==nil){
          149                                 fprint(2, "jpg: exiting after one file\n");
          150                                 break;
          151                         }
          152                 }
          153         }
          154         exits(err);
          155 }
          156 
          157 Rawimage**
          158 vidmerge(Rawimage **aa1, Rawimage **aa2)
          159 {
          160         Rawimage **aao, *ao, *a1, *a2;
          161         int i, c, row, col;
          162 
          163         aao = nil;
          164         for (i = 0; aa1[i]; i++) {
          165 
          166                 a1 = aa1[i];
          167                 a2 = aa2[i];
          168                 if (a2 == nil){
          169                         fprint(2, "jpg: vidmerge: unequal lengths\n");
          170                         return nil;
          171                 }
          172                 aao = realloc(aao, (i+2)*sizeof(Rawimage *));
          173                 if (aao == nil){
          174                         fprint(2, "jpg: vidmerge: realloc\n");
          175                         return nil;
          176                 }
          177                 aao[i+1] = nil;
          178                 ao = aao[i] = malloc(sizeof(Rawimage));
          179                 if (ao == nil){
          180                         fprint(2, "jpg: vidmerge: realloc\n");
          181                         return nil;
          182                 }
          183                 memcpy(ao, a1, sizeof(Rawimage));
          184                 if (!eqrect(a1->r , a2->r)){
          185                         fprint(2, "jpg: vidmerge: rects different in img %d\n", i);
          186                         return nil;
          187                 }
          188                 if (a1->cmaplen != a2->cmaplen){
          189                         fprint(2, "jpg: vidmerge: cmaplen different in img %d\n", i);
          190                         return nil;
          191                 }
          192                 if (a1->nchans != a2->nchans){
          193                         fprint(2, "jpg: vidmerge: nchans different in img %d\n", i);
          194                         return nil;
          195                 }
          196                 if (a1->fields != a2->fields){
          197                         fprint(2, "jpg: vidmerge: fields different in img %d\n", i);
          198                         return nil;
          199                 }
          200                 ao->r.max.y += Dy(ao->r);
          201                 ao->chanlen += ao->chanlen;
          202                 if (ao->chanlen != Dx(ao->r)*Dy(ao->r)){
          203                         fprint(2, "jpg: vidmerge: chanlen wrong %d != %d*%d\n",
          204                                 ao->chanlen, Dx(ao->r), Dy(ao->r));
          205                         return nil;
          206                 }
          207                 row = Dx(a1->r);
          208                 for (c = 0; c < ao->nchans; c++) {
          209                         uchar *po, *p1, *p2;
          210 
          211                         ao->chans[c] = malloc(ao->chanlen);
          212                         po = ao->chans[c];
          213                         p1 = a1->chans[c];
          214                         p2 = a2->chans[c];
          215                         for (col = 0; col < Dy(a1->r); col++) {
          216                                 memcpy(po, p1, row);
          217                                 po += row, p1 += row;
          218                                 memcpy(po, p2, row);
          219                                 po += row, p2 += row;
          220                         }
          221                         free(a1->chans[c]);
          222                         free(a2->chans[c]);
          223                 }
          224                 if(a2->cmap != nil)
          225                         free(a2->cmap);
          226                 free(a1);
          227                 free(a2);
          228         }
          229         if (aa2[i] != nil)
          230                 fprint(2, "jpg: vidmerge: unequal lengths\n");
          231         free(aa1);
          232         free(aa2);
          233         return aao;
          234 }
          235 
          236 char*
          237 show(int fd, char *name, int outc)
          238 {
          239         Rawimage **array, *r, *c;
          240         static int inited;
          241         Image *i;
          242         int j, ch, outchan;
          243         Biobuf b;
          244         char buf[32];
          245 
          246         if(Binit(&b, fd, OREAD) < 0)
          247                 return nil;
          248         outchan = outc;
          249 rpt:        array = Breadjpg(&b, colorspace);
          250         if(array == nil || array[0]==nil){
          251                 fprint(2, "jpg: decode %s failed: %r\n", name);
          252                 return "decode";
          253         }
          254         if (fflag) {
          255                 Rawimage **a;
          256 
          257                 a = Breadjpg(&b, colorspace);
          258                 if(a == nil || a[0]==nil){
          259                         fprint(2, "jpg: decode %s-2 failed: %r\n", name);
          260                         return "decode";
          261                 }
          262                 array = vidmerge(a, array);
          263         } else
          264                 Bterm(&b);
          265 
          266         r = array[0];
          267         c = nil;
          268         if(jflag)
          269                 goto Return;
          270         if(!dflag){
          271                 if(!inited){
          272                         if(initdraw(0, 0, 0) < 0){
          273                                 fprint(2, "jpg: initdraw failed: %r\n");
          274                                 return "initdraw";
          275                         }
          276                         if(Fflag == 0)
          277                                 einit(Ekeyboard|Emouse);
          278                 inited++;
          279                 }
          280                 if(defaultcolor && screen->depth>8 && outchan==CMAP8)
          281                         outchan = RGB24;
          282         }
          283         if(outchan == CMAP8)
          284                 c = torgbv(r, !eflag);
          285         else{
          286                 if(outchan==GREY8 || (r->chandesc==CY && threeflag==0)){
          287                         c = totruecolor(r, CY);
          288                         outchan = GREY8;
          289                 }else
          290                         c = totruecolor(r, CRGB24);
          291         }
          292         if(c == nil){
          293                 fprint(2, "jpg: conversion of %s failed: %r\n", name);
          294                 return "torgbv";
          295         }
          296         if(!dflag){
          297                 if(c->chandesc == CY)
          298                         i = allocimage(display, c->r, GREY8, 0, 0);
          299                 else
          300                         i = allocimage(display, c->r, outchan, 0, 0);
          301                 if(i == nil){
          302                         fprint(2, "jpg: allocimage %s failed: %r\n", name);
          303                         return "allocimage";
          304                 }
          305                 if(loadimage(i, i->r, c->chans[0], c->chanlen) < 0){
          306                         fprint(2, "jpg: loadimage %s failed: %r\n", name);
          307                         return "loadimage";
          308                 }
          309                 image = i;
          310                 eresized(0);
          311                 if (Fflag) {
          312                         freeimage(i);
          313                         for(j=0; j<r->nchans; j++)
          314                                 free(r->chans[j]);
          315                         free(r->cmap);
          316                         free(r);
          317                         free(array);
          318                         goto rpt;
          319                 }
          320                 if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)
          321                         exits(nil);
          322                 draw(screen, screen->clipr, display->white, nil, ZP);
          323                 image = nil;
          324                 freeimage(i);
          325         }
          326         if(nineflag){
          327                 chantostr(buf, outchan);
          328                 print("%11s %11d %11d %11d %11d ", buf,
          329                         c->r.min.x, c->r.min.y, c->r.max.x, c->r.max.y);
          330                 if(write(1, c->chans[0], c->chanlen) != c->chanlen){
          331                         fprint(2, "jpg: %s: write error %r\n", name);
          332                         return "write";
          333                 }
          334         }else if(cflag){
          335                 if(writerawimage(1, c) < 0){
          336                         fprint(2, "jpg: %s: write error: %r\n", name);
          337                         return "write";
          338                 }
          339         }
          340     Return:
          341         for(j=0; j<r->nchans; j++)
          342                 free(r->chans[j]);
          343         free(r->cmap);
          344         free(r);
          345         free(array);
          346         if(c){
          347                 free(c->chans[0]);
          348                 free(c);
          349         }
          350         if (Fflag) goto rpt;
          351         return nil;
          352 }