23 gettimeofday(&tv,NULL);
24 return tv.tv_sec + tv.tv_usec/1000000.0;
27 void loadImage(int x, int y, XImage *image, unsigned char *cp, int width, int height)
29 int i, j, k, b0, bi, npixel, nline;
30 unsigned long rmask, gmask, bmask;
31 double rshft, gshft, bshft;
32 unsigned char r, g, b, *bp, *dp, *data;
33 unsigned long pix, pixel;
35 npixel = image->bits_per_pixel / 8;
36 /* A, R, G, B or A, B, G, R */
37 if( image->byte_order != MSBFirst ) {
41 bi = -1; b0 = npixel-1;
44 rmask = image->red_mask; rshft = rmask/255.0;
45 gmask = image->green_mask; gshft = gmask/255.0;
46 bmask = image->blue_mask; bshft = bmask/255.0;
47 nline = image->bytes_per_line;
48 data = (unsigned char *)image->data + y*nline + x*npixel;
50 for( k=0; k<height; k++ ) {
52 for( j=0; j<width; ++j ) {
54 pixel = ((int)(r*rshft + 0.5) & rmask)
55 + ((int)(g*gshft + 0.5) & gmask)
56 + ((int)(b*bshft + 0.5) & bmask);
57 bp = dp + b0; pix = pixel;
58 for( i=npixel; --i>0; pix>>=8 ) {
72 clientMsg(Display *dpy,Window w,Atom amsg,int fmt)
74 XClientMessageEvent ev;
75 memset(&ev,0,sizeof(ev));
76 ev.type = ClientMessage;
78 ev.message_type = amsg;
80 XSendEvent(dpy,w,False,0,(XEvent *)&ev);
84 scale0(uint8_t *idata,int iw,int ih,uint8_t *odata,int ow,int oh)
91 for( dx=0; dx<ow; ++dx )
92 idx[dx] = ((int)((dx*iw1)/ow1));
97 for( dy=0; dy<oh; ++dy ) {
98 uint8_t *row = &idata[rsz * ((int)((dy*ih1)/oh1))];
99 for( dx=0; dx<ow; ++dx ) {
100 uint8_t *bp = &row[idx[dx]];
101 for( i=1; --i>=0; *odata++ = bp[i]);
108 scale1(uint8_t *idata,int iw,int ih,int rx,int ry,int rw,int rh,
109 uint8_t *odata,int ow,int oh,int sx,int sy,int sw,int sh)
111 //if( rw < 3 || rh < 3 || sw < 3 || sh < 3 ) return;
112 int i, dx, dy; int ibpp = 1, obpp = 1;
113 int rsz = ibpp * iw, ssz = obpp * ow;
114 double iw2 = rw-2, ih2 = rh-2;
115 double ow1 = iw2/(sw-1), oh1 = ih2/(sh-1);
116 odata += sy*ssz + 4*sx;
118 for( dy=0; dy<sh; ++dy,odata+=ssz ) {
123 int idy = rsz * (iy + ry);
124 uint8_t *row0 = &idata[idy];
125 uint8_t *row1 = &idata[idy+rsz];
128 for( dx=0; dx<sw; ++dx ) {
131 double xf1 = fx - ix;
132 double xf0 = 1.0 - xf1;
133 int idx = ibpp * (ix + rx);
134 uint8_t *cp00 = &row0[idx];
135 uint8_t *cp01 = &row0[idx+ibpp];
136 uint8_t *cp10 = &row1[idx];
137 uint8_t *cp11 = &row1[idx+ibpp];
138 double a00 = yf0 * xf0;
139 double a01 = yf0 * xf1;
140 double a10 = yf1 * xf0;
141 double a11 = yf1 * xf1;
142 for( bp[i=ibpp]=0; --i>=0; ++cp00, ++cp01, ++cp10, ++cp11 )
143 bp[i] = *cp00*a00 + *cp01*a01 + *cp10*a10 + *cp11*a11 + 0.5;
151 scale2(uint8_t *idata,int iw,int ih,int rx,int ry,int rw,int rh,
152 uint8_t *odata,int ow,int oh,int sx,int sy,int sw,int sh)
154 if( rw < 3 || rh < 3 || sw < 3 || sh < 3 ) return;
155 const int ibpp=1, obpp=1;
157 int rsz = ibpp*iw, ssz = obpp*ow;
158 double rw0=rw, rh0=rh;
159 double ow0=sw, oh0=sh;
160 double px = rw0/ow0, py = rh0/oh0;
161 double pz = (ow0*oh0)/(rw0*rh0);
163 odata += sy*ssz + obpp*sx;
165 for( dy=1; dy<=sh; ++dy,odata+=ssz ) {
167 double yf0 = ly - iy0;
168 double ny = dy*py + 1e-99;
170 double yf1 = ny - iy1;
174 for( dx=1; dx<=sw; ++dx ) {
176 double xf0 = lx - ix0;
177 double nx = dx*px + 1e-99;
179 double xf1 = nx - ix1;
181 for( y=iy0; y<=iy1; ++y ) {
182 int idy = rsz * (y + ry);
183 uint8_t *row = &idata[idy];
185 if( y == iy0 ) yw *= (y==iy1 ? yf1-yf0 : 1.0-yf0);
186 else if( y == iy1 ) yw *= yf1;
187 if( yw <= 0.0 ) continue;
188 for( x=ix0; x<=ix1; ++x ) {
190 if( x == ix0 ) xyw *= (x==ix1 ? xf1-xf0 : 1.0-xf0);
191 else if( x == ix1 ) xyw *= xf1;
192 if( xyw <= 0.0 ) continue;
193 int idx = ibpp*(x + rx);
194 uint8_t *cp = &row[idx];
207 void write_pbm(uint8_t *tp, int w, int h, const char *fmt, ...)
209 va_list ap; va_start(ap, fmt);
210 char fn[256]; vsnprintf(fn, sizeof(fn), fmt, ap);
212 FILE *fp = !strcmp(fn,"-") ? stdout : fopen(fn,"w");
214 fprintf(fp,"P5\n%d %d\n255\n",w,h);
222 int main(int ac,char **av)
234 int n, depth, depthfactor;
238 if( db.open(av[1]) ) {
239 fprintf(stderr,"cant open db: %s\n",av[1]);
242 int clip_id = atoi(av[2]);
243 if( db.clip_set.FindId(clip_id) ) {
244 printf("cant open clip %d\n",clip_id);
247 double framerate = db.clip_set.Framerate();
248 int ret = TimelineLoc::ikey_Sequences(db.timeline,clip_id,0).Locate();
249 if( ret || clip_id != (int)db.timeline.Clip_id() ) {
250 printf("cant access timeline of clip %d\n",clip_id);
253 int frame_no = 0, frame_id = -1;
256 display = XOpenDisplay(NULL);
257 if( display == NULL ) {
258 fprintf(stderr,"cant open display\n");
262 root = RootWindow(display,0);
263 screen = DefaultScreenOfDisplay(display);
264 depth = DefaultDepthOfScreen(screen);
265 visual = DefaultVisualOfScreen(screen);
268 switch( visual->c_class ) {
273 fprintf(stderr,"bad visual class %d\n",visual->c_class);
277 w = XCreateSimpleWindow(display, root, 0, 0, WIDTH, HEIGHT,
278 0, 0, WhitePixelOfScreen(screen));
280 pixels = (char *) malloc(HEIGHT*WIDTH*depthfactor);
281 image = XCreateImage( display, visual, depth, ZPixmap, 0,
282 pixels, WIDTH, HEIGHT, 8, WIDTH*depthfactor);
284 XSelectInput(display, w, ExposureMask|StructureNotifyMask|ButtonPressMask);
285 XMapWindow(display, w);
287 aMsg = XInternAtom(display,"dbtv",False);
288 gcv.function = GXcopy;
289 gcv.foreground = BlackPixelOfScreen(DefaultScreenOfDisplay(display));
291 gcv.line_style = LineSolid;
292 n = GCFunction|GCForeground|GCLineWidth|GCLineStyle;
293 gc = XCreateGC(display,w,n,&gcv);
294 double start_time = the_time();
297 XNextEvent(display,&xev);
298 /* printf("xev.type = %d/%08x\n",xev.type,xev.xany.window); */
301 if( xev.xbutton.window != w ) continue;
302 if( xev.xbutton.button != Button1 ) {
310 if( client_msg != 0 ) break;
311 client_msg = 1; /* fall through */
312 start_time = the_time();
315 frame_id = db.timeline.Frame_id();
316 if( db.video_frame.FindId(frame_id) ) {
317 printf("cant access frame %d (id %d) in clip %d\n",
318 frame_no, frame_id, clip_id); done = 1; break;
320 dat = db.video_frame._Frame_data();
321 //write_pbm(dat, SWIDTH,SHEIGHT, "%s/f%05d.pbm",av[2], fid);
322 uint8_t img[WIDTH*HEIGHT];
323 scale0(dat,SWIDTH,SHEIGHT, img,WIDTH,HEIGHT);
324 // scale1(dat, SWIDTH,SHEIGHT, 0,0,SWIDTH,SHEIGHT,
325 // img, WIDTH, HEIGHT, 0,0,WIDTH, HEIGHT);
326 loadImage(0,0, image, img, WIDTH, HEIGHT);
327 while( (int)(1000 * (frame_no/framerate - (the_time()-start_time))) > 0 ) {
331 XPutImage( display, w, gc, image, 0, 0, 0, 0, WIDTH, HEIGHT);
333 ret = TimelineLoc::rkey_Sequences(db.timeline).Next();
334 if( ret || clip_id != (int)db.timeline.Clip_id() ) { done = 1; break; }
335 clientMsg(display,w,aMsg,32);
344 XCloseDisplay(display);