7
#define Min(x,y) (((x)<(y))?(x):(y))
8
#define Max(x,y) (((x)>(y))?(x):(y))
9
/* MONO returns total intensity of r,g,b components */
10
#define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5) /*.33R+ .5G+ .17B*/
12
static void gdImageBrushApply __PARAMS((gdImagePtr im, int x, int y));
13
static void gdImageTileApply __PARAMS((gdImagePtr im, int x, int y));
16
/*SG modified to add alu modes and clipping fiels */
17
gdImagePtr gdImageCreate(sx, sy)
23
im = (gdImage *) malloc(sizeof(gdImage));
24
/* NOW ROW-MAJOR IN GD 1.3 */
25
im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sy);
27
im->polyAllocated = 0;
31
for (i=0; (i<sy); i++) {
32
/* NOW ROW-MAJOR IN GD 1.3 */
33
im->pixels[i] = (unsigned char *) calloc(
34
sx, sizeof(unsigned char));
38
for (i=0;i<gdMaxColors;i++)
41
im->transparent = (-1);
43
/* modification to add alu and clipping */
46
im->cliprect[0] = 0; /* xmin */
47
im->cliprect[1] = 0; /* ymin */
48
im->cliprect[2] = sx; /* xmax */
49
im->cliprect[3] = sy; /* ymax */
53
void gdImageDestroy(im)
57
for (i=0; (i<im->sy); i++) {
70
int gdImageColorClosest(im, r, g, b)
80
for (i=0; (i<(im->colorsTotal)); i++) {
85
rd = (im->red[i] - r);
86
gd = (im->green[i] - g);
87
bd = (im->blue[i] - b);
88
dist = rd * rd + gd * gd + bd * bd;
89
if ((i == 0) || (dist < mindist)) {
97
int gdImageColorExact(im, r, g, b)
104
for (i=0; (i<(im->colorsTotal)); i++) {
108
if ((im->red[i] == r) &&
109
(im->green[i] == g) &&
110
(im->blue[i] == b)) {
117
int gdImageColorAllocate(im, r, g, b)
125
for (i=0; (i<(im->colorsTotal)); i++) {
132
ct = im->colorsTotal;
133
if (ct == gdMaxColors) {
145
void gdImageColorDeallocate(im, color)
153
void gdImageColorTransparent(im, color)
157
im->transparent = color;
160
/*SG gdSetClipping and gdUnsetClipping have been added to handle clipping */
161
void gdSetClipping(im, xmin, ymin, xmax, ymax)
169
im->cliprect[0] = xmin; /* xmin */
170
im->cliprect[1] = ymin; /* ymin */
171
im->cliprect[2] = xmax; /* xmax */
172
im->cliprect[3] = ymax; /* ymax */
175
void gdUnsetClipping(im)
180
/*SG gdSetAlu and gdAluColor have been added to handle alu modes */
181
void gdSetAlu(im, alu)
188
int gdAluColor(im, dst, src)
194
unsigned char r, g, b, rd, gd, bd, rs, gs, bs;
204
rd = ~(unsigned char)im->red[dst];
205
gd = ~(unsigned char)im->green[dst];
206
bd = ~(unsigned char)im->blue[dst];
208
rs = ~(unsigned char)im->red[src];
209
gs = ~(unsigned char)im->green[src];
210
bs = ~(unsigned char)im->blue[src];
213
case 1: /* src AND dst */
218
case 2: /* src AND NOT dst */
223
case 4: /* NOT src AND dst */
230
case 6: /* src XOR dst */
235
case 7: /* src OR dst */
240
case 8: /*NOT src AND NOT dst */
245
case 9: /*NOT src XOR dst */
250
case 10: /* NOT dst */
255
case 11: /*src OR NOT dst */
260
case 12: /* NOT src */
265
case 13: /* NOT src OR dst */
270
case 14: /* NOT src OR NOT dst */
284
new = gdImageColorExact(im, (int)r, (int)g, (int)b);
286
new = gdImageColorAllocate(im, (int)r, (int)g, (int)b);
288
new = gdImageColorClosest(im, (int)r, (int)g, (int)b);
292
void gdSetBackground(im, background)
296
im->background = background;
298
/*SG gdImageSetPixel modified to handle alu modes */
299
void gdImageSetPixel(im, x, y, color)
310
/* Refuse to draw if no style is set. */
313
p = im->style[im->stylePos++];
315
if (p != (gdTransparent)) {
316
gdImageSetPixel(im, x, y, p);
318
im->stylePos = im->stylePos % im->styleLength;
320
case gdStyledBrushed:
322
/* Refuse to draw if no style is set. */
325
p = im->style[im->stylePos++];
326
if ((p != gdTransparent) && (p != 0)) {
327
gdImageSetPixel(im, x, y, gdBrushed);
329
im->stylePos = im->stylePos % im->styleLength;
332
gdImageBrushApply(im, x, y);
335
gdImageTileApply(im, x, y);
338
if (gdImageBoundsSafe(im, x, y)) {
339
/* NOW ROW-MAJOR IN GD 1.3 */
340
/*SG modified here to handle alu modes */
341
im->pixels[y][x] = gdAluColor(im,im->pixels[y][x],color);
349
static void gdImageBrushApply(im, x, y)
362
hy = gdImageSY(im->brush)/2;
364
y2 = y1 + gdImageSY(im->brush);
365
hx = gdImageSX(im->brush)/2;
367
x2 = x1 + gdImageSX(im->brush);
369
for (ly = y1; (ly < y2); ly++) {
371
for (lx = x1; (lx < x2); lx++) {
373
p = gdImageGetPixel(im->brush, srcx, srcy);
374
/* Allow for non-square brushes! */
375
if (p != gdImageGetTransparent(im->brush)) {
376
gdImageSetPixel(im, lx, ly,
377
im->brushColorMap[p]);
385
static void gdImageTileApply(im, x, y)
395
srcx = x % gdImageSX(im->tile);
396
srcy = y % gdImageSY(im->tile);
397
p = gdImageGetPixel(im->tile, srcx, srcy);
398
/* Allow for transparency */
399
if (p != gdImageGetTransparent(im->tile)) {
400
gdImageSetPixel(im, x, y,
401
im->tileColorMap[p]);
405
int gdImageGetPixel(im, x, y)
410
if (gdImageBoundsSafe(im, x, y)) {
411
/* NOW ROW-MAJOR IN GD 1.3 */
412
return im->pixels[y][x];
418
/* Bresenham as presented in Foley & Van Dam */
419
/*SG added function to handle Thick lines with alu modes */
420
void gdImageThickLine(im, x1, y1, x2, y2, color, thick)
429
int virtual, c, c1, x, y, oldcmap, mnx, mxx, mny, mxy;
430
gdImagePtr imv, brush, oldbrush;
432
virtual= (im->alu!=3 && im->alu!=0 && im->alu!=5);
434
mnx=Max(0,Min(x1,x2)-thick/2);
435
mny=Max(0,Min(y1,y2)-thick/2);
436
mxx=Min(im->sx,Max(x1,x2)+thick/2);
437
mxy=Min(im->sy,Max(y1,y2)+thick/2);
439
imv=gdImageCreate(im->sx, im->sy);
440
for (y=mny; (y <= mxy ); y++) {
441
for (x=mnx; (x <= mxx); x++) {
452
if (thick > 1 && color >= 0) { /* create a square brush */
453
brush=gdImageCreate(thick, thick);
454
for (y=0; (y < thick ); y++) {
455
for (x=0; (x < thick); x++) {
456
brush->pixels[y][x]=c;
459
oldbrush = imv->brush;
461
oldcmap = imv->brushColorMap[c];
462
imv->brushColorMap[c] = c;
466
gdImageLine(imv,x1, y1, x2, y2, c);
468
if (thick > 1 && color >= 0) { /* deallocate square brush */
469
gdImageDestroy(brush);
470
imv->brush = oldbrush;
471
imv->brushColorMap[c1] = oldcmap;
474
for (y=mny; (y <= mxy ); y++) {
475
for (x=mnx; (x <= mxx); x++) {
476
if (imv->pixels[y][x] == 1)
477
gdImageSetPixel(im, x, y, color);
485
void gdImageLine(im, x1, y1, x2, y2, color)
493
int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
499
incr2 = 2 * (dy - dx);
511
gdImageSetPixel(im, x, y, color);
512
if (((y2 - y1) * ydirflag) > 0) {
521
gdImageSetPixel(im, x, y, color);
532
gdImageSetPixel(im, x, y, color);
538
incr2 = 2 * (dx - dy);
550
gdImageSetPixel(im, x, y, color);
551
if (((x2 - x1) * xdirflag) > 0) {
560
gdImageSetPixel(im, x, y, color);
571
gdImageSetPixel(im, x, y, color);
576
/*SG added to handle thick polylines along with alu mode */
577
void gdImagePolyLine(im, X, Y, n, color, thick, close)
588
int virtual, c, c1, mnx, mxx, mny, mxy, oldcmap1;
589
gdImagePtr imv, brush, oldbrush;
592
virtual= (im->alu!=3 && im->alu!=0 && im->alu!=5);
602
mnx=Max(0,mnx-thick/2);
603
mny=Max(0,mny-thick/2);
604
mxx=Min(im->sx,mxx+thick/2);
605
mxy=Min(im->sy,mxy+thick/2);
607
imv=gdImageCreate(im->sx, im->sy);
608
for (y=mny; (y <= mxy ); y++) {
609
for (x=mnx; (x <= mxx); x++) {
620
if (thick > 1 && color >= 0) { /* create a square brush */
621
brush=gdImageCreate(thick, thick);
622
for (y=0; (y < thick ); y++) {
623
for (x=0; (x < thick); x++) {
624
brush->pixels[y][x]=c;
627
oldbrush = imv->brush;
629
oldcmap1 = imv->brushColorMap[c];
630
imv->brushColorMap[c] = c;
635
gdImageLine(imv,X[i],Y[i],X[i+1],Y[i+1],c);
639
gdImageLine(imv,X[n-1],Y[n-1],X[0],Y[0],c);
642
if (thick > 1 && color >= 0) { /* deallocate square brush */
643
gdImageDestroy(brush);
644
imv->brush = oldbrush;
645
imv->brushColorMap[c1] = oldcmap1;
649
for (y=mny; (y <= mxy ); y++) {
650
for (x=mnx; (x <= mxx); x++) {
651
if (imv->pixels[y][x] == 1)
652
gdImageSetPixel(im, x, y, color);
659
/*SG modified to add clipping region */
660
int gdImageBoundsSafe(im, x, y)
667
bounds= (!(((y < 0) || (y >= im->sy)) ||
668
((x < 0) || (x >= im->sx))));
669
/* next lines added to handle clipping region */
670
if (im->clipping == 1) {
673
(!(((y < im->cliprect[1]) || (y > im->cliprect[3])) ||
674
((x < im->cliprect[0]) || (x > im->cliprect[2]))));
679
/*SG gdImageChar has been modified to handle variable width fonts;
680
it now returns the position of beginning of the next character */
681
int gdImageChar(im, f, x, y, c, color)
696
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
699
fline = (c - f->offset) * f->h * f->w;
700
for (py = y; (py < (y + f->h)); py++) {
701
for (px = x; (px < (x + f->w)); px++) {
702
if (f->data[fline + cy * f->w + cx]) {
703
gdImageSetPixel(im, px, py, color);
713
/*SG gdCharWidth has been added to compute the effective width of a character */
714
int gdCharWidth(f, c)
727
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
730
fline = (c - f->offset) * f->h * f->w;
731
for (py = 0; (py < ( f->h)); py++) {
732
for (px = 0; (px < (f->w)); px++) {
733
if (f->data[fline + cy * f->w + cx]) {
745
void gdImageCharUp(im, f, x, y, c, color)
760
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
763
fline = (c - f->offset) * f->h * f->w;
764
for (py = y; (py > (y - f->w)); py--) {
765
for (px = x; (px < (x + f->h)); px++) {
766
if (f->data[fline + cy * f->w + cx]) {
767
gdImageSetPixel(im, px, py, color);
776
/*SG gdImageString has been modified to handle variable width fonts */
777
void gdImageString(im, f, x, y, s, color)
787
l = strlen((unsigned char *)s);
788
for (i=0; (i<l); i++) {
789
dx = gdImageChar(im, f, x, y, s[i], color);
795
void gdImageStringUp(im, f, x, y, s, color)
805
l = strlen((unsigned char *)s);
806
for (i=0; (i<l); i++) {
807
gdImageCharUp(im, f, x, y, s[i], color);
812
static int strlen16();
814
void gdImageString16(im, f, x, y, s, color)
819
short unsigned int *s;
825
for (i=0; (i<l); i++) {
826
gdImageChar(im, f, x, y, s[i], color);
831
void gdImageStringUp16(im, f, x, y, s, color)
836
short unsigned int *s;
842
for (i=0; (i<l); i++) {
843
gdImageCharUp(im, f, x, y, s[i], color);
848
static int strlen16(s)
849
short unsigned int *s;
859
/* s and e are integers modulo 360 (degrees), with 0 degrees
860
being the rightmost extreme and degrees changing clockwise.
861
cx and cy are the center in pixels; w and h are the horizontal
862
and vertical diameter in pixels. Nice interface, but slow, since
863
I don't yet use Bresenham (I'm using an inefficient but
864
simple solution with too much work going on in it; generalizing
865
Bresenham to ellipses and partial arcs of ellipses is non-trivial,
866
at least for me) and there are other inefficiencies (small circles
867
do far too much work). */
869
void gdImageArc(im, cx, cy, w, h, s, e, color)
887
for (i=s; (i <= e); i++) {
889
x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
890
y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
892
gdImageLine(im, lx, ly, x, y, color);
901
/* Bresenham octant code, which I should use eventually */
907
gdImageSetPixel(im, cx+x, cy+y, color);
911
d += 4 * (x - y) + 10;
917
gdImageSetPixel(im, cx+x, cy+y, color);
921
void gdImageFillToBorder(im, x, y, border, color)
930
int leftLimit, rightLimit;
934
/* Refuse to fill to a non-solid border */
937
for (i = x; (i >= 0); i--) {
938
if (gdImageGetPixel(im, i, y) == border) {
941
gdImageSetPixel(im, i, y, color);
944
if (leftLimit == (-1)) {
949
for (i = (x+1); (i < im->sx); i++) {
950
if (gdImageGetPixel(im, i, y) == border) {
953
gdImageSetPixel(im, i, y, color);
956
/* Look at lines above and below and start paints */
960
for (i = leftLimit; (i <= rightLimit); i++) {
962
c = gdImageGetPixel(im, i, y-1);
964
if ((c != border) && (c != color)) {
965
gdImageFillToBorder(im, i, y-1,
969
} else if ((c == border) || (c == color)) {
975
if (y < ((im->sy) - 1)) {
977
for (i = leftLimit; (i <= rightLimit); i++) {
979
c = gdImageGetPixel(im, i, y+1);
981
if ((c != border) && (c != color)) {
982
gdImageFillToBorder(im, i, y+1,
986
} else if ((c == border) || (c == color)) {
993
void gdImageFill(im, x, y, color)
1001
int leftLimit, rightLimit;
1003
old = gdImageGetPixel(im, x, y);
1004
if (color == gdTiled) {
1005
/* Tile fill -- got to watch out! */
1011
/* Refuse to flood-fill with a transparent pattern --
1012
I can't do it without allocating another image */
1013
if (gdImageGetTransparent(im->tile) != (-1)) {
1016
srcx = x % gdImageSX(im->tile);
1017
srcy = y % gdImageSY(im->tile);
1018
p = gdImageGetPixel(im->tile, srcx, srcy);
1019
tileColor = im->tileColorMap[p];
1020
if (old == tileColor) {
1021
/* Nothing to be done */
1026
/* Nothing to be done */
1032
for (i = x; (i >= 0); i--) {
1033
if (gdImageGetPixel(im, i, y) != old) {
1036
gdImageSetPixel(im, i, y, color);
1039
if (leftLimit == (-1)) {
1044
for (i = (x+1); (i < im->sx); i++) {
1045
if (gdImageGetPixel(im, i, y) != old) {
1048
gdImageSetPixel(im, i, y, color);
1051
/* Look at lines above and below and start paints */
1055
for (i = leftLimit; (i <= rightLimit); i++) {
1057
c = gdImageGetPixel(im, i, y-1);
1060
gdImageFill(im, i, y-1, color);
1063
} else if (c != old) {
1069
if (y < ((im->sy) - 1)) {
1071
for (i = leftLimit; (i <= rightLimit); i++) {
1073
c = gdImageGetPixel(im, i, y+1);
1076
gdImageFill(im, i, y+1, color);
1079
} else if (c != old) {
1086
/* Code drawn from ppmtogif.c, from the pbmplus package
1088
** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
1089
** Lempel-Zim compression based on "compress".
1091
** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
1093
** Copyright (C) 1989 by Jef Poskanzer.
1095
** Permission to use, copy, modify, and distribute this software and its
1096
** documentation for any purpose and without fee is hereby granted, provided
1097
** that the above copyright notice appear in all copies and that both that
1098
** copyright notice and this permission notice appear in supporting
1099
** documentation. This software is provided "as is" without express or
1100
** implied warranty.
1102
** The Graphics Interchange Format(c) is the Copyright property of
1103
** CompuServe Incorporated. GIF(sm) is a Service Mark property of
1104
** CompuServe Incorporated.
1106
* Heavily modified by Mouse, 1998-02-12.
1107
* Remove LZW compression.
1108
* Added miGIF run length compression.
1113
* a code_int must be able to hold 2**GIFBITS values of type int, and also -1
1115
typedef int code_int;
1117
static int colorstobpp();
1118
static void BumpPixel ();
1119
static int GIFNextPixel ();
1120
static void GIFEncode ();
1121
static void Putword ();
1122
static void compress ();
1123
static void output ();
1124
static void char_init ();
1125
static void char_out ();
1126
/* Allows for reuse */
1127
static void init_statics();
1129
void gdImageGif(im, out)
1133
int interlace, transparent, background, BitsPerPixel;
1134
interlace = im->interlace;
1135
transparent = im->transparent;
1136
background = im->background;
1137
BitsPerPixel = colorstobpp(im->colorsTotal);
1138
/* Clear any old values in statics strewn through the GIF code */
1140
/* All set, let's do it. */
1142
out, im->sx, im->sy, interlace, background, transparent,
1143
BitsPerPixel, im->red, im->green, im->blue, im);
1154
else if ( colors <= 4 )
1156
else if ( colors <= 8 )
1158
else if ( colors <= 16 )
1160
else if ( colors <= 32 )
1162
else if ( colors <= 64 )
1164
else if ( colors <= 128 )
1166
else if ( colors <= 256 )
1171
/*****************************************************************************
1173
* GIFENCODE.C - GIF Image compression interface
1175
* GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
1176
* BitsPerPixel, Red, Green, Blue, gdImagePtr )
1178
*****************************************************************************/
1183
static int Width, Height;
1184
static int curx, cury;
1185
static long CountDown;
1186
static int Pass = 0;
1187
static int Interlace;
1190
* Bump the 'curx' and 'cury' to point to the next pixel
1196
* Bump the current X position
1201
* If we are at the end of a scan line, set curx back to the beginning
1202
* If we are interlaced, bump the cury to the appropriate spot,
1203
* otherwise, just increment it.
1205
if( curx == Width ) {
1215
if( cury >= Height ) {
1223
if( cury >= Height ) {
1231
if( cury >= Height ) {
1246
* Return the next pixel from the image
1254
if( CountDown == 0 )
1259
r = gdImageGetPixel(im, curx, cury);
1269
GIFEncode(fp, GWidth, GHeight, GInterlace, Background, Transparent, BitsPerPixel, Red, Green, Blue, im)
1283
int RWidth, RHeight;
1284
int LeftOfs, TopOfs;
1290
Interlace = GInterlace;
1292
ColorMapSize = 1 << BitsPerPixel;
1294
RWidth = Width = GWidth;
1295
RHeight = Height = GHeight;
1296
LeftOfs = TopOfs = 0;
1298
Resolution = BitsPerPixel;
1301
* Calculate number of bits we are expecting
1303
CountDown = (long)Width * (long)Height;
1305
* Indicate which pass we are on (if interlace)
1310
* The initial code size
1312
if( BitsPerPixel <= 1 )
1315
InitCodeSize = BitsPerPixel;
1318
* Set up the current x and y position
1323
* Write the Magic header
1325
fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
1328
* Write out the screen width and height
1330
Putword( RWidth, fp );
1331
Putword( RHeight, fp );
1334
* Indicate that there is a global colour map
1336
B = 0x80; /* Yes, there is a color map */
1339
* OR in the resolution
1341
B |= (Resolution - 1) << 4;
1344
* OR in the Bits per Pixel
1346
B |= (BitsPerPixel - 1);
1354
* Write out the Background colour
1356
fputc( Background, fp );
1359
* Byte of 0's (future expansion)
1364
* Write out the Global Colour Map
1366
for( i=0; i<ColorMapSize; ++i ) {
1367
fputc( Red[i], fp );
1368
fputc( Green[i], fp );
1369
fputc( Blue[i], fp );
1373
* Write out extension for transparent colour index, if necessary.
1375
if ( Transparent >= 0 ) {
1382
fputc( (unsigned char) Transparent, fp );
1387
* Write an Image separator
1392
* Write the Image header
1395
Putword( LeftOfs, fp );
1396
Putword( TopOfs, fp );
1397
Putword( Width, fp );
1398
Putword( Height, fp );
1401
* Write out whether or not the image is interlaced
1408
* Write out the initial code size
1410
fputc( InitCodeSize, fp );
1413
* Go and actually compress the data
1415
compress( InitCodeSize+1, fp, im, Background );
1418
* Write out a Zero-length packet (to end the series)
1423
* Write the GIF file terminator
1429
* Write out a word to the GIF file
1436
fputc( w & 0xff, fp );
1437
fputc( (w / 256) & 0xff, fp );
1442
/*-----------------------------------------------------------------------
1444
* miGIF Compression - mouse and ivo's GIF-compatible compression
1446
* -run length encoding compression routines-
1448
* Copyright (C) 1998 Hutchison Avenue Software Corporation
1449
* http://www.hasc.com
1452
* Permission to use, copy, modify, and distribute this software and its
1453
* documentation for any purpose and without fee is hereby granted, provided
1454
* that the above copyright notice appear in all copies and that both that
1455
* copyright notice and this permission notice appear in supporting
1456
* documentation. This software is provided "AS IS." The Hutchison Avenue
1457
* Software Corporation disclaims all warranties, either express or implied,
1458
* including but not limited to implied warranties of merchantability and
1459
* fitness for a particular purpose, with respect to this code and accompanying
1462
* The miGIF compression routines do not, strictly speaking, generate files
1463
* conforming to the GIF spec, since the image data is not LZW-compressed
1464
* (this is the point: in order to avoid transgression of the Unisys patent
1465
* on the LZW algorithm.) However, miGIF generates data streams that any
1466
* reasonably sane LZW decompresser will decompress to what we want.
1468
* miGIF compression uses run length encoding. It compresses horizontal runs
1469
* of pixels of the same color. This type of compression gives good results
1470
* on images with many runs, for example images with lines, text and solid
1471
* shapes on a solid-colored background. It gives little or no compression
1472
* on images with few runs, for example digital or scanned photos.
1475
* mouse@rodents.montreal.qc.ca
1476
* 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
1480
* The Graphics Interchange Format(c) is the Copyright property of
1481
* CompuServe Incorporated. GIF(sm) is a Service Mark property of
1482
* CompuServe Incorporated.
1486
static int rl_pixel;
1487
static int rl_basecode;
1488
static int rl_count;
1489
static int rl_table_pixel;
1490
static int rl_table_max;
1491
static int just_cleared;
1492
static int out_bits;
1493
static int out_bits_init;
1494
static int out_count;
1495
static int out_bump;
1496
static int out_bump_init;
1497
static int out_clear;
1498
static int out_clear_init;
1499
static int max_ocodes;
1500
static int code_clear;
1501
static int code_eof;
1502
static unsigned int obuf;
1505
static unsigned char oblock[256];
1508
/* Used only when debugging GIF compression code */
1509
/* #define DEBUGGING_ENVARS */
1511
#ifdef DEBUGGING_ENVARS
1513
static int verbose_set = 0;
1515
#define VERBOSE (verbose_set?verbose:set_verbose())
1517
static int set_verbose(void)
1519
verbose = !!getenv("GIF_VERBOSE");
1531
static const char *binformat(unsigned int v, int nbits)
1533
static char *binformat(v, nbits)
1538
static char bufs[8][64];
1539
static int bhand = 0;
1545
if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
1546
bp = &bufs[bhand][0];
1547
for (bno=nbits-1,bit=(unsigned int)1<<bno;bno>=0;bno--,bit>>=1)
1548
{ *bp++ = (v & bit) ? '1' : '0';
1549
if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
1552
return(&bufs[bhand][0]);
1555
static void write_block()
1560
{ printf("write_block %d:",oblen);
1561
for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
1565
fwrite(&oblock[0],1,oblen,ofile);
1569
static void block_out(c)
1572
if (VERBOSE) printf("block_out %s\n",binformat(c,8));
1573
oblock[oblen++] = c;
1574
if (oblen >= 255) write_block();
1577
static void block_flush()
1579
if (VERBOSE) printf("block_flush\n");
1580
if (oblen > 0) write_block();
1583
static void output(val)
1586
if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
1587
obuf |= val << obits;
1590
{ block_out(obuf&0xff);
1594
if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
1597
static void output_flush()
1599
if (VERBOSE) printf("output_flush\n");
1600
if (obits > 0) block_out(obuf);
1604
static void did_clear()
1606
if (VERBOSE) printf("did_clear\n");
1607
out_bits = out_bits_init;
1608
out_bump = out_bump_init;
1609
out_clear = out_clear_init;
1615
static void output_plain(c)
1618
if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
1622
if (out_count >= out_bump)
1624
out_bump += 1 << (out_bits - 1);
1626
if (out_count >= out_clear)
1627
{ output(code_clear);
1632
static unsigned int isqrt(x)
1638
if (x < 2) return(x);
1639
for (v=x,r=1;v;v>>=2,r<<=1) ;
1641
{ v = ((x / r) + r) / 2;
1642
if ((v == r) || (v == r+1)) return(r);
1647
static unsigned int compute_triangle_count(count, nrepcodes)
1649
unsigned int nrepcodes;
1651
unsigned int perrep;
1655
perrep = (nrepcodes * (nrepcodes+1)) / 2;
1656
while (count >= perrep)
1657
{ cost += nrepcodes;
1663
while ((n*(n+1)) >= 2*count) n --;
1664
while ((n*(n+1)) < 2*count) n ++;
1670
static void max_out_clear()
1672
out_clear = max_ocodes;
1675
static void reset_out_clear()
1677
out_clear = out_clear_init;
1678
if (out_count >= out_clear)
1679
{ output(code_clear);
1684
static void rl_flush_fromclear(count)
1689
if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
1691
rl_table_pixel = rl_pixel;
1696
output_plain(rl_pixel);
1699
else if (count >= n)
1701
output_plain(rl_basecode+n-2);
1704
else if (count == 1)
1706
output_plain(rl_pixel);
1711
output_plain(rl_basecode+count-2);
1714
if (out_count == 0) n = 1; else n ++;
1717
if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
1720
static void rl_flush_clearorrep(count)
1725
if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
1726
withclr = 1 + (int)compute_triangle_count(count,max_ocodes);
1727
if (withclr < count)
1728
{ output(code_clear);
1730
rl_flush_fromclear(count);
1733
{ for (;count>0;count--) output_plain(rl_pixel);
1737
static void rl_flush_withtable(count)
1744
if (VERBOSE) printf("rl_flush_withtable %d\n",count);
1745
repmax = count / rl_table_max;
1746
leftover = count % rl_table_max;
1747
repleft = (leftover ? 1 : 0);
1748
if (out_count+repmax+repleft > max_ocodes)
1749
{ repmax = max_ocodes - out_count;
1750
leftover = count - (repmax * rl_table_max);
1751
repleft = 1 + compute_triangle_count(leftover,max_ocodes);
1753
if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
1754
if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
1755
{ output(code_clear);
1757
rl_flush_fromclear(count);
1761
for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
1764
{ rl_flush_fromclear(leftover);
1766
else if (leftover == 1)
1767
{ output_plain(rl_pixel);
1770
{ output_plain(rl_basecode+leftover-2);
1776
static void rl_flush()
1778
if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
1780
{ output_plain(rl_pixel);
1782
if (VERBOSE) printf("rl_flush ]\n");
1786
{ rl_flush_fromclear(rl_count);
1788
else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
1789
{ rl_flush_clearorrep(rl_count);
1792
{ rl_flush_withtable(rl_count);
1794
if (VERBOSE) printf("rl_flush ]\n");
1798
static void compress(init_bits, outfile, im, background)
1810
code_clear = 1 << (init_bits - 1);
1811
code_eof = code_clear + 1;
1812
rl_basecode = code_eof + 1;
1813
out_bump_init = (1 << (init_bits - 1)) - 1;
1814
/* for images with a lot of runs, making out_clear_init larger will
1815
give better compression. */
1816
out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
1818
#ifdef DEBUGGING_ENVARS
1819
{ const char *ocienv;
1820
ocienv = getenv("GIF_OUT_CLEAR_INIT");
1822
{ out_clear_init = atoi(ocienv);
1823
if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
1828
out_bits_init = init_bits;
1830
max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
1835
{ c = GIFNextPixel(im);
1836
if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
1837
if (c == EOF) break;
1850
/*-----------------------------------------------------------------------
1852
* End of miGIF section - See copyright notice at start of section.
1854
*-----------------------------------------------------------------------*/
1857
/******************************************************************************
1859
* GIF Specific routines
1861
******************************************************************************/
1864
* Number of characters so far in this 'packet'
1869
* Set up the 'byte output' routine
1878
* Define the storage for the packet accumulator
1880
static char accum[ 256 ];
1882
static void init_statics()
1884
/* Some of these are properly initialized later. What I'm doing
1885
here is making sure code that depends on C's initialization
1886
of statics doesn't break when the code gets called more
1899
/* +-------------------------------------------------------------------+ */
1900
/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */
1901
/* | Permission to use, copy, modify, and distribute this software | */
1902
/* | and its documentation for any purpose and without fee is hereby | */
1903
/* | granted, provided that the above copyright notice appear in all | */
1904
/* | copies and that both that copyright notice and this permission | */
1905
/* | notice appear in supporting documentation. This software is | */
1906
/* | provided "as is" without express or implied warranty. | */
1907
/* +-------------------------------------------------------------------+ */
1910
#define MAXCOLORMAPSIZE 256
1919
#define MAX_LWZ_BITS 12
1921
#define INTERLACE 0x40
1922
#define LOCALCOLORMAP 0x80
1923
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
1925
#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
1927
#define LM_to_uint(a,b) (((b)<<8)|(a))
1929
/* We may eventually want to use this information, but def it out for now */
1933
unsigned int Height;
1934
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
1935
unsigned int BitPixel;
1936
unsigned int ColorResolution;
1937
unsigned int Background;
1938
unsigned int AspectRatio;
1947
} Gif89 = { -1, -1, -1, 0 };
1949
static int ReadColorMap ();
1950
static int DoExtension ();
1951
static int GetDataBlock ();
1952
static int GetCode ();
1953
static int LWZReadByte ();
1954
static void ReadImage ();
1959
gdImageCreateFromGif(fd)
1964
int ColorResolution;
1967
int Transparent = (-1);
1968
unsigned char buf[16];
1970
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
1971
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
1973
int useGlobalColormap;
1978
ZeroDataBlock = FALSE;
1981
if (! ReadOK(fd,buf,6)) {
1984
if (strncmp((char *)buf,"GIF",3) != 0) {
1987
strncpy(version, (char *)buf + 3, 3);
1990
if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
1993
if (! ReadOK(fd,buf,7)) {
1996
BitPixel = 2<<(buf[4]&0x07);
1997
ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
1998
Background = buf[5];
1999
AspectRatio = buf[6];
2001
if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
2002
if (ReadColorMap(fd, BitPixel, ColorMap)) {
2007
if (! ReadOK(fd,&c,1)) {
2010
if (c == ';') { /* GIF terminator */
2012
if (imageCount < imageNumber) {
2015
/* Terminator before any image was declared! */
2019
/* Check for open colors at the end, so
2020
we can reduce colorsTotal and ultimately
2022
for (i=((im->colorsTotal-1)); (i>=0); i--) {
2032
if (c == '!') { /* Extension */
2033
if (! ReadOK(fd,&c,1)) {
2036
DoExtension(fd, c, &Transparent);
2040
if (c != ',') { /* Not a valid start character */
2046
if (! ReadOK(fd,buf,9)) {
2050
useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
2052
bitPixel = 1<<((buf[8]&0x07)+1);
2054
imw = LM_to_uint(buf[4],buf[5]);
2055
imh = LM_to_uint(buf[6],buf[7]);
2056
if (!(im = gdImageCreate(imw, imh))) {
2059
im->interlace = BitSet(buf[8], INTERLACE);
2060
if (! useGlobalColormap) {
2061
if (ReadColorMap(fd, bitPixel, localColorMap)) {
2064
ReadImage(im, fd, imw, imh, localColorMap,
2065
BitSet(buf[8], INTERLACE),
2066
imageCount != imageNumber);
2068
ReadImage(im, fd, imw, imh,
2070
BitSet(buf[8], INTERLACE),
2071
imageCount != imageNumber);
2073
if (Transparent != (-1)) {
2074
gdImageColorTransparent(im, Transparent);
2080
ReadColorMap(fd, number, buffer)
2083
unsigned char (*buffer)[256];
2086
unsigned char rgb[3];
2089
for (i = 0; i < number; ++i) {
2090
if (! ReadOK(fd, rgb, sizeof(rgb))) {
2093
buffer[CM_RED][i] = rgb[0] ;
2094
buffer[CM_GREEN][i] = rgb[1] ;
2095
buffer[CM_BLUE][i] = rgb[2] ;
2103
DoExtension(fd, label, Transparent)
2108
static unsigned char buf[256];
2111
case 0xf9: /* Graphic Control Extension */
2112
(void) GetDataBlock(fd, (unsigned char*) buf);
2113
Gif89.disposal = (buf[0] >> 2) & 0x7;
2114
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
2115
Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
2116
if ((buf[0] & 0x1) != 0)
2117
*Transparent = buf[3];
2119
while (GetDataBlock(fd, (unsigned char*) buf) != 0)
2125
while (GetDataBlock(fd, (unsigned char*) buf) != 0)
2132
GetDataBlock_(fd, buf)
2136
unsigned char count;
2138
if (! ReadOK(fd,&count,1)) {
2142
ZeroDataBlock = count == 0;
2144
if ((count != 0) && (! ReadOK(fd, buf, count))) {
2152
GetDataBlock(fd, buf)
2159
rv = GetDataBlock_(fd,buf);
2161
{ printf("[GetDataBlock returning %d",rv);
2164
for (i=0;i<rv;i++) printf(" %02x",buf[i]);
2172
GetCode_(fd, code_size, flag)
2177
static unsigned char buf[280];
2178
static int curbit, lastbit, done, last_byte;
2180
unsigned char count;
2189
if ( (curbit+code_size) >= lastbit) {
2191
if (curbit >= lastbit) {
2196
buf[0] = buf[last_byte-2];
2197
buf[1] = buf[last_byte-1];
2199
if ((count = GetDataBlock(fd, &buf[2])) == 0)
2202
last_byte = 2 + count;
2203
curbit = (curbit - lastbit) + 16;
2204
lastbit = (2+count)*8 ;
2208
for (i = curbit, j = 0; j < code_size; ++i, ++j)
2209
ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
2211
curbit += code_size;
2216
GetCode(fd, code_size, flag)
2223
rv = GetCode_(fd,code_size,flag);
2224
if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
2229
LWZReadByte_(fd, flag, input_code_size)
2232
int input_code_size;
2234
static int fresh = FALSE;
2236
static int code_size, set_code_size;
2237
static int max_code, max_code_size;
2238
static int firstcode, oldcode;
2239
static int clear_code, end_code;
2240
static int table[2][(1<< MAX_LWZ_BITS)];
2241
static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
2245
set_code_size = input_code_size;
2246
code_size = set_code_size+1;
2247
clear_code = 1 << set_code_size ;
2248
end_code = clear_code + 1;
2249
max_code_size = 2*clear_code;
2250
max_code = clear_code+2;
2252
GetCode(fd, 0, TRUE);
2256
for (i = 0; i < clear_code; ++i) {
2260
for (; i < (1<<MAX_LWZ_BITS); ++i)
2261
table[0][i] = table[1][0] = 0;
2269
firstcode = oldcode =
2270
GetCode(fd, code_size, FALSE);
2271
} while (firstcode == clear_code);
2278
while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
2279
if (code == clear_code) {
2280
for (i = 0; i < clear_code; ++i) {
2284
for (; i < (1<<MAX_LWZ_BITS); ++i)
2285
table[0][i] = table[1][i] = 0;
2286
code_size = set_code_size+1;
2287
max_code_size = 2*clear_code;
2288
max_code = clear_code+2;
2290
firstcode = oldcode =
2291
GetCode(fd, code_size, FALSE);
2293
} else if (code == end_code) {
2295
unsigned char buf[260];
2300
while ((count = GetDataBlock(fd, buf)) > 0)
2309
if (code >= max_code) {
2314
while (code >= clear_code) {
2315
*sp++ = table[1][code];
2316
if (code == table[0][code]) {
2319
code = table[0][code];
2322
*sp++ = firstcode = table[1][code];
2324
if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
2325
table[0][code] = oldcode;
2326
table[1][code] = firstcode;
2328
if ((max_code >= max_code_size) &&
2329
(max_code_size < (1<<MAX_LWZ_BITS))) {
2344
LWZReadByte(fd, flag, input_code_size)
2347
int input_code_size;
2351
rv = LWZReadByte_(fd,flag,input_code_size);
2352
if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
2357
ReadImage(im, fd, len, height, cmap, interlace, ignore)
2362
unsigned char (*cmap)[256];
2368
int xpos = 0, ypos = 0, pass = 0;
2370
/* Stash the color map into the image */
2371
for (i=0; (i<gdMaxColors); i++) {
2372
im->red[i] = cmap[CM_RED][i];
2373
im->green[i] = cmap[CM_GREEN][i];
2374
im->blue[i] = cmap[CM_BLUE][i];
2377
/* Many (perhaps most) of these colors will remain marked open. */
2378
im->colorsTotal = gdMaxColors;
2380
** Initialize the Compression routines
2382
if (! ReadOK(fd,&c,1)) {
2385
if (LWZReadByte(fd, TRUE, c) < 0) {
2390
** If this is an "uninteresting picture" ignore it.
2393
while (LWZReadByte(fd, FALSE, c) >= 0)
2398
while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
2399
/* This how we recognize which colors are actually used. */
2403
gdImageSetPixel(im, xpos, ypos, v);
2418
if (ypos >= height) {
2440
if (LWZReadByte(fd,FALSE,c)>=0) {
2445
void gdImageRectangle(im, x1, y1, x2, y2, color)
2453
gdImageLine(im, x1, y1, x2, y1, color);
2454
gdImageLine(im, x1, y2, x2, y2, color);
2455
gdImageLine(im, x1, y1, x1, y2, color);
2456
gdImageLine(im, x2, y1, x2, y2, color);
2458
void gdImageThickRectangle(im, x1, y1, x2, y2, color, thick)
2467
gdImageThickLine(im, x1, y1, x2, y1, color, thick);
2468
gdImageThickLine(im, x1, y2, x2, y2, color, thick);
2469
gdImageThickLine(im, x1, y1, x1, y2, color, thick);
2470
gdImageThickLine(im, x2, y1, x2, y2, color, thick);
2473
void gdImageFilledRectangle(im, x1, y1, x2, y2, color)
2482
for (y=y1; (y<=y2); y++) {
2483
for (x=x1; (x<=x2); x++) {
2484
gdImageSetPixel(im, x, y, color);
2489
void gdImageCopy(dst, src, dstX, dstY, srcX, srcY, w, h)
2503
int colorMap[gdMaxColors];
2504
for (i=0; (i<gdMaxColors); i++) {
2508
for (y=srcY; (y < (srcY + h)); y++) {
2510
for (x=srcX; (x < (srcX + w)); x++) {
2512
c = gdImageGetPixel(src, x, y);
2513
/* Added 7/24/95: support transparent copies */
2514
if (gdImageGetTransparent(src) == c) {
2518
/* Have we established a mapping for this color? */
2519
if (colorMap[c] == (-1)) {
2520
/* If it's the same image, mapping is trivial */
2524
/* First look for an exact match */
2525
nc = gdImageColorExact(dst,
2526
src->red[c], src->green[c],
2530
/* No, so try to allocate it */
2531
nc = gdImageColorAllocate(dst,
2532
src->red[c], src->green[c],
2534
/* If we're out of colors, go for the
2537
nc = gdImageColorClosest(dst,
2538
src->red[c], src->green[c],
2544
gdImageSetPixel(dst, tox, toy, colorMap[c]);
2551
void gdImageCopyResized(dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH)
2568
int colorMap[gdMaxColors];
2569
/* Stretch vectors */
2572
/* We only need to use floating point to determine the correct
2573
stretch vector for one line's worth. */
2575
stx = (int *) malloc(sizeof(int) * srcW);
2576
sty = (int *) malloc(sizeof(int) * srcH);
2578
for (i=0; (i < srcW); i++) {
2580
accum += (double)dstW/(double)srcW;
2581
got = (int)floor(accum);
2586
for (i=0; (i < srcH); i++) {
2588
accum += (double)dstH/(double)srcH;
2589
got = (int)floor(accum);
2593
for (i=0; (i<gdMaxColors); i++) {
2597
for (y=srcY; (y < (srcY + srcH)); y++) {
2598
for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
2600
for (x=srcX; (x < (srcX + srcW)); x++) {
2602
if (!stx[x - srcX]) {
2605
c = gdImageGetPixel(src, x, y);
2606
/* Added 7/24/95: support transparent copies */
2607
if (gdImageGetTransparent(src) == c) {
2611
/* Have we established a mapping for this color? */
2612
if (colorMap[c] == (-1)) {
2613
/* If it's the same image, mapping is trivial */
2617
/* First look for an exact match */
2618
nc = gdImageColorExact(dst,
2619
src->red[c], src->green[c],
2623
/* No, so try to allocate it */
2624
nc = gdImageColorAllocate(dst,
2625
src->red[c], src->green[c],
2627
/* If we're out of colors, go for the
2630
nc = gdImageColorClosest(dst,
2631
src->red[c], src->green[c],
2637
for (i=0; (i < stx[x - srcX]); i++) {
2638
gdImageSetPixel(dst, tox, toy, colorMap[c]);
2649
int gdGetWord(result, in)
2667
void gdPutWord(w, out)
2671
putc((unsigned char)(w >> 8), out);
2672
putc((unsigned char)(w & 0xFF), out);
2675
int gdGetByte(result, in)
2688
gdImagePtr gdImageCreateFromGd(in)
2695
if (!gdGetWord(&sx, in)) {
2698
if (!gdGetWord(&sy, in)) {
2701
im = gdImageCreate(sx, sy);
2702
if (!gdGetByte(&im->colorsTotal, in)) {
2705
if (!gdGetWord(&im->transparent, in)) {
2708
if (im->transparent == 257) {
2709
im->transparent = (-1);
2711
for (i=0; (i<gdMaxColors); i++) {
2712
if (!gdGetByte(&im->red[i], in)) {
2715
if (!gdGetByte(&im->green[i], in)) {
2718
if (!gdGetByte(&im->blue[i], in)) {
2722
for (y=0; (y<sy); y++) {
2723
for (x=0; (x<sx); x++) {
2730
/* ROW-MAJOR IN GD 1.3 */
2731
im->pixels[y][x] = ch;
2741
void gdImageGd(im, out)
2748
gdPutWord(im->sx, out);
2749
gdPutWord(im->sy, out);
2750
putc((unsigned char)im->colorsTotal, out);
2751
trans = im->transparent;
2752
if (trans == (-1)) {
2755
gdPutWord(trans, out);
2756
for (i=0; (i<gdMaxColors); i++) {
2757
putc((unsigned char)im->red[i], out);
2758
putc((unsigned char)im->green[i], out);
2759
putc((unsigned char)im->blue[i], out);
2761
for (y=0; (y < im->sy); y++) {
2762
for (x=0; (x < im->sx); x++) {
2763
/* ROW-MAJOR IN GD 1.3 */
2764
putc((unsigned char)im->pixels[y][x], out);
2770
gdImageCreateFromXbm(fd)
2781
if (!fgets(s, 160, fd)) {
2786
sp = strchr(sp, ' ');
2790
/* Skip width label */
2792
sp = strchr(sp, ' ');
2801
if (!fgets(s, 160, fd)) {
2806
sp = strchr(sp, ' ');
2810
/* Skip height label */
2812
sp = strchr(sp, ' ');
2821
/* Skip declaration line */
2822
if (!fgets(s, 160, fd)) {
2825
bytes = ((w * h) / 8) + 1;
2826
im = gdImageCreate(w, h);
2827
gdImageColorAllocate(im, 255, 255, 255);
2828
gdImageColorAllocate(im, 0, 0, 0);
2831
for (i=0; (i < bytes); i++) {
2834
/* Skip spaces, commas, CRs, 0x */
2856
sscanf(h, "%x", &b);
2857
for (bit = 1; (bit <= 128); (bit = bit << 1)) {
2858
gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
2870
/* Shouldn't happen */
2871
/* fprintf(stderr, "Error: bug in gdImageCreateFromXbm x=%d,sx=%d,y=%dsy=%d!\n",x,im->sx,y,im->sy);*/
2878
void gdImagePolygon(im, p, n, c)
2891
gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
2892
for (i=1; (i < n); i++) {
2894
gdImageLine(im, lx, ly, p->x, p->y, c);
2901
void gdImageFilledPolygon(im,p,n,c)
2902
gdImagePtr im; gdPointPtr p; int n; int c;
2914
if (!im->polyAllocated) {
2915
im->polyInts = (int *) malloc(sizeof(int) * n);
2916
im->polyAllocated = n;
2918
if (im->polyAllocated < n) {
2919
while (im->polyAllocated < n) {
2920
im->polyAllocated *= 2;
2922
im->polyInts = (int *) realloc(im->polyInts,
2923
sizeof(int) * im->polyAllocated);
2927
for (i=1; (i < n); i++) {
2928
if (p[i].y < miny) {
2931
if (p[i].y > maxy) {
2935
/* Fix in 1.3: count a vertex only once */
2936
for (y=miny; (y <= maxy); y++) {
2937
/*1.4 int interLast = 0; */
2938
/* int dirLast = 0; */
2939
/* int interFirst = 1; */
2941
for (i=0; (i < n); i++) {
2954
} else if (y1 > y2) {
2962
if ((y >= y1) && (y < y2)) {
2963
im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2964
} else if ((y == maxy) && (y > y1) && (y <= y2)) {
2965
im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2968
qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
2970
for (i=0; (i < (ints)); i+=2) {
2971
gdImageLine(im, im->polyInts[i], y,
2972
im->polyInts[i+1], y, c);
2976
int gdCompareInt(a, b)
2982
/* return (*(const int *)a) - (*(const int *)b); */
2983
return (*(int *)a) - (*(int *)b);
2986
void gdImageSetStyle(im, style, noOfPixels)
2995
malloc(sizeof(int) * noOfPixels);
2996
memcpy(im->style, style, sizeof(int) * noOfPixels);
2997
im->styleLength = noOfPixels;
3001
void gdImageSetBrush(im, brush)
3007
for (i=0; (i < gdImageColorsTotal(brush)); i++) {
3009
index = gdImageColorExact(im,
3010
gdImageRed(brush, i),
3011
gdImageGreen(brush, i),
3012
gdImageBlue(brush, i));
3013
if (index == (-1)) {
3014
index = gdImageColorAllocate(im,
3015
gdImageRed(brush, i),
3016
gdImageGreen(brush, i),
3017
gdImageBlue(brush, i));
3018
if (index == (-1)) {
3019
index = gdImageColorClosest(im,
3020
gdImageRed(brush, i),
3021
gdImageGreen(brush, i),
3022
gdImageBlue(brush, i));
3025
im->brushColorMap[i] = index;
3029
void gdImageSetTile(im, tile)
3035
for (i=0; (i < gdImageColorsTotal(tile)); i++) {
3037
index = gdImageColorExact(im,
3038
gdImageRed(tile, i),
3039
gdImageGreen(tile, i),
3040
gdImageBlue(tile, i));
3041
if (index == (-1)) {
3042
index = gdImageColorAllocate(im,
3043
gdImageRed(tile, i),
3044
gdImageGreen(tile, i),
3045
gdImageBlue(tile, i));
3046
if (index == (-1)) {
3047
index = gdImageColorClosest(im,
3048
gdImageRed(tile, i),
3049
gdImageGreen(tile, i),
3050
gdImageBlue(tile, i));
3053
im->tileColorMap[i] = index;
3057
void gdImageInterlace(im, interlaceArg)
3061
im->interlace = interlaceArg;
3064
/*SG added function to change a given color with another */
3065
void gdImageChangeColor(im, old, new)
3071
for (y=0; (y < im->sy); y++) {
3072
for (x=0; (x < im->sx); x++) {
3073
if (im->pixels[y][x]==old)
3074
im->pixels[y][x]=new;