head 1.1; branch 1.1.1; access ; symbols start:1.1.1.1 keithp:1.1.1; locks ; strict; comment @ * @; 1.1 date 2003.04.22.19.43.31; author cworth; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2003.04.22.19.43.31; author cworth; state Exp; branches ; next ; desc @@ 1.1 log @Initial revision @ text @/* xctest - silly little demonstration of Xc * * Copyright © 2002 USC/Information Sciences Institute * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of * Information Sciences Institute not be used in advertising or * publicity pertaining to distribution of the software without * specific, written prior permission. Information Sciences Institute * makes no representations about the suitability of this software for * any purpose. It is provided "as is" without express or implied * warranty. * * INFORMATION SCIENCES INSTITUTE DISCLAIMS ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INFORMATION SCIENCES * INSTITUTE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER 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 * PERFORMANCE OF THIS SOFTWARE. * * Author: Carl Worth */ #include #include #include #define XCTEST_USE_RENDER 0 /* XXX: Yes, this is totally bogus */ #include "icint.h" #include typedef enum _ictest_status { STATUS_SUCCESS, STATUS_NO_MEMORY, STATUS_FILE_NOT_FOUND, STATUS_IMAGE_NOT_PNG, STATUS_IO_ERROR } ictest_status_t; typedef struct _img { unsigned char *data; unsigned int width; unsigned int height; unsigned int stride; unsigned int depth; IcImage *icimage; Display *dpy; Pixmap pix; XcSurface *surface; } img_t; static ictest_status_t read_png_argb (const char *filename, unsigned char **data, unsigned int *width, unsigned int *height, unsigned int *stride, unsigned int *depth); static ictest_status_t write_png_argb (const char *filename, unsigned char *data, unsigned int width, unsigned int height, unsigned int stride, unsigned int depth); static const char * status_str (ictest_status_t status); static ictest_status_t img_init_icimage (img_t *img, const char *filename); #if XCTEST_USE_RENDER static ictest_status_t img_init_pixmap (img_t *img, Display *dpy, const char *filename); #endif static void img_deinit (img_t *img); #define MIN(a,b) ((a) < (b)) ? (a) : (b) static XFixed DoubleToFixed(XDouble d) { d = d * 65536; if (d < 0) return -((XFixed) (-d + 0.5)); else return (XFixed) (d + 0.5); } int main(int argc, char *argv[]) { unsigned int width, height; img_t a, b; ictest_status_t status; XTrapezoid trap; XTriangle tri; XcColor color; #if XCTEST_USE_RENDER Display *dpy; XImage *ximage; #endif if (argc < 4) { fprintf(stderr, "Usage: %s input1.png input2.png output.png\n", argv[0]); return 1; } #if XCTEST_USE_RENDER dpy = XOpenDisplay (NULL); if (dpy == 0) { fprintf (stderr, "Failed to open display: %s\n", XDisplayName(NULL)); exit (1); } XSynchronize (dpy, 1); #endif #if XCTEST_USE_RENDER status = img_init_pixmap (&a, dpy, argv[1]); #else status = img_init_icimage (&a, argv[1]); #endif if (status) return status; #if XCTEST_USE_RENDER status = img_init_pixmap (&b, dpy, argv[2]); #else status = img_init_icimage (&b, argv[2]); #endif if (status) return status; width = MIN (a.width, b.width); height = MIN (a.height, b.height); /* IcComposite (PictOpOver, a.icimage, NULL, b.icimage, a.width > b.width ? (a.width - b.width) / 2 : 0, a.height > b.height ? (a.height - b.height) / 2 : 0, 0, 0, b.width > a.width ? (b.width - a.width) / 2 : 0, b.height > a.height ? (b.height - a.height) / 2 : 0, width, height); */ trap.top = DoubleToFixed (100); trap.bottom = DoubleToFixed (400); trap.left.p1.x = DoubleToFixed (100); trap.left.p1.y = DoubleToFixed (100); trap.left.p2.x = DoubleToFixed (50); trap.left.p2.y = DoubleToFixed (400); trap.right.p1.x = DoubleToFixed (350); trap.right.p1.y = DoubleToFixed (100); trap.right.p2.x = DoubleToFixed (250); trap.right.p2.y = DoubleToFixed (400); tri.p1.x = DoubleToFixed (10); tri.p1.y = DoubleToFixed (10); tri.p2.x = DoubleToFixed (400); tri.p2.y = DoubleToFixed (30); tri.p3.x = DoubleToFixed (390); tri.p3.y = DoubleToFixed (430); color.red = 0x8000; color.blue = 0x8000; color.green = 0x0; color.alpha = 0x8000; XcCompositeTrapezoids (PictOpOver, a.surface, b.surface, XFixedToDouble(trap.left.p1.x), XFixedToDouble(trap.left.p1.y), &trap, 1); XcCompositeTriangles (PictOpOver, a.surface, b.surface, XFixedToDouble(tri.p1.x), XFixedToDouble(tri.p1.y), &tri, 1); XcFillRectangle (PictOpOver, b.surface, &color, 100, 100, 250, 250); #if XCTEST_USE_RENDER XSync (dpy, 0); ximage = XGetImage (dpy, b.pix, 0, 0, b.width, b.height, AllPlanes, ZPixmap); write_png_argb (argv[3], (unsigned char *) ximage->data, ximage->width, ximage->height, ximage->bytes_per_line, ximage->depth); XDestroyImage (ximage); #else write_png_argb (argv[3], (unsigned char *) b.data, b.width, b.height, b.stride, b.depth); #endif img_deinit (&a); img_deinit (&b); #if XCTEST_USE_RENDER XCloseDisplay (dpy); #endif return 0; } static ictest_status_t img_init_icimage (img_t *img, const char *filename) { ictest_status_t status; IcFormat format; /* zero out the fields we don't use */ img->dpy = NULL; img->pix = 0; status = read_png_argb (filename, &img->data, &img->width, &img->height, &img->stride, &img->depth); if (status) { fprintf (stderr, "Error reading %s: %s.\n", filename, status_str (status)); return status; } IcFormatInit (&format, PICT_a8r8g8b8); img->icimage = IcImageCreateForData ((IcBits *) img->data, &format, img->width, img->height, img->depth, img->stride); img->surface = XcSurfaceCreateForIcImage (img->icimage); return STATUS_SUCCESS; } #if XCTEST_USE_RENDER static ictest_status_t img_init_pixmap (img_t *img, Display *dpy, const char *filename) { int scr = DefaultScreen (dpy); ictest_status_t status; /* zero out the fields we don't use */ img->icimage = NULL; img->dpy = dpy; status = read_png_argb (filename, &img->data, &img->width, &img->height, &img->stride, &img->depth); if (status) { fprintf (stderr, "Error reading %s: %s.\n", filename, status_str (status)); return status; } img->pix = XCreatePixmap (dpy, DefaultRootWindow (dpy), img->width, img->height, img->depth); img->surface = XcSurfaceCreateForDrawable (dpy, img->pix, NULL, PictStandardARGB32, DefaultColormap (dpy, scr)); XcSurfacePutImage (img->surface, img->data, img->width, img->height, img->stride, img->depth); return STATUS_SUCCESS; } #endif static void img_deinit (img_t *img) { XcSurfaceDestroy (img->surface); free (img->data); if (img->icimage) IcImageDestroy (img->icimage); img->icimage = NULL; if (img->pix) XFreePixmap (img->dpy, img->pix); img->pix = 0; } static const char * status_str (ictest_status_t status) { switch (status) { case STATUS_NO_MEMORY: return "no memory"; break; case STATUS_FILE_NOT_FOUND: return "file not found"; break; case STATUS_IMAGE_NOT_PNG: return "file is not a PNG image"; break; case STATUS_SUCCESS: default: return "success"; break; } } static void premultiply_data (png_structp png, png_row_infop row_info, png_bytep data) { int i; for (i = 0; i < row_info->rowbytes; i += 4) { unsigned char *b = &data[i]; unsigned char alpha = b[3]; unsigned long pixel = ((((b[0] * alpha) / 255) << 0) | (((b[1] * alpha) / 255) << 8) | (((b[2] * alpha) / 255) << 16) | (alpha << 24)); unsigned long *p = (unsigned long *) b; *p = pixel; } } static void saturate_alpha (png_structp png, png_row_infop row_info, png_bytep data) { int i; for (i = 0; i < row_info->rowbytes; i += 4) { unsigned char *b = &data[i]; unsigned long pixel; unsigned long *p; pixel = ((b[0] << 0) | (b[1] << 8) | (b[2] << 16) | (0xff << 24)); p = (unsigned long *) b; *p = pixel; } } static void unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) { int i; for (i = 0; i < row_info->rowbytes; i += 4) { unsigned char *b = &data[i]; unsigned char alpha = b[3]; unsigned long pixel; unsigned long *p; if (alpha == 0) pixel = 0; else pixel = ((((b[0] * 255) / alpha) << 0) | (((b[1] * 255) / alpha) << 8) | (((b[2] * 255) / alpha) << 16) | (alpha << 24)); p = (unsigned long *) b; *p = pixel; } } static ictest_status_t read_png_argb (const char *file_name, unsigned char **data, unsigned int *width, unsigned int *height, unsigned int *stride, unsigned int *depth) { int i, bpp; FILE *file; #define PNG_SIG_SIZE 8 unsigned char png_sig[PNG_SIG_SIZE]; int sig_bytes; png_struct *png; png_info *info; png_uint_32 png_width, png_height; int png_depth; int color_type, interlace; png_byte **row_pointers; file = fopen (file_name, "rb"); if (file == NULL) return STATUS_FILE_NOT_FOUND; sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file); if (png_check_sig (png_sig, sig_bytes) == 0) { fclose (file); return STATUS_IMAGE_NOT_PNG; } /* XXX: Perhaps we'll want some other error handlers? */ png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { fclose (file); return STATUS_NO_MEMORY; } info = png_create_info_struct (png); if (info == NULL) { fclose (file); png_destroy_read_struct (&png, NULL, NULL); return STATUS_NO_MEMORY; } png_init_io (png, file); png_set_sig_bytes (png, sig_bytes); png_read_info (png, info); png_get_IHDR (png, info, &png_width, &png_height, &png_depth, &color_type, &interlace, NULL, NULL); *width = png_width; *height = png_height; *depth = 32; bpp = 32; *stride = ((*width * bpp + ((1 << IC_SHIFT) - 1)) >> IC_SHIFT) * sizeof (IcBits); /* convert palette/gray image to rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png); /* expand gray bit depth if needed */ if (color_type == PNG_COLOR_TYPE_GRAY && png_depth < 8) png_set_gray_1_2_4_to_8 (png); /* transform transparency to alpha */ if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); if (png_depth == 16) png_set_strip_16 (png); if (png_depth < 8) png_set_packing (png); /* convert grayscale to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png); if (interlace != PNG_INTERLACE_NONE) png_set_interlace_handling (png); png_set_bgr (png); png_set_filler (png, 0xff, PNG_FILLER_AFTER); png_set_read_user_transform_fn (png, premultiply_data); png_read_update_info (png, info); *data = malloc (png_height * *stride * (bpp / 8)); if (*data == NULL) { fclose (file); return STATUS_NO_MEMORY; } row_pointers = malloc (png_height * sizeof(char *)); for (i=0; i < png_height; i++) row_pointers[i] = (png_byte *) (*data + i * *stride); png_read_image (png, row_pointers); png_read_end (png, info); free (row_pointers); fclose (file); png_destroy_read_struct (&png, &info, NULL); return STATUS_SUCCESS; } static ictest_status_t write_png_argb (const char *filename, unsigned char *data, unsigned int width, unsigned int height, unsigned int stride, unsigned int depth) { int i; FILE *file; png_struct *png; png_info *info; png_byte **rows; png_color_16 white; file = fopen (filename, "wb"); if (file == NULL) return STATUS_IO_ERROR; rows = malloc (height * sizeof (png_byte *)); if (rows == NULL) return STATUS_NO_MEMORY; for (i=0; i < height; i++) { rows[i] = data + i * stride; } png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) return STATUS_NO_MEMORY; info = png_create_info_struct (png); if (info == NULL) { fclose (file); png_destroy_write_struct (&png, NULL); return STATUS_NO_MEMORY; } png_init_io (png, file); png_set_IHDR (png, info, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); white.red = 0xff; white.green = 0xff; white.blue = 0xff; png_set_bKGD (png, info, &white); png_set_write_user_transform_fn (png, depth == 24 ? saturate_alpha : unpremultiply_data); png_set_bgr (png); png_write_info (png, info); png_write_image (png, rows); png_write_end (png, info); png_destroy_write_struct (&png, &info); free (rows); fclose (file); return STATUS_SUCCESS; } @ 1.1.1.1 log @Initial import of ictest @ text @@