Blame src/gdxpm.c

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