📄 xmovie.c
字号:
from.addr = (char *)titleFont; XtConvertAndStore(axes,XtRString,&from,XtRFont,&to); if (to.addr) XtSetArg(args[nargs],XtNtitleFont, *((Font*)to.addr)); nargs++; } XtSetValues(axes,args,nargs); x1beg = x1min; getparfloat("x1beg",&x1beg); x1end = x1max; getparfloat("x1end",&x1end); x2beg = x2min; getparfloat("x2beg",&x2beg); x2end = x2max; getparfloat("x2end",&x2end); adjustAxesValues(n1,d1,f1,n2,d2,f2,&x1beg,&x1end,&x2beg,&x2end); XtcwpSetAxesValues(axes,x1beg,x1end,x2beg,x2end); /* frame sampling */ if (!getparfloat("fframe",&fframe)) fframe = 1.0; if (!getparfloat("dframe",&dframe)) dframe = 1.0; /* interpolation */ if (!getparint("interp",&interp)) interp = 1; /* initial display mode: cont or step */ if (!getparint("idm", &displayMode)) displayMode = DM_CONT; /* initialize client data */ cd.n1 = n1; cd.d1 = d1; cd.f1 = f1; cd.n2 = n2; cd.d2 = d2; cd.f2 = f2; cd.floats = z; cd.fmin = bclip; cd.fmax = wclip; cd.bmin = (unsigned char) (XtcwpGetFirstPixel(dpy)); cd.bmax = (unsigned char) (XtcwpGetLastPixel(dpy)); if(cd.bmax==0)cd.bmax=255; warn("bmin=%d bmax=%d",cd.bmin,cd.bmax); cd.x1bega = x1beg; cd.x1enda = x1end; cd.x2bega = x2beg; cd.x2enda = x2end; cd.abytes = NULL; cd.bbytes = NULL; cd.image = NULL; cd.exposed = 0; cd.noframes = 1; cd.axes = axes; cd.looping = looping; cd.frame = NULL; cd.format = format; cd.iframe = 0; cd.fframe = fframe; cd.dframe = dframe; cd.interp = interp; cd.forward = 1; cd.ac = ac; /* adjust axes title if formatted */ if (strchr(cd.format,'%') && !strstr(cd.format,"%%")) { sprintf(cd.title,cd.format,cd.fframe+cd.iframe*cd.dframe); XtVaSetValues(cd.axes,XtNtitle,cd.title,NULL); } /* add work procedure */ cd.wpid = XtAppAddWorkProc(ac,(XtWorkProc) readFrame,&cd); /* add callbacks to axes widget */ XtAddCallback(axes,XtNresizeCallback,(XtCallbackProc) resizeCB,&cd); XtAddCallback(axes,XtNexposeCallback,(XtCallbackProc) exposeCB,&cd); XtAddCallback(axes,XtNinputCallback,(XtCallbackProc) inputCB,&cd); /* add Button2 translation for reversing the movie */ XtOverrideTranslations(axes, XtParseTranslationTable("<Btn2Up>: input()")); /* add Button3 translation for pausing the movie */ XtOverrideTranslations(axes, XtParseTranslationTable("<Btn3Up>: input()")); /* set up keypress */ XtAddEventHandler(axes, KeyPress, FALSE, (XtEventHandler) key_pressed, &cd); /* realize everything */ XtRealizeWidget(toplevel); /* go */ XtAppMainLoop(ac); return EXIT_SUCCESS;}Boolean readFrame (ClientData *cd)/*****************************************************************************An XtWorkProc that reads a frame of floats when there is nothing else to do.If a new frame of floats exists (assumed true on the first call), (1) converts floats to abytes, according to the clip parameters and the initial window parameters. (2) sets bbytes and image to NULL, so that they will be remade next expose event. (3) forces an expose event by clearing one pixel (kludge!!!).Finally, if the current frame has been exposed, attempts to read a new frame of floats.*****************************************************************************/{ int n1=cd->n1,n2=cd->n2,nxa=cd->nxa,nya=cd->nya,looping=cd->looping; float d1=cd->d1,f1=cd->f1,d2=cd->d2,f2=cd->f2, x1bega=cd->x1bega,x1enda=cd->x1enda, x2bega=cd->x2bega,x2enda=cd->x2enda, fmin=cd->fmin,fmax=cd->fmax, *floats=cd->floats; unsigned char bmin=cd->bmin,bmax=cd->bmax, *abytes=cd->abytes; Frame *frame=cd->frame,*frame1; int nargs,style; Arg args[10]; static int newframe=1,nframe=0; /* if a new frame exists */ if (newframe) { /* count frames */ nframe++; /* DEBUG fprintf(stderr,"frame %d\n",nframe); */ /* determine axes style */ nargs = 0; XtSetArg(args[nargs],XtNstyle,&style); nargs++; XtGetValues(cd->axes,args,nargs); /* if not looping, free old bytes */ if (!looping && abytes!=NULL) free1(abytes); /* convert frame of floats to bytes */ abytes = makeABytes(style,x1bega,x1enda,x2bega,x2enda, fmin,fmax,bmin,bmax, n1,d1,f1,n2,d2,f2,floats, &nxa,&nya); /* if looping, save bytes in list */ if (looping) { frame1 = (Frame*)malloc(sizeof(Frame)); frame1->abytes = abytes; frame1->nxa = nxa; frame1->nya = nya; if (frame==NULL) { frame1->prev = frame1->next = frame1; } else { frame1->prev = frame; frame1->next = frame->next; frame->next->prev = frame1; frame->next = frame1; } frame = frame1; } /* free bbytes and destroy image */ if (cd->bbytes!=NULL) free1(cd->bbytes); if (cd->image!=NULL) XDestroyImage(cd->image); /* set client data */ if (cd->noframes) { cd->nxb = nxa; cd->nyb = nya; cd->ixb = 0; cd->iyb = 0; cd->noframes = 0; } cd->iframe = nframe-1; cd->nxa = nxa; cd->nya = nya; cd->abytes = abytes; cd->bbytes = NULL; cd->image = NULL; cd->frame = frame; cd->exposed = 0; /* Sleep to slow down frames */ if( cd->sleep ){ usleep( cd->sleep ); } /* clear one pixel to force expose event (kludge!!!) */ XClearArea(XtDisplay(cd->axes),XtWindow(cd->axes), 0,0,1,1,True); } /* if we've exposed previous frame, try to read another frame */ if (cd->exposed) { newframe = (fread(floats,sizeof(float),n1*n2,stdin)==n1*n2); /* if no more new frames can be read */ if (!newframe) { /* if not looping, quit calling ourself */ if (!looping) return True; /* free bbytes and destroy image */ if (cd->bbytes!=NULL) free1(cd->bbytes); if (cd->image!=NULL) XDestroyImage(cd->image); /* reverse direction at ends of movie */ if (looping==2) { if (((cd->forward) && (cd->iframe==nframe-1)) || ((!cd->forward) && (cd->iframe==0))) { cd->forward = !cd->forward; } } /* looping, so set abytes to next frame */ if (cd->forward) frame = frame->next; else frame = frame->prev; abytes = frame->abytes; nxa = frame->nxa; nya = frame->nya; /* set client data */ if (cd->forward) { ++cd->iframe; if (cd->iframe==nframe) cd->iframe = 0; } else { --cd->iframe; if (cd->iframe==-1) cd->iframe = nframe-1; } cd->nxa = nxa; cd->nya = nya; cd->abytes = abytes; cd->bbytes = NULL; cd->image = NULL; cd->frame = frame; cd->exposed = 0; if( cd->sleep ){ usleep( cd->sleep ); } /* clear one pixel to force expose event (kludge!!!) */ XClearArea(XtDisplay(cd->axes),XtWindow(cd->axes), 0,0,1,1,True); if( displayMode == DM_STEP ) return True; } /* else, do not read new frame until previous frame exposed */ } else { newframe = 0; } /* ensure that we will be called again */ /* return False; */ return ( displayMode == DM_STEP && cd->exposed );}void exposeCB (Widget w, ClientData *cd, XtcwpAxesCallbackStruct *ca)/*****************************************************************************Expose event callback - draws image inside axes box.If abytes is NULL, simple returns.If bbytes is NULL, makes bbytes from abytes.If image is NULL, makes image from bbytes before drawing.*****************************************************************************/{ int nxa=cd->nxa,nya=cd->nya,nxb=cd->nxb,nyb=cd->nyb, ixb=cd->ixb,iyb=cd->iyb; unsigned char *abytes=cd->abytes,*bbytes=cd->bbytes; XImage *image=cd->image; Position x=ca->x,y=ca->y; Dimension width=ca->width,height=ca->height; Display *dpy=XtDisplay(w); Window win=XtWindow(w); GC gc; /* if abytes do not exist, return */ if (abytes==NULL) return; /* if necessary, make bbytes */ if (bbytes==NULL) bbytes = makeBBytes(nxa,nya,abytes,nxb,nyb,ixb,iyb); /* if necessary, make image */ if (image==NULL) image = makeImage(dpy,width,height,nxb,nyb, cd->interp,bbytes); /* create GC */ gc = XCreateGC(dpy,win,0L,NULL); /* draw image */ XPutImage(dpy,win,gc,image,0,0,x,y,image->width,image->height); /* free GC */ XFreeGC(dpy,gc); /* update client data */ cd->bbytes = bbytes; cd->image = image; cd->exposed = 1; /* update axes */ if (strchr(cd->format,'%') && !strstr(cd->format,"%%")) { sprintf(cd->title,cd->format,cd->fframe+cd->iframe*cd->dframe); XtVaSetValues(cd->axes,XtNtitle,cd->title,NULL); }}void inputCB (Widget w, ClientData *cd, XtcwpAxesCallbackStruct *ca)/*****************************************************************************Input event callback - currently handles rubber zoom box and pause onbutton 3 only. Updates dimensions and start indices of bbytes, basedon user-dragged zoom box, and sets both bbytes and image to NULL, sothat expose callback will make new bbytes and image.*****************************************************************************/{ int nxa=cd->nxa,nya=cd->nya, nxb=cd->nxb,nyb=cd->nyb,ixb=cd->ixb,iyb=cd->iyb; unsigned char *bbytes=cd->bbytes; float x1bega=cd->x1bega,x1enda=cd->x1enda, x2bega=cd->x2bega,x2enda=cd->x2enda; int x=ca->x,y=ca->y,width=ca->width,height=ca->height; float x1beg=ca->x1beg,x1end=ca->x1end,x2beg=ca->x2beg,x2end=ca->x2end; int style=ca->style; XEvent *event=ca->event; int xb,yb,wb,hb; int nxbn,nybn,ixbn,iybn; float x1begn,x1endn,x2begn,x2endn; static int stopflag=0; /* check for button 2 */ if (event->type==ButtonRelease && event->xbutton.button==Button2) { cd->forward = !cd->forward; return; } /* check for button 3 */ if (event->type==ButtonRelease && event->xbutton.button==Button3) { stopflag = !stopflag; if (stopflag) { XtRemoveWorkProc(cd->wpid); } else { cd->wpid = XtAppAddWorkProc(cd->ac, (XtWorkProc) readFrame,cd); } return; } /* track pointer and get rubber box */ XtcwpRubberBox(XtDisplay(w),XtWindow(w),*event,&xb,&yb,&wb,&hb); /* if zoom box has tiny width or height */ if (wb<3 || hb<3) { /* restore number of samples inside box */ nxbn = nxa; nybn = nya; /* restore indices of first samples inside box */ ixbn = 0; iybn = 0; /* restore axes limits */ x1begn = x1bega; x1endn = x1enda; x2begn = x2bega; x2endn = x2enda; /* else if valid zoom box */ } else { /* clip zoom box to lie within axes rectangle */ if (xb<x) { wb -= x-xb; xb = x; } if (yb<y) { hb -= y-yb; yb = y; } if (xb+wb>x+width) wb = x-xb+width; if (yb+hb>y+height) hb = y-yb+height; /* determine number of samples inside box (at least 2 by 2) */ nxbn = 1+NINT((float)wb/width*(nxb-1)); if (nxbn<2) nxbn = 2; nybn = 1+NINT((float)hb/height*(nyb-1)); if (nybn<2) nybn = 2; /* determine indices of first samples inside box */ ixbn = ixb+NINT((float)(xb-x)/width*(nxb-1)); if (ixbn+nxbn>ixb+nxb) ixbn = ixb+nxb-nxbn; iybn = iyb+NINT((float)(yb-y)/height*(nyb-1)); if (iybn+nybn>iyb+nyb) iybn = iyb+nyb-nybn; /* determine axes limits */ if (style==XtcwpNORMAL) { x1begn = x1beg+(ixbn-ixb)*(x1end-x1beg)/(nxb-1); x1endn = x1beg+(ixbn+nxbn-ixb-1)*(x1end-x1beg)/(nxb-1); x2begn = x2end+(iybn+nybn-iyb-1)*(x2beg-x2end)/(nyb-1); x2endn = x2end+(iybn-iyb)*(x2beg-x2end)/(nyb-1); } else { x1endn = x1beg+(iybn+nybn-iyb-1)*(x1end-x1beg)/(nyb-1); x1begn = x1beg+(iybn-iyb)*(x1end-x1beg)/(nyb-1); x2begn = x2beg+(ixbn-ixb)*(x2end-x2beg)/(nxb-1); x2endn = x2beg+(ixbn+nxbn-ixb-1)*(x2end-x2beg)/(nxb-1); } } /* set axes limits */ XtcwpSetAxesValues(w,x1begn,x1endn,x2begn,x2endn); /* set client data */ cd->nxb = nxbn; cd->nyb = nybn; cd->ixb = ixbn; cd->iyb = iybn; /* if bytes inside box exist, destroy and set pointer to NULL */ if (bbytes!=NULL) free1(bbytes); cd->bbytes = NULL; /* if image exists, destroy and set pointer to NULL */ if (cd->image!=NULL) { XDestroyImage(cd->image); cd->image = NULL; } /* clear window and force an expose event */ XClearArea(XtDisplay(w),XtWindow(w),0,0,0,0,True);}void resizeCB (Widget w, ClientData *cd, XtcwpAxesCallbackStruct *ca)/*****************************************************************************Resize event callback - destroys image, so that expose callbackwill remake it.*****************************************************************************/{ /* if an image exists, destroy it and set pointer to NULL */ if (cd->image!=NULL) { XDestroyImage(cd->image); cd->image = NULL; } if (cd->image != NULL) /* dummy */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -