[Prev][Next][Index][Thread]

Xwindows Qcam movies



Here is my code for displaying the quickcam output in an Xwindow
to give Real Live Motion tm.
There are two parts- a single function QCRead4BitImage that
should be added to Scott's qcam.c file and then a second
file called xstuff.c.
Add -lX11 -lXext to link in x libraries.

To get it to work, modify Scott's program:
right before he first sends commands to camera add:
InitXWindows(qcwidth, qcheight);
InitPalette256();

then instead of qc_read() call, replace with
qc_reset();
...scott's code to send getimage command to QC
QCRead4BitImage(qcwidth, qcheight);
ShowPic();

slap a loop around those statements and voila: movies!

known issues:
It segfaults on exit.  64 palette mode doesn't quite work.
only supports 4 bit image.  I think the qc_reset in the loop
is killing frame rate, but it was only way I could get image to update.

Sorry for how piecemile this source and directions are.  I was supposed
to "libraryize" and clean it up last nite but a disk error trashed the
whole file so I spent all last nite just recoding what I'd lost.
I figured I'd at least get it out to people so they can tackle some
of the things I've missed.

I'll be working on it more this evening. (nothing quite like a job
to mess with one's "hackin' groove" :^( )

Paul Chinn

here's the code that should go in qcam.c
/* Read a scan from the QC */
extern char *sbuf;
extern char ColorTable[64];
int QCRead4BitImage(int w, int h)
{
        int i, hi, lo;
 
  for(i=0;i < w * h;i+=2) {
    write_lpcontrol(6);
    qc_waithand(1);
    hi=read_lpstatus()&0xf0;
    write_lpcontrol(0xe);
    qc_waithand(0);
    lo=(read_lpstatus()&0xf0);
 
        /*4 bit mode has 16 shades of grey.  we need to scale to
        our 256 palette.  Ordinarily we'd multiply the 4 bit value by
        16 - but since QC returns value in hi 4 bits, it's already
        effectively been mulitplied by 16- so we have to do nothing*/
 
/*use this code if using a 64 color palette*/
/*      sbuf[i] = ColorTable[63 - (hi >> 2) ];
        sbuf[i+1] = ColorTable[63 - (lo >> 2)];
*/
/*use this for 256 color*/
        sbuf[i] = 256 - hi;
        sbuf[i+1] = 256 - lo;
        }
        return (1);
}
 
/***************************************
XWindow Support for QuickCam
Paul Chinn
loomer@svpal.org
 
I took a bunch of this code from the source for VGB
"Virtual GameBoy" emulator by Marat Fayzullin and
Elan Feingold
*****************/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
 
 
 
/** MIT Shared Memory Extension for X ************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
XShmSegmentInfo SHMInfo;
 
void ExitXWindows();
 
/** Various X-related variables ******************************/
Screen *screen;
Display *disp;
Window root,win;
XColor col;
Colormap cmap;
XImage *ximage;
XEvent ev;
GC gc;
int screen_num;
unsigned long white,black;
 
/*my palette of greys*/
char ColorTable[64];
 
/*image buffer*/
char *sbuf;
 
/** Initialize xwindows, and prepare a shared memory buffer for
 the image */
 
int InitXWindows(int width, int height)
{
    XGCValues values;
    XSizeHints hints;
    XWMHints wmhints;
 
    disp=XOpenDisplay(NULL);
    if(!disp) {printf("open display failed\n"); return 0;}
 
    screen=DefaultScreenOfDisplay(disp);
    screen_num=DefaultScreen(disp);
    white=XWhitePixel(disp,screen_num);
    black=XBlackPixel(disp,screen_num);
 
    root=DefaultRootWindow(disp);
 
    win=XCreateSimpleWindow(disp,root,0,0,width,height,0,white,black);
    if(!win) {  printf("create window failed\n");return(0); }
 
    /*tell window manager about our window*/
    /*hints.flags=USSize;hints.width=width;hints.height=height;
    wmhints.input=True;wmhints.flags=InputHint;
    XSetWMHints(disp,win,&wmhints);
    XSetWMNormalHints(disp,win,&hints);
    */XStoreName(disp, win, "QuickCam");
        XSelectInput(disp, win, ExposureMask);
        XMapRaised(disp, win);
        XNextEvent(disp, &ev);
 
        gc = XCreateGC(disp, win, 0, &values);
 
        ximage = XShmCreateImage(
                disp, DefaultVisual(disp, screen_num), 8,
                ZPixmap, NULL, &SHMInfo, width, height);
        if(!ximage)
        {
                printf("CreateImage Failed\n");
                return(0);
        }
 
        SHMInfo.shmid=shmget(
                IPC_PRIVATE,ximage->bytes_per_line*ximage->height,
                IPC_CREAT|0777);
        if(SHMInfo.shmid < 0)
        {
                perror("shmget failed:");
                return (0);
        }
 
        sbuf = ximage->data = SHMInfo.shmaddr = shmat(SHMInfo.shmid, 0, 0);
        XShmAttach(disp, &SHMInfo);
        signal(SIGHUP, ExitXWindows); signal(SIGINT, ExitXWindows);
        signal(SIGQUIT, ExitXWindows); signal(SIGTERM, ExitXWindows);
        return(1);
}
 
void ExitXWindows()
{
        XShmDetach(disp, &SHMInfo);
        if(SHMInfo.shmaddr)
                shmdt(SHMInfo.shmaddr);
        if(SHMInfo.shmid > 0)
                shmctl(SHMInfo.shmid, IPC_RMID, 0);
}
int InitPalette64()
{
        int i;
 
        for(i=0; i<64; i++)
        {
                col.red =col.green = col.blue = i * 1024;
                printf("(%d) ",XAllocColor(disp, DefaultColormap(disp, screen_num), &col));
                ColorTable[i] = col.pixel;
                printf("%d ", col.pixel);
        }
}
 
int InitPalette256()
{
        int i;
 
        cmap = XCreateColormap(disp, win, DefaultVisual(disp, screen_num), AllocAll);
        printf("%d\n",cmap);
        for(i=0; i< 256; i++)
        {
                col.pixel = i;
                col.red = col.green = col.blue = i *256;
                col.flags=0xff;
                printf("%d %d\n", i, XStoreColor(disp, cmap, &col));
        }
        printf("%d \n",XSetWindowColormap(disp, win, cmap));
        return (1);
}
void ShowPic(int width, int height)
{
        XShmPutImage(disp, win, gc, ximage, 0,0,0,0,width, height, False);
        XFlush(disp);
}
 


Follow-Ups: