diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2003-08-11 04:26:00 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2003-08-11 04:26:00 +0000 |
commit | c5e843b82205c04c618a423d3bb223f1f630b7a1 (patch) | |
tree | 47eb18ea910be2d9735290aef960fd458b46d29c /modules/pdp_capture.c |
added sources from pidip-0.12.4svn2git-root
svn path=/trunk/externals/pidip/; revision=837
Diffstat (limited to 'modules/pdp_capture.c')
-rw-r--r-- | modules/pdp_capture.c | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/modules/pdp_capture.c b/modules/pdp_capture.c new file mode 100644 index 0000000..f7e9292 --- /dev/null +++ b/modules/pdp_capture.c @@ -0,0 +1,938 @@ +/* + * PiDiP module. + * Copyright (c) by Yves Degoyon (ydegoyon@free.fr) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* This object lets you capture a portion of the screen + * and turn it into pdp packets + * ( inspired by ImageMagick code ) + */ + +#include "pdp.h" +#include "yuv.h" +#include <math.h> +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <magick/api.h> +#include <magick/magick.h> +#include <magick/xwindow.h> + +#define PDP_DISPLAY_LENGTH 1024 + +static char *pdp_capture_version = "pdp_capture: version 0.1, capture of screen written by Yves Degoyon (ydegoyon@free.fr)"; + +typedef struct pdp_capture_struct +{ + t_object x_obj; + + t_outlet *x_outlet0; + t_int x_packet0; + short int *x_data; + t_pdp *x_header; + t_int x_displayopen; + + char *x_display; + t_int x_screen; + t_int x_x; + t_int x_y; + t_int x_vwidth; + t_int x_vheight; + t_int x_vsize; + + Image *x_Ximage; + Display *x_dpy; +} t_pdp_capture; + +/***********************************************/ +/* this code is borrowed from ImageMagick */ +/* but not exported, sorry, guys and girls, */ +/* i only need that */ +/***********************************************/ + +static Window XMyGetSubwindow(t_pdp_capture *o, Display *display, Window window, int x, int y) +{ + Window source_window, target_window; + int status, x_offset, y_offset; + + assert(display != (Display *) NULL); + source_window=XRootWindow(display, o->x_screen); + if (window == (Window) NULL) + { + return(source_window); + } + target_window=window; + for ( ; ; ) + { + status=XTranslateCoordinates(display,source_window,window,x,y, &x_offset,&y_offset,&target_window); + if (status != 1) + { + break; + } + if (target_window == (Window) NULL) + { + break; + } + source_window=window; + window=target_window; + x=x_offset; + y=y_offset; + } + if (target_window == (Window) NULL) + { + target_window=window; + } + return(target_window); +} + +static Window XMyClientWindow(t_pdp_capture *o, Display *display,Window target_window) +{ + Atom state, type; + int format, status; + unsigned char *data; + unsigned long after, number_items; + Window client_window; + + assert(display != (Display *) NULL); + state=XInternAtom(display,"WM_STATE",1); + if (state == (Atom) NULL) + { + return(target_window); + } + type=(Atom) NULL; + status=XGetWindowProperty(display,target_window,state,0L,0L,0, (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data); + if ((status == Success) && (type != (Atom) NULL)) + { + return(target_window); + } + client_window=XWindowByProperty(display,target_window,state); + if (client_window == (Window) NULL) + { + return(target_window); + } + return(client_window); +} + +static Image *XMyGetWindowImage(t_pdp_capture *o, Display *display,const Window window, const unsigned int level) +{ + typedef struct _ColormapInfo + { + Colormap colormap; + XColor *colors; + struct _ColormapInfo *next; + } ColormapInfo; + + typedef struct _WindowInfo + { + Window window, parent; + Visual *visual; + Colormap colormap; + XSegment bounds; + RectangleInfo crop_info; + } WindowInfo; + + IndexPacket index; + int display_height, display_width, id, status, x_offset, y_offset; + RectangleInfo crop_info; + register IndexPacket *indexes; + register int i; + static ColormapInfo *colormap_info = (ColormapInfo *) NULL; + static int max_windows = 0, number_windows = 0; + static WindowInfo *window_info; + Window child, root_window; + XWindowAttributes window_attributes; + + assert(display != (Display *) NULL); + status=XGetWindowAttributes(display,window,&window_attributes); + if ((status == 0) || (window_attributes.map_state != IsViewable)) + { + return((Image *) NULL); + } + root_window=XRootWindow(display, o->x_screen ); + (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset, &y_offset,&child); + crop_info.x=x_offset; + crop_info.y=y_offset; + crop_info.width=window_attributes.width; + crop_info.height=window_attributes.height; + if (crop_info.x < 0) + { + crop_info.width+=crop_info.x; + crop_info.x=0; + } + if (crop_info.y < 0) + { + crop_info.height+=crop_info.y; + crop_info.y=0; + } + display_width=XDisplayWidth(display, o->x_screen); + if ((int) (crop_info.x+crop_info.width) > display_width) + { + crop_info.width=display_width-crop_info.x; + } + display_height=XDisplayHeight(display, o->x_screen); + if ((int) (crop_info.y+crop_info.height) > display_height) + { + crop_info.height=display_height-crop_info.y; + } + if (number_windows >= max_windows) + { + max_windows+=1024; + if (window_info == (WindowInfo *) NULL) + { + window_info=(WindowInfo *) AcquireMemory(max_windows*sizeof(WindowInfo)); + } + else + { + ReacquireMemory((void **) &window_info,max_windows*sizeof(WindowInfo)); + } + } + if (window_info == (WindowInfo *) NULL) + { + post("pdp_capture : MemoryAllocationFailed : UnableToReadXImage"); + return((Image *) NULL); + } + id=number_windows++; + window_info[id].window=window; + window_info[id].visual=window_attributes.visual; + window_info[id].colormap=window_attributes.colormap; + window_info[id].bounds.x1=(short) crop_info.x; + window_info[id].bounds.y1=(short) crop_info.y; + window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1); + window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1); + crop_info.x-=x_offset; + crop_info.y-=y_offset; + + window_info[id].crop_info=crop_info; + if (level != 0) + { + unsigned int number_children; + Window *children; + + status=XQueryTree(display,window,&root_window,&window_info[id].parent, &children,&number_children); + for (i=0; i < id; i++) + { + if ((window_info[i].window == window_info[id].parent) && + (window_info[i].visual == window_info[id].visual) && + (window_info[i].colormap == window_info[id].colormap)) + { + if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) || + (window_info[id].bounds.x1 >= window_info[i].bounds.x2) || + (window_info[id].bounds.y1 <= window_info[i].bounds.y1) || + (window_info[id].bounds.y1 >= window_info[i].bounds.y2)) + { + number_windows--; + break; + } + } + } + if ((status == 1) && (number_children != 0)) + { + (void) XFree((void *) children); + } + } + if (level <= 1) + { + ColormapInfo *next; + Image *composite_image, *image; + int y; + register int j, x; + register PixelPacket *q; + register unsigned long pixel; + unsigned int import, number_colors; + XColor *colors; + XImage *ximage; + + image=(Image *) NULL; + for (id=0; id < number_windows; id++) + { + import=(window_info[id].bounds.x2 >= window_info[0].bounds.x1) && + (window_info[id].bounds.x1 <= window_info[0].bounds.x2) && + (window_info[id].bounds.y2 >= window_info[0].bounds.y1) && + (window_info[id].bounds.y1 <= window_info[0].bounds.y2); + for (j=0; j < id; j++) + { + if ((window_info[id].visual == window_info[j].visual) && + (window_info[id].colormap == window_info[j].colormap) && + (window_info[id].bounds.x1 >= window_info[j].bounds.x1) && + (window_info[id].bounds.y1 >= window_info[j].bounds.y1) && + (window_info[id].bounds.x2 <= window_info[j].bounds.x2) && + (window_info[id].bounds.y2 <= window_info[j].bounds.y2)) + { + import=0; + } + else + { + if ((window_info[id].visual != window_info[j].visual) || + (window_info[id].colormap != window_info[j].colormap)) + { + if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) && + (window_info[id].bounds.x1 < window_info[j].bounds.x2) && + (window_info[id].bounds.y2 > window_info[j].bounds.y1) && + (window_info[id].bounds.y1 < window_info[j].bounds.y2)) + { + import=1; + } + } + } + } + if (!import) + { + continue; + } + // post( "pdp_capture : get image : %ld [%d,%d,%d,%d]", window_info[id].window, + // (int) window_info[id].crop_info.x, + // (int) window_info[id].crop_info.y, + // (unsigned int) window_info[id].crop_info.width, + // (unsigned int) window_info[id].crop_info.height ); + ximage=XGetImage(display,window_info[id].window, + (int) window_info[id].crop_info.x,(int) window_info[id].crop_info.y, + (unsigned int) window_info[id].crop_info.width, + (unsigned int) window_info[id].crop_info.height,AllPlanes,ZPixmap); + if (ximage == (XImage *) NULL) + { + continue; + } + number_colors=0; + colors=(XColor *) NULL; + if (window_info[id].colormap != (Colormap) NULL) + { + ColormapInfo *p; + + number_colors=window_info[id].visual->map_entries; + for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next) + { + if (p->colormap == window_info[id].colormap) + { + break; + } + } + if (p == (ColormapInfo *) NULL) + { + colors=(XColor *) AcquireMemory(number_colors*sizeof(XColor)); + if (colors == (XColor *) NULL) + { + XDestroyImage(ximage); + return((Image *) NULL); + } + if ((window_info[id].visual->storage_class != DirectColor) && + (window_info[id].visual->storage_class != TrueColor)) + { + for (i=0; i < (int) number_colors; i++) + { + colors[i].pixel=i; + colors[i].pad=0; + } + } + else + { + unsigned long blue, blue_bit, green, green_bit, red, red_bit; + + red=0; + green=0; + blue=0; + red_bit=window_info[id].visual->red_mask & + (~(window_info[id].visual->red_mask)+1); + green_bit=window_info[id].visual->green_mask & + (~(window_info[id].visual->green_mask)+1); + blue_bit=window_info[id].visual->blue_mask & + (~(window_info[id].visual->blue_mask)+1); + for (i=0; i < (int) number_colors; i++) + { + colors[i].pixel=red | green | blue; + colors[i].pad=0; + red+=red_bit; + if (red > window_info[id].visual->red_mask) + red=0; + green+=green_bit; + if (green > window_info[id].visual->green_mask) + green=0; + blue+=blue_bit; + if (blue > window_info[id].visual->blue_mask) + blue=0; + } + } + (void) XQueryColors(display,window_info[id].colormap,colors, (int) number_colors); + p=(ColormapInfo *) AcquireMemory(sizeof(ColormapInfo)); + if (p == (ColormapInfo *) NULL) + return((Image *) NULL); + p->colormap=window_info[id].colormap; + p->colors=colors; + p->next=colormap_info; + colormap_info=p; + } + colors=p->colors; + } + composite_image=AllocateImage((ImageInfo *) NULL); + if (composite_image == (Image *) NULL) + { + XDestroyImage(ximage); + return((Image *) NULL); + } + if ((window_info[id].visual->storage_class != TrueColor) && + (window_info[id].visual->storage_class != DirectColor)) + { + composite_image->storage_class=PseudoClass; + } + composite_image->columns=ximage->width; + composite_image->rows=ximage->height; + switch (composite_image->storage_class) + { + case DirectClass: + default: + { + register unsigned long color, index; + unsigned long blue_mask, blue_shift, green_mask, green_shift, red_mask, red_shift; + + red_mask=window_info[id].visual->red_mask; + red_shift=0; + while ((red_mask & 0x01) == 0) + { + red_mask>>=1; + red_shift++; + } + green_mask=window_info[id].visual->green_mask; + green_shift=0; + while ((green_mask & 0x01) == 0) + { + green_mask>>=1; + green_shift++; + } + blue_mask=window_info[id].visual->blue_mask; + blue_shift=0; + while ((blue_mask & 0x01) == 0) + { + blue_mask>>=1; + blue_shift++; + } + if ((number_colors != 0) && + (window_info[id].visual->storage_class == DirectColor)) + { + for (y=0; y < (long) composite_image->rows; y++) + { + q=SetImagePixels(composite_image,0,y, + composite_image->columns,1); + if (q == (PixelPacket *) NULL) + break; + for (x=0; x < (long) composite_image->columns; x++) + { + pixel=XGetPixel(ximage,x,y); + index=(pixel >> red_shift) & red_mask; + q->red=ScaleShortToQuantum(colors[index].red); + index=(pixel >> green_shift) & green_mask; + q->green=ScaleShortToQuantum(colors[index].green); + index=(pixel >> blue_shift) & blue_mask; + q->blue=ScaleShortToQuantum(colors[index].blue); + q++; + } + if (!SyncImagePixels(composite_image)) + break; + } + } + else + { + for (y=0; y < (long) composite_image->rows; y++) + { + q=SetImagePixels(composite_image,0,y, + composite_image->columns,1); + if (q == (PixelPacket *) NULL) + break; + for (x=0; x < (long) composite_image->columns; x++) + { + pixel=XGetPixel(ximage,x,y); + color=(pixel >> red_shift) & red_mask; + q->red=ScaleShortToQuantum((65535L*color)/red_mask); + color=(pixel >> green_shift) & green_mask; + q->green=ScaleShortToQuantum((65535L*color)/green_mask); + color=(pixel >> blue_shift) & blue_mask; + q->blue=ScaleShortToQuantum((65535L*color)/blue_mask); + q++; + } + if (!SyncImagePixels(composite_image)) + { + break; + } + } + } + break; + } + case PseudoClass: + { + if (!AllocateImageColormap(composite_image,number_colors)) + { + XDestroyImage(ximage); + DestroyImage(composite_image); + return((Image *) NULL); + } + for (i=0; i < (int) composite_image->colors; i++) + { + composite_image->colormap[colors[i].pixel].red= + ScaleShortToQuantum(colors[i].red); + composite_image->colormap[colors[i].pixel].green= + ScaleShortToQuantum(colors[i].green); + composite_image->colormap[colors[i].pixel].blue= + ScaleShortToQuantum(colors[i].blue); + } + for (y=0; y < (long) composite_image->rows; y++) + { + q=SetImagePixels(composite_image,0,y,composite_image->columns,1); + if (q == (PixelPacket *) NULL) + break; + indexes=GetIndexes(composite_image); + for (x=0; x < (long) composite_image->columns; x++) + { + index=(IndexPacket) XGetPixel(ximage,x,y); + indexes[x]=index; + *q++=composite_image->colormap[index]; + } + if (!SyncImagePixels(composite_image)) + { + break; + } + } + break; + } + } + XDestroyImage(ximage); + if (image == (Image *) NULL) + { + image=composite_image; + continue; + } + (void) XTranslateCoordinates(display,window_info[id].window,window,0,0, &x_offset,&y_offset,&child); + x_offset-=(int) crop_info.x; + if (x_offset < 0) + { + x_offset=0; + } + y_offset-=(int) crop_info.y; + if (y_offset < 0) + { + y_offset=0; + } + (void) CompositeImage(image,CopyCompositeOp,composite_image, x_offset,y_offset); + } + while (colormap_info != (ColormapInfo *) NULL) + { + next=colormap_info->next; + LiberateMemory((void **) &colormap_info->colors); + LiberateMemory((void **) &colormap_info); + colormap_info=next; + } + /* + Free resources and restore initial state. + */ + LiberateMemory((void **) &window_info); + window_info=(WindowInfo *) NULL; + max_windows=0; + number_windows=0; + colormap_info=(ColormapInfo *) NULL; + return(image); + } + return((Image *) NULL); +} + +/*************************************************/ +/* this code is adapted from ImageMagick */ +/* mainly because i don't want user interactions */ +/* and i want to chose the screen also */ +/*************************************************/ + +static void pdp_capture_do_capture(t_pdp_capture *x) +{ + Colormap *colormaps; + Image *image; + int number_colormaps, number_windows, status, X, Y; + RectangleInfo crop_info; + Window *children, client, prior_target, root, target; + XTextProperty window_name; + Window child; + XWindowAttributes window_attributes; + + /* + Open X server connection. + */ + if (!x->x_displayopen) + { + post( "pdp_capture : display not open : no capture" ); + return; + } + (void) XSetErrorHandler(XError); + crop_info.x=x->x_x; + crop_info.y=x->x_y; + crop_info.width=x->x_vwidth; + crop_info.height=x->x_vheight; + root=XRootWindow(x->x_dpy, x->x_screen); + target=(Window) NULL; + prior_target=target; + + target = XMyGetSubwindow(x, x->x_dpy,root,x->x_x,x->x_y); + + client=target; /* obsolete */ + if (target != root) + { + unsigned int d; + status=XGetGeometry(x->x_dpy,target,&root,&X,&X,&d,&d,&d,&d); + if (status != 0) + { + for ( ; ; ) + { + Window parent; + + status=XQueryTree(x->x_dpy,target,&root,&parent,&children,&d); + if (status && (children != (Window *) NULL)) + { + (void) XFree((char *) children); + } + if (!status || (parent == (Window) NULL) || (parent == root)) break; + target=parent; + } + client=XMyClientWindow(x, x->x_dpy, target); + target=client; + if (prior_target) target=prior_target; + } + } + status=XGetWindowAttributes(x->x_dpy,target,&window_attributes); + if (status == 0) + { + post( "pdp_capture : unable to read window attributes" ); + (void) XCloseDisplay(x->x_dpy); + return; + } + (void) XTranslateCoordinates(x->x_dpy,target,root,0,0,&X,&Y,&child); + crop_info.x=x->x_x; + crop_info.y=x->x_y; + crop_info.width=x->x_vwidth; + crop_info.height=x->x_vheight; + target=root; + + number_windows=0; + status=XGetWMColormapWindows(x->x_dpy,target,&children,&number_windows); + if ((status == 1) && (number_windows > 0)) + { + (void) XFree ((char *) children); + } + colormaps=XListInstalledColormaps(x->x_dpy,target,&number_colormaps); + if (number_colormaps > 0) + { + (void) XFree((char *) colormaps); + } + + image=XMyGetWindowImage(x, x->x_dpy, target, 1); + if (image == (Image *) NULL) + { + post( "pdp_capture : unable to read xwindow image" ); + } + else + { + Image *clone_image; + + clone_image=CloneImage(image,0,0,1,&image->exception); + if (clone_image != (Image *) NULL) + { + x->x_Ximage=CropImage(clone_image,&crop_info,&image->exception); + if (x->x_Ximage != (Image *) NULL) + { + DestroyImage(image); + DestroyImage(clone_image); + image=x->x_Ximage; + } + } + status=XGetWMName(x->x_dpy,target,&window_name); + } + return; +} + +static void pdp_capture_display(t_pdp_capture *x, t_symbol *s) +{ + if ( x->x_displayopen ) + { + if ( XCloseDisplay(x->x_dpy) == -1 ) + { + post( "pdp_capture : could not close display" ); + } + } + strcpy( x->x_display, s->s_name ); + if ( ( x->x_dpy = XOpenDisplay( x->x_display ) ) != NULL ) + { + x->x_displayopen = 1; + + x->x_vwidth=XDisplayWidth(x->x_dpy, x->x_screen); + x->x_vheight=XDisplayHeight(x->x_dpy, x->x_screen); + x->x_vsize=x->x_vwidth*x->x_vheight; + + } +} + +static void pdp_capture_screen(t_pdp_capture *x, t_floatarg fscreen) +{ + if ( (int)fscreen > 0 ) + { + x->x_screen = (int) fscreen; + } +} + +static void pdp_capture_x(t_pdp_capture *x, t_floatarg fx) +{ + t_int width; + t_int err; + + if (!x->x_displayopen) + { + post( "pdp_capture : display not open : not setting x" ); + return; + } + width = XDisplayWidth( x->x_dpy, x->x_screen ); + if ( ( (int)fx > 0 ) && ( (int)fx <= width ) ) + { + x->x_x = (int) fx; + if ( x->x_x + x->x_vwidth > width ) + { + x->x_vwidth = width - x->x_x; + x->x_vsize = x->x_vwidth * x->x_vheight; + } + } + else + { + post( "pdp_capture : x position out of range : [0, %d]", width ); + } +} + +static void pdp_capture_y(t_pdp_capture *x, t_floatarg fy) +{ + t_int height; + t_int err; + + if (!x->x_displayopen) + { + post( "pdp_capture : display not open : not setting y" ); + return; + } + height = XDisplayHeight( x->x_dpy, x->x_screen ); + if ( ( (int)fy > 0 ) && ( (int)fy <= height ) ) + { + x->x_y = (int) fy; + if ( x->x_y + x->x_vheight > height ) + { + x->x_vheight = height - x->x_y; + x->x_vsize = x->x_vwidth * x->x_vheight; + } + } + else + { + post( "pdp_capture : y position out of range : [0, %d]", height ); + } +} + +static void pdp_capture_width(t_pdp_capture *x, t_floatarg fwidth) +{ + t_int width; + t_int err; + + if (!x->x_displayopen) + { + post( "pdp_capture : display not open : not setting width" ); + return; + } + width = XDisplayWidth( x->x_dpy, x->x_screen ); + if ( ( (int)fwidth > 0 ) && ( (int)fwidth <= (width-x->x_x) ) ) + { + x->x_vwidth = (int) fwidth; + x->x_vsize = x->x_vwidth * x->x_vheight; + } + else + { + post( "pdp_capture : width out of range : [0, %d]", width-x->x_x ); + } +} + +static void pdp_capture_height(t_pdp_capture *x, t_floatarg fheight) +{ + t_int height; + t_int err; + + if (!x->x_displayopen) + { + post( "pdp_capture : display not open : not setting height" ); + return; + } + height = XDisplayWidth( x->x_dpy, x->x_screen ); + if ( ( (int)fheight > 0 ) && ( (int)fheight <= (height-x->x_y) ) ) + { + x->x_vheight = (int) fheight; + x->x_vsize = x->x_vwidth * x->x_vheight; + } + else + { + post( "pdp_capture : width out of range : [0, %d]", height-x->x_y ); + } +} + +static void pdp_capture_sendpacket(t_pdp_capture *x) +{ + /* unregister and propagate if valid dest packet */ + if (x->x_packet0 != -1 ) + { + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0); + } +} + +static void pdp_capture_bang(t_pdp_capture *x) +{ + PixelPacket pixel; + short int *pY, *pU, *pV; + unsigned char y, u, v; + t_int px, py, r, g, b; + long number_pixels; + + // capture the image and output a PDP packet + pdp_capture_do_capture( x ); + + x->x_vwidth = x->x_Ximage->columns; + x->x_vheight = x->x_Ximage->rows; + x->x_vsize = x->x_vwidth*x->x_vheight; + + x->x_packet0 = pdp_packet_new_image_YCrCb( x->x_vwidth, x->x_vheight ); + x->x_data = (short int *)pdp_packet_data(x->x_packet0); + x->x_header = pdp_packet_header(x->x_packet0); + + x->x_header->info.image.encoding = PDP_IMAGE_YV12; + x->x_header->info.image.width = x->x_vwidth; + x->x_header->info.image.height = x->x_vheight; + + number_pixels=(long) GetPixelCacheArea(x->x_Ximage); + + // post( "pdp_capture : capture done : w=%d h=%d pixels=%ld", x->x_vwidth, x->x_vheight, number_pixels ); + + pY = x->x_data; + pV = x->x_data+x->x_vsize; + pU = x->x_data+x->x_vsize+(x->x_vsize>>2); + for ( py=0; py<x->x_vheight; py++ ) + { + for ( px=0; px<x->x_vwidth; px++ ) + { + pixel = GetOnePixel(x->x_Ximage, px, py); + // scale values + r = (pixel.red*255)/65535; + g = (pixel.green*255)/65535; + b = (pixel.blue*255)/65535; + // post( "pdp_capture : pixel : [%d, %d] : %d,%d,%d", px, py, r, g, b ); + y = yuv_RGBtoY(((r)<<16)+((g)<<8)+(b)); + u = yuv_RGBtoU(((r)<<16)+((g)<<8)+(b)); + v = yuv_RGBtoV(((r)<<16)+((g)<<8)+(b)); + + *(pY) = y<<7; + if ( (px%2==0) && (py%2==0) ) + { + *(pV) = (v-128)<<8; + *(pU) = (u-128)<<8; + } + pY++; + if ( (px%2==0) && (py%2==0) ) + { + pV++;pU++; + } + } + } + + // output the new packet + pdp_capture_sendpacket( x ); + + DestroyImage( x->x_Ximage ); +} + +static void pdp_capture_free(t_pdp_capture *x) +{ + int i; + + if ( x->x_packet0 != -1 ) + { + pdp_packet_mark_unused(x->x_packet0); + } + if ( x->x_displayopen ) + { + if ( XCloseDisplay(x->x_dpy) == -1 ) + { + post( "pdp_capture : could not close display" ); + } + } +} + +t_class *pdp_capture_class; + +void *pdp_capture_new(void) +{ + int i; + + t_pdp_capture *x = (t_pdp_capture *)pd_new(pdp_capture_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("x")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("y")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("width")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("height")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_packet0 = -1; + + x->x_display = (char *) malloc( PDP_DISPLAY_LENGTH ); + strcpy( x->x_display, ":0.0" ); + + x->x_displayopen = 0; + if ( ( x->x_dpy = XOpenDisplay( x->x_display ) ) != NULL ) + { + x->x_displayopen = 1; + + x->x_vwidth=XDisplayWidth(x->x_dpy, x->x_screen); + x->x_vheight=XDisplayWidth(x->x_dpy, x->x_screen); + x->x_vsize=x->x_vwidth*x->x_vheight; + + } + + x->x_screen = 0; + x->x_x = 0; + x->x_y = 0; + x->x_vwidth = 320; + x->x_vheight = 240; + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_capture_setup(void) +{ + post( pdp_capture_version ); + pdp_capture_class = class_new(gensym("pdp_capture"), (t_newmethod)pdp_capture_new, + (t_method)pdp_capture_free, sizeof(t_pdp_capture), 0, A_NULL); + + class_addmethod(pdp_capture_class, (t_method)pdp_capture_bang, gensym("bang"), A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_display, gensym("display"), A_SYMBOL, A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_screen, gensym("screen"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_x, gensym("x"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_y, gensym("y"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_width, gensym("width"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_capture_class, (t_method)pdp_capture_height, gensym("height"), A_DEFFLOAT, A_NULL); + +} + +#ifdef __cplusplus +} +#endif |