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

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

 /*
  * $Log: bitmap_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: bitmap_image.c                 <<<<
   >>>>                                                       <<<<
   >>>>		Creates a bitmap Khoros Image		      <<<<
   >>>>                                                       <<<<
   >>>>                create_bitmap_image()	              <<<<              
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */


/************************************************************
*
*  MODULE NAME: create_bitmap_image
*
*      PURPOSE: Creates a bitmap 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 bitmap image that is padded to 8 bits.
*
*
*   WRITTEN BY: Mark Young
*
*************************************************************/

#define XVSetBit(num,bit)	(num | bit)	    /* Set the bit in num */
#define XVClearBit(num,bit)	(num & (~bit))	    /* Clear the bit in num */


struct xvimage *create_bitmap_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, border, depth;
	unsigned long	bg, planes;
 
	register int	 row, col, pos;
	register unsigned char	*bitmap, bit;
	register XImage 	*ximage;

	int	x, y, rx, ry, size;
	Window	root, dummy;
	struct	xvimage *image, *createimage();

	if ( !XGetGeometry(display, workspace, &root, &rx, &ry, 
                           &width, &height,  &border, &depth))
	{
	   (void) fprintf(stderr,"\n\ncreate_bitmap_image:  ");
	   (void) fprintf(stderr,"Window does not exist.\n\n");
	   return(NULL);
	}
	else
	{
	   XTranslateCoordinates(display, workspace,XDefaultRootWindow(display),
				 0, 0, &x, &y, &dummy);
	}

	/*
	 * 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 
	 */
	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;

	/*
	 * inquire about the background color and then get the window's
	 * image.
	 */
	bg = BlackPixel(display, screen_num);
	if (depth == 1)
	{
	   /* 
	    * dump graphics window from monochrome display 
	    */
	   planes = DisplayPlanes(display, screen_num);
           ximage = XGetImage(display, workspace, x, y, width, height, planes, 
			      XYPixmap);
	}
	else
	{
	   /*
	    * else dump graphics window with AllPlanes 
	    */
           ximage = XGetImage(display, workspace, x, y, width, height, 
			      AllPlanes, ZPixmap);
	}

	/*
	 * fill the xvimage structure with appropriate
	 * values and defaults where necessary     
	 */
	if (!(image = createimage(ximage->height, ximage->width, VFF_TYP_BIT,
                    1, 1, "khoros bitmap screen image", 0, 0, VFF_MS_NONE,
		    VFF_MAPTYP_NONE, VFF_LOC_IMPLICIT, 0)))
	{
	   return(NULL);
	}

  	bitmap = (unsigned char *) image->imagedata;
	size = (((ximage->width +7)/8) * ximage->height);
	bzero((char *) bitmap, size); 
 
	/*
	 * for each pixel value in the image, we either set or clear the
	 * corresponding bit.  A bit is cleared if the pixel value equals
	 * the image's background color, else the bit is set.  This is done
	 * for each row of pixels, which is then padded (cleared) to the 
	 * nearest multiple of 8. 
	 */
	for (row = 0; row < ximage->height; row++)
	{
	    pos = 0;
	    for (col = 0; col < ximage->width; col++)
	    {
		bit = 1 << pos;      /* Bit to set or clear */
		if (XGetPixel(ximage,col,row) != bg)
		   *bitmap = XVSetBit(*bitmap, bit);
		else
		   *bitmap = XVClearBit(*bitmap, bit);

		if (pos == 7)
		{
		   bitmap++;
		   pos = 0;
		}
		else pos++;
	    }

	    /* pad the rest of the byte with zeros */
	    if (pos != 0)
	    {
	       for (col = pos; col < 8; col++)
	       {
		   bit = 1 << pos;
		   *bitmap = XVClearBit(*bitmap, bit);
	       }
	       bitmap++;
	    }
	}

	/*
	 * Destroy the X window image and return the khoros image
	 */
	XDestroyImage(ximage); 
	return (image);
}
