330 lines
7.4 KiB
C
330 lines
7.4 KiB
C
|
/*
|
|||
|
* tkWinImage.c --
|
|||
|
*
|
|||
|
* This file contains routines for manipulation full-color images.
|
|||
|
*
|
|||
|
* Copyright (c) 1995 Sun Microsystems, Inc.
|
|||
|
*
|
|||
|
* See the file "license.terms" for information on usage and redistribution
|
|||
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
|
*
|
|||
|
* SCCS: @(#) tkWinImage.c 1.13 97/07/07 11:19:45
|
|||
|
*/
|
|||
|
|
|||
|
#include "tkWinInt.h"
|
|||
|
|
|||
|
static int DestroyImage _ANSI_ARGS_((XImage* data));
|
|||
|
static unsigned long ImageGetPixel _ANSI_ARGS_((XImage *image, int x, int y));
|
|||
|
static int PutPixel _ANSI_ARGS_((XImage *image, int x, int y,
|
|||
|
unsigned long pixel));
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* DestroyImage --
|
|||
|
*
|
|||
|
* This is a trivial wrapper around ckfree to make it possible to
|
|||
|
* pass ckfree as a pointer.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* Deallocates the image.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
int
|
|||
|
DestroyImage(imagePtr)
|
|||
|
XImage *imagePtr; /* image to free */
|
|||
|
{
|
|||
|
if (imagePtr) {
|
|||
|
if (imagePtr->data) {
|
|||
|
ckfree((char*)imagePtr->data);
|
|||
|
}
|
|||
|
ckfree((char*)imagePtr);
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* ImageGetPixel --
|
|||
|
*
|
|||
|
* Get a single pixel from an image.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Returns the 32 bit pixel value.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
unsigned long
|
|||
|
ImageGetPixel(image, x, y)
|
|||
|
XImage *image;
|
|||
|
int x, y;
|
|||
|
{
|
|||
|
unsigned long pixel = 0;
|
|||
|
unsigned char *srcPtr = &(image->data[(y * image->bytes_per_line)
|
|||
|
+ ((x * image->bits_per_pixel) / NBBY)]);
|
|||
|
|
|||
|
switch (image->bits_per_pixel) {
|
|||
|
case 32:
|
|||
|
case 24:
|
|||
|
pixel = RGB(srcPtr[2], srcPtr[1], srcPtr[0]);
|
|||
|
break;
|
|||
|
case 16:
|
|||
|
pixel = RGB(((((WORD*)srcPtr)[0]) >> 7) & 0xf8,
|
|||
|
((((WORD*)srcPtr)[0]) >> 2) & 0xf8,
|
|||
|
((((WORD*)srcPtr)[0]) << 3) & 0xf8);
|
|||
|
break;
|
|||
|
case 8:
|
|||
|
pixel = srcPtr[0];
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
pixel = ((x%2) ? (*srcPtr) : ((*srcPtr) >> 4)) & 0x0f;
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
pixel = ((*srcPtr) & (0x80 >> (x%8))) ? 1 : 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
return pixel;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* PutPixel --
|
|||
|
*
|
|||
|
* Set a single pixel in an image.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* None.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
static int
|
|||
|
PutPixel(image, x, y, pixel)
|
|||
|
XImage *image;
|
|||
|
int x, y;
|
|||
|
unsigned long pixel;
|
|||
|
{
|
|||
|
unsigned char *destPtr = &(image->data[(y * image->bytes_per_line)
|
|||
|
+ ((x * image->bits_per_pixel) / NBBY)]);
|
|||
|
|
|||
|
switch (image->bits_per_pixel) {
|
|||
|
case 32:
|
|||
|
/*
|
|||
|
* Pixel is DWORD: 0x00BBGGRR
|
|||
|
*/
|
|||
|
|
|||
|
destPtr[3] = 0;
|
|||
|
case 24:
|
|||
|
/*
|
|||
|
* Pixel is triplet: 0xBBGGRR.
|
|||
|
*/
|
|||
|
|
|||
|
destPtr[0] = (unsigned char) GetBValue(pixel);
|
|||
|
destPtr[1] = (unsigned char) GetGValue(pixel);
|
|||
|
destPtr[2] = (unsigned char) GetRValue(pixel);
|
|||
|
break;
|
|||
|
case 16:
|
|||
|
/*
|
|||
|
* Pixel is WORD: 5-5-5 (R-G-B)
|
|||
|
*/
|
|||
|
|
|||
|
(*(WORD*)destPtr) =
|
|||
|
((GetRValue(pixel) & 0xf8) << 7)
|
|||
|
| ((GetGValue(pixel) & 0xf8) <<2)
|
|||
|
| ((GetBValue(pixel) & 0xf8) >> 3);
|
|||
|
break;
|
|||
|
case 8:
|
|||
|
/*
|
|||
|
* Pixel is 8-bit index into color table.
|
|||
|
*/
|
|||
|
|
|||
|
(*destPtr) = (unsigned char) pixel;
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
/*
|
|||
|
* Pixel is 4-bit index in MSBFirst order.
|
|||
|
*/
|
|||
|
if (x%2) {
|
|||
|
(*destPtr) = (unsigned char) (((*destPtr) & 0xf0)
|
|||
|
| (pixel & 0x0f));
|
|||
|
} else {
|
|||
|
(*destPtr) = (unsigned char) (((*destPtr) & 0x0f)
|
|||
|
| ((pixel << 4) & 0xf0));
|
|||
|
}
|
|||
|
break;
|
|||
|
case 1: {
|
|||
|
/*
|
|||
|
* Pixel is bit in MSBFirst order.
|
|||
|
*/
|
|||
|
|
|||
|
int mask = (0x80 >> (x%8));
|
|||
|
if (pixel) {
|
|||
|
(*destPtr) |= mask;
|
|||
|
} else {
|
|||
|
(*destPtr) &= ~mask;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* XCreateImage --
|
|||
|
*
|
|||
|
* Allocates storage for a new XImage.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Returns a newly allocated XImage.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
XImage *
|
|||
|
XCreateImage(display, visual, depth, format, offset, data, width, height,
|
|||
|
bitmap_pad, bytes_per_line)
|
|||
|
Display* display;
|
|||
|
Visual* visual;
|
|||
|
unsigned int depth;
|
|||
|
int format;
|
|||
|
int offset;
|
|||
|
char* data;
|
|||
|
unsigned int width;
|
|||
|
unsigned int height;
|
|||
|
int bitmap_pad;
|
|||
|
int bytes_per_line;
|
|||
|
{
|
|||
|
XImage* imagePtr = (XImage *) ckalloc(sizeof(XImage));
|
|||
|
imagePtr->width = width;
|
|||
|
imagePtr->height = height;
|
|||
|
imagePtr->xoffset = offset;
|
|||
|
imagePtr->format = format;
|
|||
|
imagePtr->data = data;
|
|||
|
imagePtr->byte_order = LSBFirst;
|
|||
|
imagePtr->bitmap_unit = 8;
|
|||
|
imagePtr->bitmap_bit_order = MSBFirst;
|
|||
|
imagePtr->bitmap_pad = bitmap_pad;
|
|||
|
imagePtr->bits_per_pixel = depth;
|
|||
|
imagePtr->depth = depth;
|
|||
|
|
|||
|
/*
|
|||
|
* Under Windows, bitmap_pad must be on an LONG data-type boundary.
|
|||
|
*/
|
|||
|
|
|||
|
#define LONGBITS (sizeof(LONG) * 8)
|
|||
|
|
|||
|
bitmap_pad = (bitmap_pad + LONGBITS - 1) / LONGBITS * LONGBITS;
|
|||
|
|
|||
|
/*
|
|||
|
* Round to the nearest bitmap_pad boundary.
|
|||
|
*/
|
|||
|
|
|||
|
if (bytes_per_line) {
|
|||
|
imagePtr->bytes_per_line = bytes_per_line;
|
|||
|
} else {
|
|||
|
imagePtr->bytes_per_line = (((depth * width)
|
|||
|
+ (bitmap_pad - 1)) >> 3) & ~((bitmap_pad >> 3) - 1);
|
|||
|
}
|
|||
|
|
|||
|
imagePtr->red_mask = 0;
|
|||
|
imagePtr->green_mask = 0;
|
|||
|
imagePtr->blue_mask = 0;
|
|||
|
|
|||
|
imagePtr->f.put_pixel = PutPixel;
|
|||
|
imagePtr->f.get_pixel = ImageGetPixel;
|
|||
|
imagePtr->f.destroy_image = DestroyImage;
|
|||
|
imagePtr->f.create_image = NULL;
|
|||
|
imagePtr->f.sub_image = NULL;
|
|||
|
imagePtr->f.add_pixel = NULL;
|
|||
|
|
|||
|
return imagePtr;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*
|
|||
|
* XGetImage --
|
|||
|
*
|
|||
|
* This function copies data from a pixmap or window into an
|
|||
|
* XImage.
|
|||
|
*
|
|||
|
* Results:
|
|||
|
* Returns a newly allocated image containing the data from the
|
|||
|
* given rectangle of the given drawable.
|
|||
|
*
|
|||
|
* Side effects:
|
|||
|
* None.
|
|||
|
*
|
|||
|
*----------------------------------------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
XImage *
|
|||
|
XGetImage(display, d, x, y, width, height, plane_mask, format)
|
|||
|
Display* display;
|
|||
|
Drawable d;
|
|||
|
int x;
|
|||
|
int y;
|
|||
|
unsigned int width;
|
|||
|
unsigned int height;
|
|||
|
unsigned long plane_mask;
|
|||
|
int format;
|
|||
|
{
|
|||
|
TkWinDrawable *twdPtr = (TkWinDrawable *)d;
|
|||
|
XImage *imagePtr;
|
|||
|
HDC dc;
|
|||
|
char infoBuf[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
|
|||
|
BITMAPINFO *infoPtr = (BITMAPINFO*)infoBuf;
|
|||
|
|
|||
|
if ((twdPtr->type != TWD_BITMAP) || (twdPtr->bitmap.handle == NULL)
|
|||
|
|| (format != XYPixmap) || (plane_mask != 1)) {
|
|||
|
panic("XGetImage: not implemented");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
imagePtr = XCreateImage(display, NULL, 1, XYBitmap, 0, NULL,
|
|||
|
width, height, 32, 0);
|
|||
|
imagePtr->data = ckalloc(imagePtr->bytes_per_line * imagePtr->height);
|
|||
|
|
|||
|
dc = GetDC(NULL);
|
|||
|
|
|||
|
GetDIBits(dc, twdPtr->bitmap.handle, 0, height, NULL,
|
|||
|
infoPtr, DIB_RGB_COLORS);
|
|||
|
|
|||
|
infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|||
|
infoPtr->bmiHeader.biWidth = width;
|
|||
|
infoPtr->bmiHeader.biHeight = -(LONG)height;
|
|||
|
infoPtr->bmiHeader.biPlanes = 1;
|
|||
|
infoPtr->bmiHeader.biBitCount = 1;
|
|||
|
infoPtr->bmiHeader.biCompression = BI_RGB;
|
|||
|
infoPtr->bmiHeader.biCompression = 0;
|
|||
|
infoPtr->bmiHeader.biXPelsPerMeter = 0;
|
|||
|
infoPtr->bmiHeader.biYPelsPerMeter = 0;
|
|||
|
infoPtr->bmiHeader.biClrUsed = 0;
|
|||
|
infoPtr->bmiHeader.biClrImportant = 0;
|
|||
|
|
|||
|
GetDIBits(dc, twdPtr->bitmap.handle, 0, height, imagePtr->data,
|
|||
|
infoPtr, DIB_RGB_COLORS);
|
|||
|
ReleaseDC(NULL, dc);
|
|||
|
|
|||
|
return imagePtr;
|
|||
|
}
|