+++ /dev/null
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <stdlib.h>
-#include "gd.h"
-#include "mtables.c"
-
-static void gdImageBrushApply(gdImagePtr im, int x, int y);
-static void gdImageTileApply(gdImagePtr im, int x, int y);
-
-gdImagePtr gdImageCreate(int sx, int sy)
-{
- int i;
- gdImagePtr im;
- im = (gdImage *) calloc(1,sizeof(gdImage));
- /* NOW ROW-MAJOR IN GD 1.3 */
- im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sy);
- im->polyInts = 0;
- im->polyAllocated = 0;
- im->brush = 0;
- im->tile = 0;
- im->style = 0;
- for (i=0; (i<sy); i++) {
- /* NOW ROW-MAJOR IN GD 1.3 */
- im->pixels[i] = (unsigned char *) calloc(
- sx, sizeof(unsigned char));
- }
- im->sx = sx;
- im->sy = sy;
- im->colorsTotal = 0;
- im->transparent = (-1);
- im->interlace = 0;
- return im;
-}
-
-void gdImageDestroy(gdImagePtr im)
-{
- int i;
- for (i=0; (i<im->sy); i++) {
- free(im->pixels[i]);
- }
- free(im->pixels);
- if (im->polyInts) {
- free(im->polyInts);
- }
- if (im->style) {
- free(im->style);
- }
- free(im);
-}
-
-int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
-{
- int i;
- long rd, gd, bd;
- int ct = (-1);
- long mindist = 0;
- for (i=0; (i<(im->colorsTotal)); i++) {
- long dist;
- if (im->open[i]) {
- continue;
- }
- rd = (im->red[i] - r);
- gd = (im->green[i] - g);
- bd = (im->blue[i] - b);
- dist = rd * rd + gd * gd + bd * bd;
- if ((i == 0) || (dist < mindist)) {
- mindist = dist;
- ct = i;
- }
- }
- return ct;
-}
-
-int gdImageColorExact(gdImagePtr im, int r, int g, int b)
-{
- int i;
- for (i=0; (i<(im->colorsTotal)); i++) {
- if (im->open[i]) {
- continue;
- }
- if ((im->red[i] == r) &&
- (im->green[i] == g) &&
- (im->blue[i] == b)) {
- return i;
- }
- }
- return -1;
-}
-
-int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
-{
- int i;
- int ct = (-1);
- for (i=0; (i<(im->colorsTotal)); i++) {
- if (im->open[i]) {
- ct = i;
- break;
- }
- }
- if (ct == (-1)) {
- ct = im->colorsTotal;
- if (ct == gdMaxColors) {
- return -1;
- }
- im->colorsTotal++;
- }
- im->red[ct] = r;
- im->green[ct] = g;
- im->blue[ct] = b;
- im->open[ct] = 0;
- return ct;
-}
-
-void gdImageColorDeallocate(gdImagePtr im, int color)
-{
- /* Mark it open. */
- im->open[color] = 1;
-}
-
-void gdImageColorTransparent(gdImagePtr im, int color)
-{
- im->transparent = color;
-}
-
-void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
-{
- int p;
- switch(color) {
- case gdStyled:
- if (!im->style) {
- /* Refuse to draw if no style is set. */
- return;
- } else {
- p = im->style[im->stylePos++];
- }
- if (p != (gdTransparent)) {
- gdImageSetPixel(im, x, y, p);
- }
- im->stylePos = im->stylePos % im->styleLength;
- break;
- case gdStyledBrushed:
- if (!im->style) {
- /* Refuse to draw if no style is set. */
- return;
- }
- p = im->style[im->stylePos++];
- if ((p != gdTransparent) && (p != 0)) {
- gdImageSetPixel(im, x, y, gdBrushed);
- }
- im->stylePos = im->stylePos % im->styleLength;
- break;
- case gdBrushed:
- gdImageBrushApply(im, x, y);
- break;
- case gdTiled:
- gdImageTileApply(im, x, y);
- break;
- default:
- if (gdImageBoundsSafe(im, x, y)) {
- /* NOW ROW-MAJOR IN GD 1.3 */
- im->pixels[y][x] = color;
- }
- break;
- }
-}
-
-static void gdImageBrushApply(gdImagePtr im, int x, int y)
-{
- int lx, ly;
- int hy;
- int hx;
- int x1, y1, x2, y2;
- int srcx, srcy;
- if (!im->brush) {
- return;
- }
- hy = gdImageSY(im->brush)/2;
- y1 = y - hy;
- y2 = y1 + gdImageSY(im->brush);
- hx = gdImageSX(im->brush)/2;
- x1 = x - hx;
- x2 = x1 + gdImageSX(im->brush);
- srcy = 0;
- for (ly = y1; (ly < y2); ly++) {
- srcx = 0;
- for (lx = x1; (lx < x2); lx++) {
- int p;
- p = gdImageGetPixel(im->brush, srcx, srcy);
- /* Allow for non-square brushes! */
- if (p != gdImageGetTransparent(im->brush)) {
- gdImageSetPixel(im, lx, ly,
- im->brushColorMap[p]);
- }
- srcx++;
- }
- srcy++;
- }
-}
-
-static void gdImageTileApply(gdImagePtr im, int x, int y)
-{
- int srcx, srcy;
- int p;
- if (!im->tile) {
- return;
- }
- srcx = x % gdImageSX(im->tile);
- srcy = y % gdImageSY(im->tile);
- p = gdImageGetPixel(im->tile, srcx, srcy);
- /* Allow for transparency */
- if (p != gdImageGetTransparent(im->tile)) {
- gdImageSetPixel(im, x, y,
- im->tileColorMap[p]);
- }
-}
-
-int gdImageGetPixel(gdImagePtr im, int x, int y)
-{
- if (gdImageBoundsSafe(im, x, y)) {
- /* NOW ROW-MAJOR IN GD 1.3 */
- return im->pixels[y][x];
- } else {
- return 0;
- }
-}
-
-/* Bresenham as presented in Foley & Van Dam */
-
-void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
-{
- int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
- dx = abs(x2-x1);
- dy = abs(y2-y1);
- if (dy <= dx) {
- d = 2*dy - dx;
- incr1 = 2*dy;
- incr2 = 2 * (dy - dx);
- if (x1 > x2) {
- x = x2;
- y = y2;
- ydirflag = (-1);
- xend = x1;
- } else {
- x = x1;
- y = y1;
- ydirflag = 1;
- xend = x2;
- }
- gdImageSetPixel(im, x, y, color);
- if (((y2 - y1) * ydirflag) > 0) {
- while (x < xend) {
- x++;
- if (d <0) {
- d+=incr1;
- } else {
- y++;
- d+=incr2;
- }
- gdImageSetPixel(im, x, y, color);
- }
- } else {
- while (x < xend) {
- x++;
- if (d <0) {
- d+=incr1;
- } else {
- y--;
- d+=incr2;
- }
- gdImageSetPixel(im, x, y, color);
- }
- }
- } else {
- d = 2*dx - dy;
- incr1 = 2*dx;
- incr2 = 2 * (dx - dy);
- if (y1 > y2) {
- y = y2;
- x = x2;
- yend = y1;
- xdirflag = (-1);
- } else {
- y = y1;
- x = x1;
- yend = y2;
- xdirflag = 1;
- }
- gdImageSetPixel(im, x, y, color);
- if (((x2 - x1) * xdirflag) > 0) {
- while (y < yend) {
- y++;
- if (d <0) {
- d+=incr1;
- } else {
- x++;
- d+=incr2;
- }
- gdImageSetPixel(im, x, y, color);
- }
- } else {
- while (y < yend) {
- y++;
- if (d <0) {
- d+=incr1;
- } else {
- x--;
- d+=incr2;
- }
- gdImageSetPixel(im, x, y, color);
- }
- }
- }
-}
-
-static void dashedSet(gdImagePtr im, int x, int y, int color,
- int *onP, int *dashStepP);
-
-void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
-{
- int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
- int dashStep = 0;
- int on = 1;
- dx = abs(x2-x1);
- dy = abs(y2-y1);
- if (dy <= dx) {
- d = 2*dy - dx;
- incr1 = 2*dy;
- incr2 = 2 * (dy - dx);
- if (x1 > x2) {
- x = x2;
- y = y2;
- ydirflag = (-1);
- xend = x1;
- } else {
- x = x1;
- y = y1;
- ydirflag = 1;
- xend = x2;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- if (((y2 - y1) * ydirflag) > 0) {
- while (x < xend) {
- x++;
- if (d <0) {
- d+=incr1;
- } else {
- y++;
- d+=incr2;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- }
- } else {
- while (x < xend) {
- x++;
- if (d <0) {
- d+=incr1;
- } else {
- y--;
- d+=incr2;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- }
- }
- } else {
- d = 2*dx - dy;
- incr1 = 2*dx;
- incr2 = 2 * (dx - dy);
- if (y1 > y2) {
- y = y2;
- x = x2;
- yend = y1;
- xdirflag = (-1);
- } else {
- y = y1;
- x = x1;
- yend = y2;
- xdirflag = 1;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- if (((x2 - x1) * xdirflag) > 0) {
- while (y < yend) {
- y++;
- if (d <0) {
- d+=incr1;
- } else {
- x++;
- d+=incr2;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- }
- } else {
- while (y < yend) {
- y++;
- if (d <0) {
- d+=incr1;
- } else {
- x--;
- d+=incr2;
- }
- dashedSet(im, x, y, color, &on, &dashStep);
- }
- }
- }
-}
-
-static void dashedSet(gdImagePtr im, int x, int y, int color,
- int *onP, int *dashStepP)
-{
- int dashStep = *dashStepP;
- int on = *onP;
- dashStep++;
- if (dashStep == gdDashSize) {
- dashStep = 0;
- on = !on;
- }
- if (on) {
- gdImageSetPixel(im, x, y, color);
- }
- *dashStepP = dashStep;
- *onP = on;
-}
-
-
-int gdImageBoundsSafe(gdImagePtr im, int x, int y)
-{
- return (!(((y < 0) || (y >= im->sy)) ||
- ((x < 0) || (x >= im->sx))));
-}
-
-void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y,
- int c, int color)
-{
- int cx, cy;
- int px, py;
- int fline;
- cx = 0;
- cy = 0;
- if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
- return;
- }
- fline = (c - f->offset) * f->h * f->w;
- for (py = y; (py < (y + f->h)); py++) {
- for (px = x; (px < (x + f->w)); px++) {
- if (f->data[fline + cy * f->w + cx]) {
- gdImageSetPixel(im, px, py, color);
- }
- cx++;
- }
- cx = 0;
- cy++;
- }
-}
-
-void gdImageCharUp(gdImagePtr im, gdFontPtr f,
- int x, int y, int c, int color)
-{
- int cx, cy;
- int px, py;
- int fline;
- cx = 0;
- cy = 0;
- if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
- return;
- }
- fline = (c - f->offset) * f->h * f->w;
- for (py = y; (py > (y - f->w)); py--) {
- for (px = x; (px < (x + f->h)); px++) {
- if (f->data[fline + cy * f->w + cx]) {
- gdImageSetPixel(im, px, py, color);
- }
- cy++;
- }
- cy = 0;
- cx++;
- }
-}
-
-void gdImageString(gdImagePtr im, gdFontPtr f,
- int x, int y, unsigned char *s, int color)
-{
- int i;
- int l;
- l = strlen(s);
- for (i=0; (i<l); i++) {
- gdImageChar(im, f, x, y, s[i], color);
- x += f->w;
- }
-}
-
-void gdImageStringUp(gdImagePtr im, gdFontPtr f,
- int x, int y, unsigned char *s, int color)
-{
- int i;
- int l;
- l = strlen(s);
- for (i=0; (i<l); i++) {
- gdImageCharUp(im, f, x, y, s[i], color);
- y -= f->w;
- }
-}
-
-static int strlen16(unsigned short *s);
-
-void gdImageString16(gdImagePtr im, gdFontPtr f,
- int x, int y, unsigned short *s, int color)
-{
- int i;
- int l;
- l = strlen16(s);
- for (i=0; (i<l); i++) {
- gdImageChar(im, f, x, y, s[i], color);
- x += f->w;
- }
-}
-
-void gdImageStringUp16(gdImagePtr im, gdFontPtr f,
- int x, int y, unsigned short *s, int color)
-{
- int i;
- int l;
- l = strlen16(s);
- for (i=0; (i<l); i++) {
- gdImageCharUp(im, f, x, y, s[i], color);
- y -= f->w;
- }
-}
-
-static int strlen16(unsigned short *s)
-{
- int len = 0;
- while (*s) {
- s++;
- len++;
- }
- return len;
-}
-
-/* s and e are integers modulo 360 (degrees), with 0 degrees
- being the rightmost extreme and degrees changing clockwise.
- cx and cy are the center in pixels; w and h are the horizontal
- and vertical diameter in pixels. Nice interface, but slow, since
- I don't yet use Bresenham (I'm using an inefficient but
- simple solution with too much work going on in it; generalizing
- Bresenham to ellipses and partial arcs of ellipses is non-trivial,
- at least for me) and there are other inefficiencies (small circles
- do far too much work). */
-
-void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
-{
- int i;
- int lx = 0, ly = 0;
- int w2, h2;
- w2 = w/2;
- h2 = h/2;
- while (e < s) {
- e += 360;
- }
- for (i=s; (i <= e); i++) {
- int x, y;
- x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
- y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
- if (i != s) {
- gdImageLine(im, lx, ly, x, y, color);
- }
- lx = x;
- ly = y;
- }
-}
-
-
-#if 0
- /* Bresenham octant code, which I should use eventually */
- int x, y, d;
- x = 0;
- y = w;
- d = 3-2*w;
- while (x < y) {
- gdImageSetPixel(im, cx+x, cy+y, color);
- if (d < 0) {
- d += 4 * x + 6;
- } else {
- d += 4 * (x - y) + 10;
- y--;
- }
- x++;
- }
- if (x == y) {
- gdImageSetPixel(im, cx+x, cy+y, color);
- }
-#endif
-
-void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
-{
- int lastBorder;
- /* Seek left */
- int leftLimit, rightLimit;
- int i;
- leftLimit = (-1);
- if (border < 0) {
- /* Refuse to fill to a non-solid border */
- return;
- }
- for (i = x; (i >= 0); i--) {
- if (gdImageGetPixel(im, i, y) == border) {
- break;
- }
- gdImageSetPixel(im, i, y, color);
- leftLimit = i;
- }
- if (leftLimit == (-1)) {
- return;
- }
- /* Seek right */
- rightLimit = x;
- for (i = (x+1); (i < im->sx); i++) {
- if (gdImageGetPixel(im, i, y) == border) {
- break;
- }
- gdImageSetPixel(im, i, y, color);
- rightLimit = i;
- }
- /* Look at lines above and below and start paints */
- /* Above */
- if (y > 0) {
- lastBorder = 1;
- for (i = leftLimit; (i <= rightLimit); i++) {
- int c;
- c = gdImageGetPixel(im, i, y-1);
- if (lastBorder) {
- if ((c != border) && (c != color)) {
- gdImageFillToBorder(im, i, y-1,
- border, color);
- lastBorder = 0;
- }
- } else if ((c == border) || (c == color)) {
- lastBorder = 1;
- }
- }
- }
- /* Below */
- if (y < ((im->sy) - 1)) {
- lastBorder = 1;
- for (i = leftLimit; (i <= rightLimit); i++) {
- int c;
- c = gdImageGetPixel(im, i, y+1);
- if (lastBorder) {
- if ((c != border) && (c != color)) {
- gdImageFillToBorder(im, i, y+1,
- border, color);
- lastBorder = 0;
- }
- } else if ((c == border) || (c == color)) {
- lastBorder = 1;
- }
- }
- }
-}
-
-void gdImageFill(gdImagePtr im, int x, int y, int color)
-{
- int lastBorder;
- int old;
- int leftLimit, rightLimit;
- int i;
- old = gdImageGetPixel(im, x, y);
- if (color == gdTiled) {
- /* Tile fill -- got to watch out! */
- int p, tileColor;
- int srcx, srcy;
- if (!im->tile) {
- return;
- }
- /* Refuse to flood-fill with a transparent pattern --
- I can't do it without allocating another image */
- if (gdImageGetTransparent(im->tile) != (-1)) {
- return;
- }
- srcx = x % gdImageSX(im->tile);
- srcy = y % gdImageSY(im->tile);
- p = gdImageGetPixel(im->tile, srcx, srcy);
- tileColor = im->tileColorMap[p];
- if (old == tileColor) {
- /* Nothing to be done */
- return;
- }
- } else {
- if (old == color) {
- /* Nothing to be done */
- return;
- }
- }
- /* Seek left */
- leftLimit = (-1);
- for (i = x; (i >= 0); i--) {
- if (gdImageGetPixel(im, i, y) != old) {
- break;
- }
- gdImageSetPixel(im, i, y, color);
- leftLimit = i;
- }
- if (leftLimit == (-1)) {
- return;
- }
- /* Seek right */
- rightLimit = x;
- for (i = (x+1); (i < im->sx); i++) {
- if (gdImageGetPixel(im, i, y) != old) {
- break;
- }
- gdImageSetPixel(im, i, y, color);
- rightLimit = i;
- }
- /* Look at lines above and below and start paints */
- /* Above */
- if (y > 0) {
- lastBorder = 1;
- for (i = leftLimit; (i <= rightLimit); i++) {
- int c;
- c = gdImageGetPixel(im, i, y-1);
- if (lastBorder) {
- if (c == old) {
- gdImageFill(im, i, y-1, color);
- lastBorder = 0;
- }
- } else if (c != old) {
- lastBorder = 1;
- }
- }
- }
- /* Below */
- if (y < ((im->sy) - 1)) {
- lastBorder = 1;
- for (i = leftLimit; (i <= rightLimit); i++) {
- int c;
- c = gdImageGetPixel(im, i, y+1);
- if (lastBorder) {
- if (c == old) {
- gdImageFill(im, i, y+1, color);
- lastBorder = 0;
- }
- } else if (c != old) {
- lastBorder = 1;
- }
- }
- }
-}
-
-/* Code drawn from ppmtogif.c, from the pbmplus package
-**
-** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
-** Lempel-Zim compression based on "compress".
-**
-** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
-**
-** Copyright (C) 1989 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation. This software is provided "as is" without express or
-** implied warranty.
-**
-** The Graphics Interchange Format(c) is the Copyright property of
-** CompuServe Incorporated. GIF(sm) is a Service Mark property of
-** CompuServe Incorporated.
-*
-* Heavily modified by Mouse, 1998-02-12.
-* Remove LZW compression.
-* Added miGIF run length compression.
-*
-*/
-
-/*
- * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
- */
-typedef int code_int;
-
-static int colorstobpp(int colors);
-static void BumpPixel (void);
-static int GIFNextPixel (gdImagePtr im);
-static void GIFEncode (FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
-static void Putword (int w, FILE *fp);
-static void compress (int, FILE *, gdImagePtr, int);
-static void output (code_int code);
-/* Allows for reuse */
-static void init_statics(void);
-
-void gdImageGif(gdImagePtr im, FILE *out)
-{
- int interlace, transparent, BitsPerPixel;
- interlace = im->interlace;
- transparent = im->transparent;
-
- BitsPerPixel = colorstobpp(im->colorsTotal);
- /* Clear any old values in statics strewn through the GIF code */
- init_statics();
- /* All set, let's do it. */
- GIFEncode(
- out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
- im->red, im->green, im->blue, im);
-}
-
-static int
-colorstobpp(int colors)
-{
- int bpp = 0;
-
- if ( colors <= 2 )
- bpp = 1;
- else if ( colors <= 4 )
- bpp = 2;
- else if ( colors <= 8 )
- bpp = 3;
- else if ( colors <= 16 )
- bpp = 4;
- else if ( colors <= 32 )
- bpp = 5;
- else if ( colors <= 64 )
- bpp = 6;
- else if ( colors <= 128 )
- bpp = 7;
- else if ( colors <= 256 )
- bpp = 8;
- return bpp;
- }
-
-/*****************************************************************************
- *
- * GIFENCODE.C - GIF Image compression interface
- *
- * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
- * BitsPerPixel, Red, Green, Blue, gdImagePtr )
- *
- *****************************************************************************/
-
-#define TRUE 1
-#define FALSE 0
-
-static int Width, Height;
-static int curx, cury;
-static long CountDown;
-static int Pass = 0;
-static int Interlace;
-
-/*
- * Bump the 'curx' and 'cury' to point to the next pixel
- */
-static void
-BumpPixel(void)
-{
- /*
- * Bump the current X position
- */
- ++curx;
-
- /*
- * If we are at the end of a scan line, set curx back to the beginning
- * If we are interlaced, bump the cury to the appropriate spot,
- * otherwise, just increment it.
- */
- if( curx == Width ) {
- curx = 0;
-
- if( !Interlace )
- ++cury;
- else {
- switch( Pass ) {
-
- case 0:
- cury += 8;
- if( cury >= Height ) {
- ++Pass;
- cury = 4;
- }
- break;
-
- case 1:
- cury += 8;
- if( cury >= Height ) {
- ++Pass;
- cury = 2;
- }
- break;
-
- case 2:
- cury += 4;
- if( cury >= Height ) {
- ++Pass;
- cury = 1;
- }
- break;
-
- case 3:
- cury += 2;
- break;
- }
- }
- }
-}
-
-/*
- * Return the next pixel from the image
- */
-static int
-GIFNextPixel(gdImagePtr im)
-{
- int r;
-
- if( CountDown == 0 )
- return EOF;
-
- --CountDown;
-
- r = gdImageGetPixel(im, curx, cury);
-
- BumpPixel();
-
- return r;
-}
-
-/* public */
-
-static void
-GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
-{
- int B;
- int RWidth, RHeight;
- int LeftOfs, TopOfs;
- int Resolution;
- int ColorMapSize;
- int InitCodeSize;
- int i;
-
- Interlace = GInterlace;
-
- ColorMapSize = 1 << BitsPerPixel;
-
- RWidth = Width = GWidth;
- RHeight = Height = GHeight;
- LeftOfs = TopOfs = 0;
-
- Resolution = BitsPerPixel;
-
- /*
- * Calculate number of bits we are expecting
- */
- CountDown = (long)Width * (long)Height;
-
- /*
- * Indicate which pass we are on (if interlace)
- */
- Pass = 0;
-
- /*
- * The initial code size
- */
- if( BitsPerPixel <= 1 )
- InitCodeSize = 2;
- else
- InitCodeSize = BitsPerPixel;
-
- /*
- * Set up the current x and y position
- */
- curx = cury = 0;
-
- /*
- * Write the Magic header
- */
- fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
-
- /*
- * Write out the screen width and height
- */
- Putword( RWidth, fp );
- Putword( RHeight, fp );
-
- /*
- * Indicate that there is a global colour map
- */
- B = 0x80; /* Yes, there is a color map */
-
- /*
- * OR in the resolution
- */
- B |= (Resolution - 1) << 4;
-
- /*
- * OR in the Bits per Pixel
- */
- B |= (BitsPerPixel - 1);
-
- /*
- * Write it out
- */
- fputc( B, fp );
-
- /*
- * Write out the Background colour
- */
- fputc( Background, fp );
-
- /*
- * Byte of 0's (future expansion)
- */
- fputc( 0, fp );
-
- /*
- * Write out the Global Colour Map
- */
- for( i=0; i<ColorMapSize; ++i ) {
- fputc( Red[i], fp );
- fputc( Green[i], fp );
- fputc( Blue[i], fp );
- }
-
- /*
- * Write out extension for transparent colour index, if necessary.
- */
- if ( Transparent >= 0 ) {
- fputc( '!', fp );
- fputc( 0xf9, fp );
- fputc( 4, fp );
- fputc( 1, fp );
- fputc( 0, fp );
- fputc( 0, fp );
- fputc( (unsigned char) Transparent, fp );
- fputc( 0, fp );
- }
-
- /*
- * Write an Image separator
- */
- fputc( ',', fp );
-
- /*
- * Write the Image header
- */
-
- Putword( LeftOfs, fp );
- Putword( TopOfs, fp );
- Putword( Width, fp );
- Putword( Height, fp );
-
- /*
- * Write out whether or not the image is interlaced
- */
- if( Interlace )
- fputc( 0x40, fp );
- else
- fputc( 0x00, fp );
-
- /*
- * Write out the initial code size
- */
- fputc( InitCodeSize, fp );
-
- /*
- * Go and actually compress the data
- */
- compress( InitCodeSize+1, fp, im, Background );
-
- /*
- * Write out a Zero-length packet (to end the series)
- */
- fputc( 0, fp );
-
- /*
- * Write the GIF file terminator
- */
- fputc( ';', fp );
-}
-
-/*
- * Write out a word to the GIF file
- */
-static void
-Putword(int w, FILE *fp)
-{
- fputc( w & 0xff, fp );
- fputc( (w / 256) & 0xff, fp );
-}
-
-#define GIFBITS 12
-
-/*-----------------------------------------------------------------------
- *
- * miGIF Compression - mouse and ivo's GIF-compatible compression
- *
- * -run length encoding compression routines-
- *
- * Copyright (C) 1998 Hutchison Avenue Software Corporation
- * http://www.hasc.com
- * info@hasc.com
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. This software is provided "AS IS." The Hutchison Avenue
- * Software Corporation disclaims all warranties, either express or implied,
- * including but not limited to implied warranties of merchantability and
- * fitness for a particular purpose, with respect to this code and accompanying
- * documentation.
- *
- * The miGIF compression routines do not, strictly speaking, generate files
- * conforming to the GIF spec, since the image data is not LZW-compressed
- * (this is the point: in order to avoid transgression of the Unisys patent
- * on the LZW algorithm.) However, miGIF generates data streams that any
- * reasonably sane LZW decompresser will decompress to what we want.
- *
- * miGIF compression uses run length encoding. It compresses horizontal runs
- * of pixels of the same color. This type of compression gives good results
- * on images with many runs, for example images with lines, text and solid
- * shapes on a solid-colored background. It gives little or no compression
- * on images with few runs, for example digital or scanned photos.
- *
- * der Mouse
- * mouse@rodents.montreal.qc.ca
- * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
- *
- * ivo@hasc.com
- *
- * The Graphics Interchange Format(c) is the Copyright property of
- * CompuServe Incorporated. GIF(sm) is a Service Mark property of
- * CompuServe Incorporated.
- *
- */
-
-static int rl_pixel;
-static int rl_basecode;
-static int rl_count;
-static int rl_table_pixel;
-static int rl_table_max;
-static int just_cleared;
-static int out_bits;
-static int out_bits_init;
-static int out_count;
-static int out_bump;
-static int out_bump_init;
-static int out_clear;
-static int out_clear_init;
-static int max_ocodes;
-static int code_clear;
-static int code_eof;
-static unsigned int obuf;
-static int obits;
-static FILE *ofile;
-static unsigned char oblock[256];
-static int oblen;
-
-/* Used only when debugging GIF compression code */
-/* #define DEBUGGING_ENVARS */
-
-#ifdef DEBUGGING_ENVARS
-
-static int verbose_set = 0;
-static int verbose;
-#define VERBOSE (verbose_set?verbose:set_verbose())
-
-static int set_verbose(void)
-{
- verbose = !!getenv("GIF_VERBOSE");
- verbose_set = 1;
- return(verbose);
-}
-
-#else
-
-#define VERBOSE 0
-
-#endif
-
-
-static const char *binformat(unsigned int v, int nbits)
-{
- static char bufs[8][64];
- static int bhand = 0;
- unsigned int bit;
- int bno;
- char *bp;
-
- bhand --;
- if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
- bp = &bufs[bhand][0];
- for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1)
- { *bp++ = (v & bit) ? '1' : '0';
- if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
- }
- *bp = '\0';
- return(&bufs[bhand][0]);
-}
-
-static void write_block(void)
-{
- int i;
-
- if (VERBOSE)
- { printf("write_block %d:",oblen);
- for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
- printf("\n");
- }
- fputc(oblen,ofile);
- fwrite(&oblock[0],1,oblen,ofile);
- oblen = 0;
-}
-
-static void block_out(unsigned char c)
-{
- if (VERBOSE) printf("block_out %s\n",binformat(c,8));
- oblock[oblen++] = c;
- if (oblen >= 255) write_block();
-}
-
-static void block_flush(void)
-{
- if (VERBOSE) printf("block_flush\n");
- if (oblen > 0) write_block();
-}
-
-static void output(int val)
-{
- if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
- obuf |= val << obits;
- obits += out_bits;
- while (obits >= 8)
- { block_out(obuf&0xff);
- obuf >>= 8;
- obits -= 8;
- }
- if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
-}
-
-static void output_flush(void)
-{
- if (VERBOSE) printf("output_flush\n");
- if (obits > 0) block_out(obuf);
- block_flush();
-}
-
-static void did_clear(void)
-{
- if (VERBOSE) printf("did_clear\n");
- out_bits = out_bits_init;
- out_bump = out_bump_init;
- out_clear = out_clear_init;
- out_count = 0;
- rl_table_max = 0;
- just_cleared = 1;
-}
-
-static void output_plain(int c)
-{
- if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
- just_cleared = 0;
- output(c);
- out_count ++;
- if (out_count >= out_bump)
- { out_bits ++;
- out_bump += 1 << (out_bits - 1);
- }
- if (out_count >= out_clear)
- { output(code_clear);
- did_clear();
- }
-}
-
-static unsigned int isqrt(unsigned int x)
-{
- unsigned int r;
- unsigned int v;
-
- if (x < 2) return(x);
- for (v=x,r=1;v;v>>=2,r<<=1) ;
- while (1)
- { v = ((x / r) + r) / 2;
- if ((v == r) || (v == r+1)) return(r);
- r = v;
- }
-}
-
-static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes)
-{
- unsigned int perrep;
- unsigned int ncost;
-
- ncost = 0;
- perrep = (nrepcodes * (nrepcodes+1)) / 2;
- while (count >= perrep)
- { ncost += nrepcodes;
- count -= perrep;
- }
- if (count > 0)
- { unsigned int n;
- n = isqrt(count);
- while ((n*(n+1)) >= 2*count) n --;
- while ((n*(n+1)) < 2*count) n ++;
- ncost += n;
- }
- return(ncost);
-}
-
-static void max_out_clear(void)
-{
- out_clear = max_ocodes;
-}
-
-static void reset_out_clear(void)
-{
- out_clear = out_clear_init;
- if (out_count >= out_clear)
- { output(code_clear);
- did_clear();
- }
-}
-
-static void rl_flush_fromclear(int count)
-{
- int n;
-
- if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
- max_out_clear();
- rl_table_pixel = rl_pixel;
- n = 1;
- while (count > 0)
- { if (n == 1)
- { rl_table_max = 1;
- output_plain(rl_pixel);
- count --;
- }
- else if (count >= n)
- { rl_table_max = n;
- output_plain(rl_basecode+n-2);
- count -= n;
- }
- else if (count == 1)
- { rl_table_max ++;
- output_plain(rl_pixel);
- count = 0;
- }
- else
- { rl_table_max ++;
- output_plain(rl_basecode+count-2);
- count = 0;
- }
- if (out_count == 0) n = 1; else n ++;
- }
- reset_out_clear();
- if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
-}
-
-static void rl_flush_clearorrep(int count)
-{
- int withclr;
-
- if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
- withclr = 1 + compute_triangle_count(count,max_ocodes);
- if (withclr < count)
- { output(code_clear);
- did_clear();
- rl_flush_fromclear(count);
- }
- else
- { for (;count>0;count--) output_plain(rl_pixel);
- }
-}
-
-static void rl_flush_withtable(int count)
-{
- int repmax;
- int repleft;
- int leftover;
-
- if (VERBOSE) printf("rl_flush_withtable %d\n",count);
- repmax = count / rl_table_max;
- leftover = count % rl_table_max;
- repleft = (leftover ? 1 : 0);
- if (out_count+repmax+repleft > max_ocodes)
- { repmax = max_ocodes - out_count;
- leftover = count - (repmax * rl_table_max);
- repleft = 1 + compute_triangle_count(leftover,max_ocodes);
- }
- if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
- if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
- { output(code_clear);
- did_clear();
- rl_flush_fromclear(count);
- return;
- }
- max_out_clear();
- for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
- if (leftover)
- { if (just_cleared)
- { rl_flush_fromclear(leftover);
- }
- else if (leftover == 1)
- { output_plain(rl_pixel);
- }
- else
- { output_plain(rl_basecode+leftover-2);
- }
- }
- reset_out_clear();
-}
-
-static void rl_flush(void)
-{
-
- if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
- if (rl_count == 1)
- { output_plain(rl_pixel);
- rl_count = 0;
- if (VERBOSE) printf("rl_flush ]\n");
- return;
- }
- if (just_cleared)
- { rl_flush_fromclear(rl_count);
- }
- else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
- { rl_flush_clearorrep(rl_count);
- }
- else
- { rl_flush_withtable(rl_count);
- }
- if (VERBOSE) printf("rl_flush ]\n");
- rl_count = 0;
-}
-
-static void compress(int init_bits, FILE *outfile, gdImagePtr im, int background)
-{
- int c;
-
- ofile = outfile;
- obuf = 0;
- obits = 0;
- oblen = 0;
- code_clear = 1 << (init_bits - 1);
- code_eof = code_clear + 1;
- rl_basecode = code_eof + 1;
- out_bump_init = (1 << (init_bits - 1)) - 1;
- /* for images with a lot of runs, making out_clear_init larger will
- give better compression. */
- out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
-#ifdef DEBUGGING_ENVARS
- { const char *ocienv;
- ocienv = getenv("GIF_OUT_CLEAR_INIT");
- if (ocienv)
- { out_clear_init = atoi(ocienv);
- if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
- }
- }
-#endif
- out_bits_init = init_bits;
- max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
- did_clear();
- output(code_clear);
- rl_count = 0;
- while (1)
- { c = GIFNextPixel(im);
- if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
- if (c == EOF) break;
- if (rl_pixel == c)
- { rl_count ++;
- }
- else
- { rl_pixel = c;
- rl_count = 1;
- }
- }
- output(code_eof);
- output_flush();
-}
-
-/*-----------------------------------------------------------------------
- *
- * End of miGIF section - See copyright notice at start of section.
- *
- *-----------------------------------------------------------------------
-
-
- ******************************************************************************
- *
- * GIF Specific routines
- *
- ******************************************************************************/
-
-/*
- * Number of characters so far in this 'packet'
- */
-static int a_count;
-
-/*
- * Define the storage for the packet accumulator
- */
-
-static void init_statics(void) {
- /* Some of these are properly initialized later. What I'm doing
- here is making sure code that depends on C's initialization
- of statics doesn't break when the code gets called more
- than once. */
- Width = 0;
- Height = 0;
- curx = 0;
- cury = 0;
- CountDown = 0;
- Pass = 0;
- Interlace = 0;
- a_count = 0;
-}
-
-
-/* +-------------------------------------------------------------------+ */
-/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */
-/* | Permission to use, copy, modify, and distribute this software | */
-/* | and its documentation for any purpose and without fee is hereby | */
-/* | granted, provided that the above copyright notice appear in all | */
-/* | copies and that both that copyright notice and this permission | */
-/* | notice appear in supporting documentation. This software is | */
-/* | provided "as is" without express or implied warranty. | */
-/* +-------------------------------------------------------------------+ */
-
-
-#define MAXCOLORMAPSIZE 256
-
-#define TRUE 1
-#define FALSE 0
-
-#define CM_RED 0
-#define CM_GREEN 1
-#define CM_BLUE 2
-
-#define MAX_LWZ_BITS 12
-
-#define INTERLACE 0x40
-#define LOCALCOLORMAP 0x80
-#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
-
-#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
-
-#define LM_to_uint(a,b) (((b)<<8)|(a))
-
-/* We may eventually want to use this information, but def it out for now */
-#if 0
-static struct {
- unsigned int Width;
- unsigned int Height;
- unsigned char ColorMap[3][MAXCOLORMAPSIZE];
- unsigned int BitPixel;
- unsigned int ColorResolution;
- unsigned int Background;
- unsigned int AspectRatio;
-} GifScreen;
-#endif
-
-int ZeroDataBlock;
-
-
-void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
-{
- gdImageLine(im, x1, y1, x2, y1, color);
- gdImageLine(im, x1, y2, x2, y2, color);
- gdImageLine(im, x1, y1, x1, y2, color);
- gdImageLine(im, x2, y1, x2, y2, color);
-}
-
-void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
-{
- int x, y;
- for (y=y1; (y<=y2); y++) {
- for (x=x1; (x<=x2); x++) {
- gdImageSetPixel(im, x, y, color);
- }
- }
-}
-
-void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
-{
- int c;
- int x, y;
- int tox, toy;
- int i;
- int colorMap[gdMaxColors];
- for (i=0; (i<gdMaxColors); i++) {
- colorMap[i] = (-1);
- }
- toy = dstY;
- for (y=srcY; (y < (srcY + h)); y++) {
- tox = dstX;
- for (x=srcX; (x < (srcX + w)); x++) {
- int nc;
- c = gdImageGetPixel(src, x, y);
- /* Added 7/24/95: support transparent copies */
- if (gdImageGetTransparent(src) == c) {
- tox++;
- continue;
- }
- /* Have we established a mapping for this color? */
- if (colorMap[c] == (-1)) {
- /* If it's the same image, mapping is trivial */
- if (dst == src) {
- nc = c;
- } else {
- /* First look for an exact match */
- nc = gdImageColorExact(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- }
- if (nc == (-1)) {
- /* No, so try to allocate it */
- nc = gdImageColorAllocate(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- /* If we're out of colors, go for the
- closest color */
- if (nc == (-1)) {
- nc = gdImageColorClosest(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- }
- }
- colorMap[c] = nc;
- }
- gdImageSetPixel(dst, tox, toy, colorMap[c]);
- tox++;
- }
- toy++;
- }
-}
-
-void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
-{
- int c;
- int x, y;
- int tox, toy;
- int ydest;
- int i;
- int colorMap[gdMaxColors];
- /* Stretch vectors */
- int *stx;
- int *sty;
- /* We only need to use floating point to determine the correct
- stretch vector for one line's worth. */
- double accum;
- stx = (int *) malloc(sizeof(int) * srcW);
- sty = (int *) malloc(sizeof(int) * srcH);
- accum = 0;
- for (i=0; (i < srcW); i++) {
- int got;
- accum += (double)dstW/(double)srcW;
- got = floor(accum);
- stx[i] = got;
- accum -= got;
- }
- accum = 0;
- for (i=0; (i < srcH); i++) {
- int got;
- accum += (double)dstH/(double)srcH;
- got = floor(accum);
- sty[i] = got;
- accum -= got;
- }
- for (i=0; (i<gdMaxColors); i++) {
- colorMap[i] = (-1);
- }
- toy = dstY;
- for (y=srcY; (y < (srcY + srcH)); y++) {
- for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
- tox = dstX;
- for (x=srcX; (x < (srcX + srcW)); x++) {
- int nc;
- if (!stx[x - srcX]) {
- continue;
- }
- c = gdImageGetPixel(src, x, y);
- /* Added 7/24/95: support transparent copies */
- if (gdImageGetTransparent(src) == c) {
- tox += stx[x-srcX];
- continue;
- }
- /* Have we established a mapping for this color? */
- if (colorMap[c] == (-1)) {
- /* If it's the same image, mapping is trivial */
- if (dst == src) {
- nc = c;
- } else {
- /* First look for an exact match */
- nc = gdImageColorExact(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- }
- if (nc == (-1)) {
- /* No, so try to allocate it */
- nc = gdImageColorAllocate(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- /* If we're out of colors, go for the
- closest color */
- if (nc == (-1)) {
- nc = gdImageColorClosest(dst,
- src->red[c], src->green[c],
- src->blue[c]);
- }
- }
- colorMap[c] = nc;
- }
- for (i=0; (i < stx[x - srcX]); i++) {
- gdImageSetPixel(dst, tox, toy, colorMap[c]);
- tox++;
- }
- }
- toy++;
- }
- }
- free(stx);
- free(sty);
-}
-
-int gdGetWord(int *result, FILE *in)
-{
- int r;
- r = getc(in);
- if (r == EOF) {
- return 0;
- }
- *result = r << 8;
- r = getc(in);
- if (r == EOF) {
- return 0;
- }
- *result += r;
- return 1;
-}
-
-void gdPutWord(int w, FILE *out)
-{
- putc((unsigned char)(w >> 8), out);
- putc((unsigned char)(w & 0xFF), out);
-}
-
-int gdGetByte(int *result, FILE *in)
-{
- int r;
- r = getc(in);
- if (r == EOF) {
- return 0;
- }
- *result = r;
- return 1;
-}
-
-gdImagePtr gdImageCreateFromGd(FILE *in)
-{
- int sx, sy;
- int x, y;
- int i;
- gdImagePtr im;
- if (!gdGetWord(&sx, in)) {
- goto fail1;
- }
- if (!gdGetWord(&sy, in)) {
- goto fail1;
- }
- im = gdImageCreate(sx, sy);
- if (!gdGetByte(&im->colorsTotal, in)) {
- goto fail2;
- }
- if (!gdGetWord(&im->transparent, in)) {
- goto fail2;
- }
- if (im->transparent == 257) {
- im->transparent = (-1);
- }
- for (i=0; (i<gdMaxColors); i++) {
- if (!gdGetByte(&im->red[i], in)) {
- goto fail2;
- }
- if (!gdGetByte(&im->green[i], in)) {
- goto fail2;
- }
- if (!gdGetByte(&im->blue[i], in)) {
- goto fail2;
- }
- }
- for (y=0; (y<sy); y++) {
- for (x=0; (x<sx); x++) {
- int ch;
- ch = getc(in);
- if (ch == EOF) {
- gdImageDestroy(im);
- return 0;
- }
- /* ROW-MAJOR IN GD 1.3 */
- im->pixels[y][x] = ch;
- }
- }
- return im;
-fail2:
- gdImageDestroy(im);
-fail1:
- return 0;
-}
-
-void gdImageGd(gdImagePtr im, FILE *out)
-{
- int x, y;
- int i;
- int trans;
- gdPutWord(im->sx, out);
- gdPutWord(im->sy, out);
- putc((unsigned char)im->colorsTotal, out);
- trans = im->transparent;
- if (trans == (-1)) {
- trans = 257;
- }
- gdPutWord(trans, out);
- for (i=0; (i<gdMaxColors); i++) {
- putc((unsigned char)im->red[i], out);
- putc((unsigned char)im->green[i], out);
- putc((unsigned char)im->blue[i], out);
- }
- for (y=0; (y < im->sy); y++) {
- for (x=0; (x < im->sx); x++) {
- /* ROW-MAJOR IN GD 1.3 */
- putc((unsigned char)im->pixels[y][x], out);
- }
- }
-}
-
-gdImagePtr
-gdImageCreateFromXbm(FILE *fd)
-{
- gdImagePtr im;
- int bit;
- int w, h;
- int bytes;
- int ch;
- int i, x, y;
- char *sp;
- char s[161];
- if (!fgets(s, 160, fd)) {
- return 0;
- }
- sp = &s[0];
- /* Skip #define */
- sp = strchr(sp, ' ');
- if (!sp) {
- return 0;
- }
- /* Skip width label */
- sp++;
- sp = strchr(sp, ' ');
- if (!sp) {
- return 0;
- }
- /* Get width */
- w = atoi(sp + 1);
- if (!w) {
- return 0;
- }
- if (!fgets(s, 160, fd)) {
- return 0;
- }
- sp = s;
- /* Skip #define */
- sp = strchr(sp, ' ');
- if (!sp) {
- return 0;
- }
- /* Skip height label */
- sp++;
- sp = strchr(sp, ' ');
- if (!sp) {
- return 0;
- }
- /* Get height */
- h = atoi(sp + 1);
- if (!h) {
- return 0;
- }
- /* Skip declaration line */
- if (!fgets(s, 160, fd)) {
- return 0;
- }
- bytes = (w * h / 8) + 1;
- im = gdImageCreate(w, h);
- gdImageColorAllocate(im, 255, 255, 255);
- gdImageColorAllocate(im, 0, 0, 0);
- x = 0;
- y = 0;
- for (i=0; (i < bytes); i++) {
- char h[3];
- int b;
- /* Skip spaces, commas, CRs, 0x */
- while(1) {
- ch = getc(fd);
- if (ch == EOF) {
- goto fail;
- }
- if (ch == 'x') {
- break;
- }
- }
- /* Get hex value */
- ch = getc(fd);
- if (ch == EOF) {
- goto fail;
- }
- h[0] = ch;
- ch = getc(fd);
- if (ch == EOF) {
- goto fail;
- }
- h[1] = ch;
- h[2] = '\0';
- sscanf(h, "%x", &b);
- for (bit = 1; (bit <= 128); (bit = bit << 1)) {
- gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
- if (x == im->sx) {
- x = 0;
- y++;
- if (y == im->sy) {
- return im;
- }
- /* Fix 8/8/95 */
- break;
- }
- }
- }
- /* Shouldn't happen */
- fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n");
- return 0;
-fail:
- gdImageDestroy(im);
- return 0;
-}
-
-void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
-{
- int i;
- int lx, ly;
- if (!n) {
- return;
- }
- lx = p->x;
- ly = p->y;
- gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
- for (i=1; (i < n); i++) {
- p++;
- gdImageLine(im, lx, ly, p->x, p->y, c);
- lx = p->x;
- ly = p->y;
- }
-}
-
-int gdCompareInt(const void *a, const void *b);
-
-void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
-{
- int i;
- int y;
- int y1, y2;
- int ints;
- if (!n) {
- return;
- }
- if (!im->polyAllocated) {
- im->polyInts = (int *) malloc(sizeof(int) * n);
- im->polyAllocated = n;
- }
- if (im->polyAllocated < n) {
- while (im->polyAllocated < n) {
- im->polyAllocated *= 2;
- }
- im->polyInts = (int *) realloc(im->polyInts,
- sizeof(int) * im->polyAllocated);
- }
- y1 = p[0].y;
- y2 = p[0].y;
- for (i=1; (i < n); i++) {
- if (p[i].y < y1) {
- y1 = p[i].y;
- }
- if (p[i].y > y2) {
- y2 = p[i].y;
- }
- }
- /* Fix in 1.3: count a vertex only once */
- for (y=y1; (y < y2); y++) {
- int interLast = 0;
- int dirLast = 0;
- int interFirst = 1;
- ints = 0;
- for (i=0; (i <= n); i++) {
- int x1, x2;
- int y1, y2;
- int dir;
- int ind1, ind2;
- int lastInd1 = 0;
- if ((i == n) || (!i)) {
- ind1 = n-1;
- ind2 = 0;
- } else {
- ind1 = i-1;
- ind2 = i;
- }
- y1 = p[ind1].y;
- y2 = p[ind2].y;
- if (y1 < y2) {
- y1 = p[ind1].y;
- y2 = p[ind2].y;
- x1 = p[ind1].x;
- x2 = p[ind2].x;
- dir = -1;
- } else if (y1 > y2) {
- y2 = p[ind1].y;
- y1 = p[ind2].y;
- x2 = p[ind1].x;
- x1 = p[ind2].x;
- dir = 1;
- } else {
- /* Horizontal; just draw it */
- gdImageLine(im,
- p[ind1].x, y1,
- p[ind2].x, y1,
- c);
- continue;
- }
- if ((y >= y1) && (y <= y2)) {
- int inter =
- (y-y1) * (x2-x1) / (y2-y1) + x1;
- /* Only count intersections once
- except at maxima and minima. Also,
- if two consecutive intersections are
- endpoints of the same horizontal line
- that is not at a maxima or minima,
- discard the leftmost of the two. */
- if (!interFirst) {
- if ((p[ind1].y == p[lastInd1].y) &&
- (p[ind1].x != p[lastInd1].x)) {
- if (dir == dirLast) {
- if (inter > interLast) {
- /* Replace the old one */
- im->polyInts[ints] = inter;
- } else {
- /* Discard this one */
- }
- continue;
- }
- }
- if (inter == interLast) {
- if (dir == dirLast) {
- continue;
- }
- }
- }
- if (i > 0) {
- im->polyInts[ints++] = inter;
- }
- lastInd1 = i;
- dirLast = dir;
- interLast = inter;
- interFirst = 0;
- }
- }
- qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
- for (i=0; (i < (ints-1)); i+=2) {
- gdImageLine(im, im->polyInts[i], y,
- im->polyInts[i+1], y, c);
- }
- }
-}
-
-int gdCompareInt(const void *a, const void *b)
-{
- return (*(const int *)a) - (*(const int *)b);
-}
-
-void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
-{
- if (im->style) {
- free(im->style);
- }
- im->style = (int *)
- malloc(sizeof(int) * noOfPixels);
- memcpy(im->style, style, sizeof(int) * noOfPixels);
- im->styleLength = noOfPixels;
- im->stylePos = 0;
-}
-
-void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
-{
- int i;
- im->brush = brush;
- for (i=0; (i < gdImageColorsTotal(brush)); i++) {
- int index;
- index = gdImageColorExact(im,
- gdImageRed(brush, i),
- gdImageGreen(brush, i),
- gdImageBlue(brush, i));
- if (index == (-1)) {
- index = gdImageColorAllocate(im,
- gdImageRed(brush, i),
- gdImageGreen(brush, i),
- gdImageBlue(brush, i));
- if (index == (-1)) {
- index = gdImageColorClosest(im,
- gdImageRed(brush, i),
- gdImageGreen(brush, i),
- gdImageBlue(brush, i));
- }
- }
- im->brushColorMap[i] = index;
- }
-}
-
-void gdImageSetTile(gdImagePtr im, gdImagePtr tile)
-{
- int i;
- im->tile = tile;
- for (i=0; (i < gdImageColorsTotal(tile)); i++) {
- int index;
- index = gdImageColorExact(im,
- gdImageRed(tile, i),
- gdImageGreen(tile, i),
- gdImageBlue(tile, i));
- if (index == (-1)) {
- index = gdImageColorAllocate(im,
- gdImageRed(tile, i),
- gdImageGreen(tile, i),
- gdImageBlue(tile, i));
- if (index == (-1)) {
- index = gdImageColorClosest(im,
- gdImageRed(tile, i),
- gdImageGreen(tile, i),
- gdImageBlue(tile, i));
- }
- }
- im->tileColorMap[i] = index;
- }
-}
-
-void gdImageInterlace(gdImagePtr im, int interlaceArg)
-{
- im->interlace = interlaceArg;
-}