Blame src/gdxpm.c

Packit ed3af9
/*
Packit ed3af9
 * Add ability to load xpm files to gd, requires the xpm
Packit ed3af9
 * library.
Packit ed3af9
 * Caolan.McNamara@ul.ie
Packit ed3af9
 * http://www.csn.ul.ie/~caolan
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
Packit ed3af9
/**
Packit ed3af9
 * File: XPM Input
Packit ed3af9
 *
Packit ed3af9
 * Read XPM images.
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
Packit ed3af9
#ifdef HAVE_CONFIG_H
Packit ed3af9
#	include "config.h"
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#include <stdio.h>
Packit ed3af9
#include <stdlib.h>
Packit ed3af9
#include <string.h>
Packit ed3af9
#include "gd.h"
Packit ed3af9
#include "gdhelpers.h"
Packit ed3af9
#include "gd_color_map.h"
Packit ed3af9
#include "gd_errors.h"
Packit ed3af9
Packit ed3af9
#ifndef HAVE_LIBXPM
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreateFromXpm(char *filename)
Packit ed3af9
{
Packit ed3af9
	(void)filename;
Packit ed3af9
	gd_error_ex(GD_ERROR, "libgd was not built with xpm support\n");
Packit ed3af9
	return NULL;
Packit ed3af9
}
Packit ed3af9
#else
Packit ed3af9
Packit ed3af9
#include <X11/xpm.h>
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
  Function: gdImageCreateFromXpm
Packit ed3af9
Packit ed3af9
    <gdImageCreateFromXbm> is called to load images from XPM X Window
Packit ed3af9
    System color bitmap format files. This function is available only
Packit ed3af9
    if HAVE_XPM is selected in the Makefile and the Xpm library is
Packit ed3af9
    linked with the application. Unlike most gd file functions, the
Packit ed3af9
    Xpm functions *require filenames*, not file
Packit ed3af9
    pointers. <gdImageCreateFromXpm> returns a <gdImagePtr> to the new
Packit ed3af9
    image, or NULL if unable to load the image (most often because the
Packit ed3af9
    file is corrupt or does not contain an XPM bitmap format
Packit ed3af9
    image). You can inspect the sx and sy members of the image to
Packit ed3af9
    determine its size. The image must eventually be destroyed using
Packit ed3af9
    <gdImageDestroy>.
Packit ed3af9
Packit ed3af9
  Parameters:
Packit ed3af9
Packit ed3af9
    filename - The input filename (*not* FILE pointer)
Packit ed3af9
Packit ed3af9
  Returns:
Packit ed3af9
Packit ed3af9
    A pointer to the new image or NULL if an error occurred.
Packit ed3af9
Packit ed3af9
  Example:
Packit ed3af9
    (start code)
Packit ed3af9
Packit ed3af9
    gdImagePtr im;
Packit ed3af9
    FILE *in;
Packit ed3af9
    in = fopen("myxpm.xpm", "rb");
Packit ed3af9
    im = gdImageCreateFromXpm(in);
Packit ed3af9
    fclose(in);
Packit ed3af9
    // ... Use the image ...
Packit ed3af9
    gdImageDestroy(im);
Packit ed3af9
Packit ed3af9
    (end code)
Packit ed3af9
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(gdImagePtr) gdImageCreateFromXpm(char *filename)
Packit ed3af9
{
Packit ed3af9
	XpmInfo info;
Packit ed3af9
	XpmImage image;
Packit ed3af9
	unsigned int i, j, k, number, len;
Packit ed3af9
	char buf[5];
Packit ed3af9
	gdImagePtr im = 0;
Packit ed3af9
	int *pointer;
Packit ed3af9
	int red = 0, green = 0, blue = 0;
Packit ed3af9
	int *colors;
Packit ed3af9
	int ret;
Packit ed3af9
Packit ed3af9
	ret = XpmReadFileToXpmImage(filename, &image, &info;;
Packit ed3af9
	if(ret != XpmSuccess) {
Packit ed3af9
		return 0;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	number = image.ncolors;
Packit ed3af9
	if(overflow2(sizeof(int), number)) {
Packit ed3af9
		goto done;
Packit ed3af9
	}
Packit ed3af9
	for(i = 0; i < number; i++) {
Packit ed3af9
		/*
Packit ed3af9
		   avoid NULL pointer dereference
Packit ed3af9
		   TODO better fix need to manage monochrome/monovisual
Packit ed3af9
		   see m_color or g4_color or g_color
Packit ed3af9
		*/
