 /*
  * Khoros: $Id: pixmap_image.c,v 1.1 1991/05/10 15:57:28 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: pixmap_image.c,v 1.1 1991/05/10 15:57:28 khoros Exp $";
#endif

 /*
  * $Log: pixmap_image.c,v $
 * Revision 1.1  1991/05/10  15:57:28  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "xvutils.h"	


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    	    file name: pixmap_image.c                 <<<<
   >>>>                                                       <<<<
   >>>>         Creates a pixmap Khoros Image                 <<<<
   >>>>                                                       <<<<
   >>>>                create_pixmap_image()		      <<<<              
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */

/*
 * We should not have to define Xfree() since the X11R2 documentation
 * implies that it available through the X11 libraries, but I
 * can't seem to find it in any libraries or includes.  Xfree()
 * is defined in the source directory lib/X/Xlibos.h, which is
 * not available at the regular library level.
 */
#ifndef Xfree
#define Xfree(str) free((str))
#endif

/************************************************************
*
*  MODULE NAME: create_pixmap_image
*
*      PURPOSE: Creates a pixmap khoros image that is padded to 8 bits
*		from an ximage, which may be padded to 4, 8, 16, or 32 bits
*               
*        INPUT: 1. display --	The Display in which the window resides.
*		2. screen_num--	Which screen (inside the Display) in which the 
*				window resides.
*		3. workspace --	The window in which we are to create the khoros
*				image.
*		4. subimage --	An integer flag indicating if the image is to
*				be extracted from a portion of the rootwindow
*				or some window.
*		5. sub_x,
*		   sub_y,
*		   sub_width,
*		   sub_height--	Integers representing the x, y, width, height
*				of the screen in which to extract the image.
*
*       OUTPUT: creates a pixmap khoros image.
*
*
*   WRITTEN BY: Mark Young
*
*************************************************************/


struct xvimage *create_pixmap_image(display, screen_num, workspace, subimage,
				    sub_x, sub_y, sub_width, sub_height)

Display	*display;
int	screen_num;
Window	workspace;
int	subimage, sub_x, sub_y, sub_width, sub_height;
{
	unsigned int	 width, height, depth;
	int		 map_size, map_num, color_model;
 
	register int	  row, col;
	register unsigned char	*pixmap, *color;
	XImage		  *ximage;
	Window		  dummy, rootwindow;
	XWindowAttributes attributes;

	int		x, y, i;
	Visual		*visual;
	XColor		color_defs[256];
	char		*malloc();
	struct	xvimage *image, *create_bitmap_image(), *createimage();


	XFlush(display);
	if ( !XGetWindowAttributes(display, workspace, &attributes))
	{
	   (void) fprintf (stderr,"\n\ncreate_pixmap_image:  ");
	   (void) fprintf (stderr,"Window does not exist.\n\n");
	   return(NULL);
	}
	else
	{
	   rootwindow = XDefaultRootWindow(display);
	   XTranslateCoordinates(display, workspace, rootwindow,
			0, 0, &x, &y, &dummy);
	}
	width  = attributes.width;
	height = attributes.height;
	depth  = attributes.depth;

	/*
	 * Check to see if the user wishes to extract a subimage, rather
	 * than a whole window.
	 */
	if (subimage)
	{
	   if (sub_x < 0) sub_x = 0;
	   if (sub_y < 0) sub_y = 0;

	   if ((sub_width - sub_x) <= ((int) width))
	      width = sub_width;

	   if ((sub_height - sub_y) <= ((int) height))
	      height = sub_height;

	   x = sub_x;
	   y = sub_y;
	}

	/*
	 * Make sure the desired window does not overlap the display
	 */
	if ((x + width) > XDisplayWidth(display, screen_num))
	   width = XDisplayWidth(display, screen_num) - x;

	if (x < 0)
	{
	   x = abs(x);
	   width = width - x;
	}
	else if (!subimage)
	   x = 0;

	if ((y + height) > XDisplayHeight(display, screen_num))
	   height = XDisplayHeight(display, screen_num) - y;

	if (y < 0)
	{
	   y = abs(y);
	   height = height - y;
	}
	else if (!subimage)
	   y = 0;


	/*
	 *  Display is really a bitmap screen so call "create_bitmap_image".
	 */
	if (depth == 1)
	{
	   /* 
	    * return the bitmap khoros image created from 
	    * "create_bitmap_image"
	    */
           return(create_bitmap_image(display, screen_num, workspace, subimage,
				      sub_x, sub_y, sub_width, sub_height));
	}
	else
	{
	   /*
	    *  else dump graphics window with AllPlanes 
	    */
           ximage = XGetImage(display, workspace, x, y, width, height, 
			      AllPlanes, ZPixmap);
	   visual = attributes.visual;
	}

	map_size = visual->map_entries;
	switch (visual->class)
	{
	    case DirectColor:
	    case TrueColor:

	    case PseudoColor:
	    case StaticColor:
				map_num = 3;
				color_model = VFF_CM_genericRGB;
				break;
	    case GrayScale:
	    case StaticGray:
				map_num = 1;
				color_model = VFF_CM_NONE;
				break;
	}


	/*
         * fill the xvimage structure with appropriate
         * values and defaults where necessary
         */
        image = createimage(ximage->height, ximage->width, VFF_TYP_1_BYTE,
                    1, 1, "khoros pixmap screen image", map_num, map_size,
		    VFF_MS_ONEPERBAND, VFF_MAPTYP_1_BYTE, VFF_LOC_IMPLICIT, 0);

	if (image == NULL)
	{
	   return(NULL);
	}

	image->map_enable = VFF_MAP_FORCE;
	image->map_scheme = VFF_MS_ONEPERBAND;
	image->color_space_model = color_model;

	/*
	 *  Get the Normalized pixel values off the screen.
	 */
	pixmap = (unsigned char *) image->imagedata;
	for (row = 0; row < ximage->height; row++)
	{
	    for (col = 0; col < ximage->width; col++)
		*pixmap++ = (unsigned char) XGetPixel(ximage,col,row);
	}


	for (i = 0; i < map_size; i++)
	{
	    color_defs[i].pixel = i;
	    color_defs[i].flags = DoRed | DoGreen | DoBlue;
	}
	XQueryColors(display, attributes.colormap, color_defs, map_size);

	if (map_num == 3)
	{
	   color = (unsigned char *) image->maps;
	   for (i = 0; i < map_size; i++)
	   {
	       color[i]		     = color_defs[i].red/256;
	       color[i + map_size]   = color_defs[i].green/256;
	       color[i + 2*map_size] = color_defs[i].blue/256;
	   }
	}
	else if (color_model == VFF_CM_NONE)
	{
	   color = (unsigned char *) image->maps;
	   for (i = 0; i < map_size; i++)
	       color[i]	= color_defs[i].red/256;
	}

	/*
	 *  Clean up!!  What a mess.
	 */
	XDestroyImage(ximage); 
	return (image);
}