Packit ed3af9
		if (!image.colorTable[i].c_color) {
Packit ed3af9
			goto done;
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	colors = (int *)gdMalloc(sizeof(int) * number);
Packit ed3af9
	if(colors == NULL) {
Packit ed3af9
		goto done;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if(!(im = gdImageCreate(image.width, image.height))) {
Packit ed3af9
		gdFree(colors);
Packit ed3af9
		goto done;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	for(i = 0; i < number; i++) {
Packit ed3af9
		char *c_color = image.colorTable[i].c_color;
Packit ed3af9
		if(strcmp(c_color, "None") == 0) {
Packit ed3af9
			colors[i] = gdImageGetTransparent(im);
Packit ed3af9
			if(colors[i] == -1) colors[i] = gdImageColorAllocate(im, 0, 0, 0);
Packit ed3af9
			if(colors[i] != -1) gdImageColorTransparent(im, colors[i]);
Packit ed3af9
			continue;
Packit ed3af9
		}
Packit ed3af9
		len = strlen(c_color);
Packit ed3af9
		if(len < 1) continue;
Packit ed3af9
		if(c_color[0] == '#') {
Packit ed3af9
			switch(len) {
Packit ed3af9
			case 4:
Packit ed3af9
				buf[2] = '\0';
Packit ed3af9
				buf[0] = buf[1] = c_color[1];
Packit ed3af9
				red = strtol(buf, NULL, 16);
Packit ed3af9
Packit ed3af9
				buf[0] = buf[1] = c_color[2];
Packit ed3af9
				green = strtol(buf, NULL, 16);
Packit ed3af9
Packit ed3af9
				buf[0] = buf[1] = c_color[3];
Packit ed3af9
				blue = strtol(buf, NULL, 16);
Packit ed3af9
				break;
Packit ed3af9
Packit ed3af9
			case 7:
Packit ed3af9
				buf[2] = '\0';
Packit ed3af9
				buf[0] = c_color[1];
Packit ed3af9
				buf[1] = c_color[2];
Packit ed3af9
				red = strtol(buf, NULL, 16);
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[3];
Packit ed3af9
				buf[1] = c_color[4];
Packit ed3af9
				green = strtol(buf, NULL, 16);
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[5];
Packit ed3af9
				buf[1] = c_color[6];
Packit ed3af9
				blue = strtol(buf, NULL, 16);
Packit ed3af9
				break;
Packit ed3af9
Packit ed3af9
			case 10:
Packit ed3af9
				buf[3] = '\0';
Packit ed3af9
				buf[0] = c_color[1];
Packit ed3af9
				buf[1] = c_color[2];
Packit ed3af9
				buf[2] = c_color[3];
Packit ed3af9
				red = strtol(buf, NULL, 16);
Packit ed3af9
				red /= 64;
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[4];
Packit ed3af9
				buf[1] = c_color[5];
Packit ed3af9
				buf[2] = c_color[6];
Packit ed3af9
				green = strtol(buf, NULL, 16);
Packit ed3af9
				green /= 64;
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[7];
Packit ed3af9
				buf[1] = c_color[8];
Packit ed3af9
				buf[2] = c_color[9];
Packit ed3af9
				blue = strtol(buf, NULL, 16);
Packit ed3af9
				blue /= 64;
Packit ed3af9
				break;
Packit ed3af9
Packit ed3af9
			case 13:
Packit ed3af9
				buf[4] = '\0';
Packit ed3af9
				buf[0] = c_color[1];
Packit ed3af9
				buf[1] = c_color[2];
Packit ed3af9
				buf[2] = c_color[3];
Packit ed3af9
				buf[3] = c_color[4];
Packit ed3af9
				red = strtol(buf, NULL, 16);
Packit ed3af9
				red /= 256;
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[5];
Packit ed3af9
				buf[1] = c_color[6];
Packit ed3af9
				buf[2] = c_color[7];
Packit ed3af9
				buf[3] = c_color[8];
Packit ed3af9
				green = strtol(buf, NULL, 16);
Packit ed3af9
				green /= 256;
Packit ed3af9
Packit ed3af9
				buf[0] = c_color[9];
Packit ed3af9
				buf[1] = c_color[10];
Packit ed3af9
				buf[2] = c_color[11];
Packit ed3af9
				buf[3] = c_color[12];
Packit ed3af9
				blue = strtol(buf, NULL, 16);
Packit ed3af9
				blue /= 256;
Packit ed3af9
				break;
Packit ed3af9
			}
Packit ed3af9
		} else if(!gdColorMapLookup(GD_COLOR_MAP_X11, c_color, &red, &green, &blue)) {
Packit ed3af9
			continue;
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		colors[i] = gdImageColorResolve(im, red, green, blue);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	pointer = (int *)image.data;
Packit ed3af9
Packit ed3af9
	for(i = 0; i < image.height; i++) {
Packit ed3af9
		for(j = 0; j < image.width; j++) {
Packit ed3af9
			k = *pointer++;
Packit ed3af9
			gdImageSetPixel(im, j, i, colors[k]);
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	gdFree(colors);
Packit ed3af9
Packit ed3af9
done:
Packit ed3af9
	XpmFreeXpmImage(&image);
Packit ed3af9
	XpmFreeXpmInfo(&info;;
Packit ed3af9
	return im;
Packit ed3af9
}
Packit ed3af9
#endif /* HAVE_LIBXPM */