mimetexrb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/extconf.rb +7 -0
- data/ext/src/gifsave.c +1123 -0
- data/ext/src/mimetex.c +14960 -0
- data/ext/src/mimetex.h +2017 -0
- data/ext/src/mimetex.html +3750 -0
- data/ext/src/mimetexrb.c +70 -0
- data/ext/src/texfonts.h +54343 -0
- data/gemspec.rb +18 -0
- metadata +53 -0
data/ext/extconf.rb
ADDED
data/ext/src/gifsave.c
ADDED
@@ -0,0 +1,1123 @@
|
|
1
|
+
/* $Id: gifsave.c,v 1.2 1998/07/05 16:29:56 sverrehu Exp $ */
|
2
|
+
/**************************************************************************
|
3
|
+
*
|
4
|
+
* FILE gifsave.c
|
5
|
+
*
|
6
|
+
* DESCRIPTION Routines to create a GIF-file. See README for
|
7
|
+
* a description.
|
8
|
+
*
|
9
|
+
* The functions were originally written using Borland's
|
10
|
+
* C-compiler on an IBM PC -compatible computer, but they
|
11
|
+
* are compiled and tested on Linux and SunOS as well.
|
12
|
+
*
|
13
|
+
* WRITTEN BY Sverre H. Huseby <sverrehu@online.no>
|
14
|
+
*
|
15
|
+
**************************************************************************/
|
16
|
+
|
17
|
+
#include <stdlib.h>
|
18
|
+
#include <stdio.h>
|
19
|
+
/* #include <unistd.h> */ /* (added by j.forkosh) to get STDOUT_FILENO*/
|
20
|
+
#include <string.h> /* " */
|
21
|
+
/* --- windows-specific header info --- */
|
22
|
+
#ifndef WINDOWS /* -DWINDOWS not supplied by user */
|
23
|
+
#if defined(_WINDOWS) || defined(_WIN32) || defined(WIN32) \
|
24
|
+
|| defined(DJGPP) /* try to recognize windows compilers */ \
|
25
|
+
|| defined(_USRDLL) /* must be WINDOWS if compiling for DLL */
|
26
|
+
#define WINDOWS /* signal windows */
|
27
|
+
#endif
|
28
|
+
#endif
|
29
|
+
#ifdef WINDOWS /* " if filename=NULL passed to GIF_Create()*/
|
30
|
+
#include <fcntl.h> /* " OutFile=stdout used. But Windows opens*/
|
31
|
+
#include <io.h> /* " stdout in char mode, and precedes every*/
|
32
|
+
/* " 0x0A with spurious 0x0D. */
|
33
|
+
#if defined(_O_BINARY) && !defined(O_BINARY) /* only have _O_BINARY */
|
34
|
+
#define O_BINARY _O_BINARY /* make O_BINARY available, etc... */
|
35
|
+
#define setmode _setmode
|
36
|
+
#define fileno _fileno
|
37
|
+
#endif
|
38
|
+
#if defined(_O_BINARY) || defined(O_BINARY) /* setmode() now available */
|
39
|
+
#define HAVE_SETMODE /* so we'll use setmode() */
|
40
|
+
#endif
|
41
|
+
#endif
|
42
|
+
|
43
|
+
/* #include "gifsave.h" */ /* (j.forkosh) explcitly include header */
|
44
|
+
enum GIF_Code {
|
45
|
+
GIF_OK = 0,
|
46
|
+
GIF_ERRCREATE,
|
47
|
+
GIF_ERRWRITE,
|
48
|
+
GIF_OUTMEM
|
49
|
+
};
|
50
|
+
|
51
|
+
int GIF_Create(char *buffer, int width, int height,
|
52
|
+
int numcolors, int colorres);
|
53
|
+
void GIF_SetColor(int colornum, int red, int green, int blue);
|
54
|
+
void GIF_SetTransparent(int colornum); /* (added by j.forkosh) */
|
55
|
+
int GIF_CompressImage(int left, int top, int width, int height,
|
56
|
+
int (*getpixel)(int x, int y));
|
57
|
+
int GIF_Close(void);
|
58
|
+
/* --- end-of-header gifsave.h --- */
|
59
|
+
|
60
|
+
|
61
|
+
/**************************************************************************
|
62
|
+
* *
|
63
|
+
* P R I V A T E D A T A *
|
64
|
+
* *
|
65
|
+
**************************************************************************/
|
66
|
+
|
67
|
+
typedef unsigned Word; /* at least two bytes (16 bits) */
|
68
|
+
typedef unsigned char Byte; /* exactly one byte (8 bits) */
|
69
|
+
|
70
|
+
/* used by IO-routines */
|
71
|
+
static FILE *OutFile = NULL; /* file to write to */
|
72
|
+
static Byte *OutBuffer = NULL; /* (added by j.forkosh) */
|
73
|
+
static int isCloseOutFile = 0; /* " */
|
74
|
+
#if !defined(MAXGIFSZ) /* " */
|
75
|
+
#define MAXGIFSZ 131072 /* " max #bytes comprising gif image */
|
76
|
+
#endif /* " */
|
77
|
+
int gifSize = 0; /* " #bytes comprising gif */
|
78
|
+
int maxgifSize = MAXGIFSZ; /* " max #bytes written to OutBuffer */
|
79
|
+
|
80
|
+
/* used when writing to a file bitwise */
|
81
|
+
static Byte Buffer[256]; /* there must be one more than `needed' */
|
82
|
+
static int Index, /* current byte in buffer */
|
83
|
+
BitsLeft; /* bits left to fill in current byte. These
|
84
|
+
* are right-justified */
|
85
|
+
|
86
|
+
/* used by routines maintaining an LZW string table */
|
87
|
+
#define RES_CODES 2
|
88
|
+
|
89
|
+
#define HASH_FREE 0xFFFF
|
90
|
+
#define NEXT_FIRST 0xFFFF
|
91
|
+
|
92
|
+
#define MAXBITS 12
|
93
|
+
#define MAXSTR (1 << MAXBITS)
|
94
|
+
|
95
|
+
#define HASHSIZE 9973
|
96
|
+
#define HASHSTEP 2039
|
97
|
+
|
98
|
+
#define HASH(index, lastbyte) (((lastbyte << 8) ^ index) % HASHSIZE)
|
99
|
+
|
100
|
+
static Byte *StrChr = NULL;
|
101
|
+
static Word *StrNxt = NULL,
|
102
|
+
*StrHsh = NULL,
|
103
|
+
NumStrings;
|
104
|
+
|
105
|
+
/* used in the main routines */
|
106
|
+
typedef struct {
|
107
|
+
Word LocalScreenWidth,
|
108
|
+
LocalScreenHeight;
|
109
|
+
Byte GlobalColorTableSize : 3,
|
110
|
+
SortFlag : 1,
|
111
|
+
ColorResolution : 3,
|
112
|
+
GlobalColorTableFlag : 1;
|
113
|
+
Byte BackgroundColorIndex;
|
114
|
+
Byte PixelAspectRatio;
|
115
|
+
} ScreenDescriptor;
|
116
|
+
|
117
|
+
typedef struct {
|
118
|
+
Byte Separator;
|
119
|
+
Word LeftPosition,
|
120
|
+
TopPosition;
|
121
|
+
Word Width,
|
122
|
+
Height;
|
123
|
+
Byte LocalColorTableSize : 3,
|
124
|
+
Reserved : 2,
|
125
|
+
SortFlag : 1,
|
126
|
+
InterlaceFlag : 1,
|
127
|
+
LocalColorTableFlag : 1;
|
128
|
+
} ImageDescriptor;
|
129
|
+
|
130
|
+
static int BitsPrPrimColor, /* bits pr primary color */
|
131
|
+
NumColors; /* number of colors in color table */
|
132
|
+
static int TransparentColorIndex=(-1); /* (added by j.forkosh) */
|
133
|
+
static Byte *ColorTable = NULL;
|
134
|
+
static Word ScreenHeight,
|
135
|
+
ScreenWidth,
|
136
|
+
ImageHeight,
|
137
|
+
ImageWidth,
|
138
|
+
ImageLeft,
|
139
|
+
ImageTop,
|
140
|
+
RelPixX, RelPixY; /* used by InputByte() -function */
|
141
|
+
static int (*GetPixel)(int x, int y);
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
/**************************************************************************
|
146
|
+
* *
|
147
|
+
* P R I V A T E F U N C T I O N S *
|
148
|
+
* *
|
149
|
+
**************************************************************************/
|
150
|
+
|
151
|
+
/*========================================================================*
|
152
|
+
= Routines to do file IO =
|
153
|
+
*========================================================================*/
|
154
|
+
|
155
|
+
/*-------------------------------------------------------------------------
|
156
|
+
*
|
157
|
+
* NAME Create
|
158
|
+
*
|
159
|
+
* DESCRIPTION Creates a new file, and enables referencing using the
|
160
|
+
* global variable OutFile. This variable is only used
|
161
|
+
* by these IO-functions, making it relatively simple to
|
162
|
+
* rewrite file IO.
|
163
|
+
*
|
164
|
+
* INPUT filename
|
165
|
+
* name of file to create,
|
166
|
+
* or NULL for stdout,
|
167
|
+
* or if *filename='\000' then it's the address of
|
168
|
+
* a memory buffer to which gif will be written
|
169
|
+
*
|
170
|
+
* RETURNS GIF_OK - OK
|
171
|
+
* GIF_ERRWRITE - Error opening the file
|
172
|
+
*/
|
173
|
+
static int Create(char *buffer) {
|
174
|
+
OutBuffer = NULL; /* (added by j.forkosh) */
|
175
|
+
isCloseOutFile = 0; /* " */
|
176
|
+
|
177
|
+
char *filename = NULL;
|
178
|
+
if (filename == NULL) {
|
179
|
+
// OutFile = stdout; /* " */
|
180
|
+
OutBuffer = (Byte *)buffer; /* " */
|
181
|
+
/*OutFile = fdopen(STDOUT_FILENO,"wb");*//* " doesn't work, */
|
182
|
+
#ifdef WINDOWS /* " so instead... */
|
183
|
+
#ifdef HAVE_SETMODE /* " try to use setmode()*/
|
184
|
+
if ( setmode ( fileno (stdout), O_BINARY) /* to set stdout */
|
185
|
+
== -1 ); /* handle error *//* " to binary mode */
|
186
|
+
#else /* " setmode not available */
|
187
|
+
#if 1 /* " */
|
188
|
+
freopen ("CON", "wb", stdout); /* " freopen stdout binary */
|
189
|
+
#else /* " */
|
190
|
+
stdout = fdopen (STDOUT_FILENO, "wb"); /*fdopen stdout binary*/
|
191
|
+
#endif /* " */
|
192
|
+
#endif /* " */
|
193
|
+
#endif /* " */
|
194
|
+
} else if ( *filename != '\000') {
|
195
|
+
if ((OutFile = fopen(filename, "wb")) == NULL)
|
196
|
+
return GIF_ERRCREATE;
|
197
|
+
isCloseOutFile = 1;
|
198
|
+
} else {
|
199
|
+
OutBuffer = (Byte *)filename; /* " */
|
200
|
+
}
|
201
|
+
return GIF_OK;
|
202
|
+
}
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
/*-------------------------------------------------------------------------
|
207
|
+
*
|
208
|
+
* NAME Write
|
209
|
+
*
|
210
|
+
* DESCRIPTION Output bytes to the current OutFile.
|
211
|
+
*
|
212
|
+
* INPUT buf pointer to buffer to write
|
213
|
+
* len number of bytes to write
|
214
|
+
*
|
215
|
+
* RETURNS GIF_OK - OK
|
216
|
+
* GIF_ERRWRITE - Error writing to the file
|
217
|
+
*/
|
218
|
+
static int
|
219
|
+
Write(const void *buf, unsigned len)
|
220
|
+
{
|
221
|
+
if ( OutBuffer == NULL ) /* (added by j.forkosh) */
|
222
|
+
{ if (fwrite(buf, sizeof(Byte), len, OutFile) < len)
|
223
|
+
return GIF_ERRWRITE; }
|
224
|
+
else { /* (added by j.forkosh) */
|
225
|
+
if ( gifSize+len <= maxgifSize ) /* " */
|
226
|
+
memcpy(OutBuffer+gifSize,buf,len); } /* " */
|
227
|
+
gifSize += len; /* " */
|
228
|
+
return GIF_OK;
|
229
|
+
}
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
/*-------------------------------------------------------------------------
|
234
|
+
*
|
235
|
+
* NAME WriteByte
|
236
|
+
*
|
237
|
+
* DESCRIPTION Output one byte to the current OutFile.
|
238
|
+
*
|
239
|
+
* INPUT b byte to write
|
240
|
+
*
|
241
|
+
* RETURNS GIF_OK - OK
|
242
|
+
* GIF_ERRWRITE - Error writing to the file
|
243
|
+
*/
|
244
|
+
static int
|
245
|
+
WriteByte(Byte b)
|
246
|
+
{
|
247
|
+
if ( OutBuffer == NULL ) /* (added by j.forkosh) */
|
248
|
+
{ if (putc(b, OutFile) == EOF)
|
249
|
+
return GIF_ERRWRITE; }
|
250
|
+
else /* (added by j.forkosh) */
|
251
|
+
{ if ( gifSize < maxgifSize ) /* " */
|
252
|
+
OutBuffer[gifSize] = b; } /* " */
|
253
|
+
gifSize++; /* " */
|
254
|
+
return GIF_OK;
|
255
|
+
}
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
/*-------------------------------------------------------------------------
|
260
|
+
*
|
261
|
+
* NAME WriteWord
|
262
|
+
*
|
263
|
+
* DESCRIPTION Output one word (2 bytes with byte-swapping, like on
|
264
|
+
* the IBM PC) to the current OutFile.
|
265
|
+
*
|
266
|
+
* INPUT w word to write
|
267
|
+
*
|
268
|
+
* RETURNS GIF_OK - OK
|
269
|
+
* GIF_ERRWRITE - Error writing to the file
|
270
|
+
*/
|
271
|
+
static int
|
272
|
+
WriteWord(Word w)
|
273
|
+
{
|
274
|
+
if ( OutBuffer == NULL ) /* (added by j.forkosh) */
|
275
|
+
{ if (putc(w & 0xFF, OutFile) == EOF)
|
276
|
+
return GIF_ERRWRITE;
|
277
|
+
if (putc((w >> 8), OutFile) == EOF)
|
278
|
+
return GIF_ERRWRITE; }
|
279
|
+
else /* (added by j.forkosh) */
|
280
|
+
if ( gifSize+1 < maxgifSize ) /* " */
|
281
|
+
{ OutBuffer[gifSize] = (Byte)(w & 0xFF); /* " */
|
282
|
+
OutBuffer[gifSize+1] = (Byte)(w >> 8); } /* " */
|
283
|
+
gifSize += 2; /* " */
|
284
|
+
return GIF_OK;
|
285
|
+
}
|
286
|
+
|
287
|
+
|
288
|
+
|
289
|
+
/*-------------------------------------------------------------------------
|
290
|
+
*
|
291
|
+
* NAME Close
|
292
|
+
*
|
293
|
+
* DESCRIPTION Close current OutFile.
|
294
|
+
*/
|
295
|
+
static void
|
296
|
+
Close(void)
|
297
|
+
{
|
298
|
+
if ( isCloseOutFile ) /* (added by j.forkosh) */
|
299
|
+
fclose(OutFile);
|
300
|
+
OutBuffer = NULL; /* (added by j.forkosh) */
|
301
|
+
isCloseOutFile = 0; /* " */
|
302
|
+
}
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
|
308
|
+
/*========================================================================*
|
309
|
+
= =
|
310
|
+
= Routines to write a bit-file =
|
311
|
+
= =
|
312
|
+
*========================================================================*/
|
313
|
+
|
314
|
+
/*-------------------------------------------------------------------------
|
315
|
+
*
|
316
|
+
* NAME InitBitFile
|
317
|
+
*
|
318
|
+
* DESCRIPTION Initiate for using a bitfile. All output is sent to
|
319
|
+
* the current OutFile using the I/O-routines above.
|
320
|
+
*/
|
321
|
+
static void
|
322
|
+
InitBitFile(void)
|
323
|
+
{
|
324
|
+
Buffer[Index = 0] = 0;
|
325
|
+
BitsLeft = 8;
|
326
|
+
}
|
327
|
+
|
328
|
+
|
329
|
+
|
330
|
+
/*-------------------------------------------------------------------------
|
331
|
+
*
|
332
|
+
* NAME ResetOutBitFile
|
333
|
+
*
|
334
|
+
* DESCRIPTION Tidy up after using a bitfile
|
335
|
+
*
|
336
|
+
* RETURNS 0 - OK, -1 - error
|
337
|
+
*/
|
338
|
+
static int
|
339
|
+
ResetOutBitFile(void)
|
340
|
+
{
|
341
|
+
Byte numbytes;
|
342
|
+
|
343
|
+
/* how much is in the buffer? */
|
344
|
+
numbytes = Index + (BitsLeft == 8 ? 0 : 1);
|
345
|
+
|
346
|
+
/* write whatever is in the buffer to the file */
|
347
|
+
if (numbytes) {
|
348
|
+
if (WriteByte(numbytes) != GIF_OK)
|
349
|
+
return -1;
|
350
|
+
|
351
|
+
if (Write(Buffer, numbytes) != GIF_OK)
|
352
|
+
return -1;
|
353
|
+
|
354
|
+
Buffer[Index = 0] = 0;
|
355
|
+
BitsLeft = 8;
|
356
|
+
}
|
357
|
+
return 0;
|
358
|
+
}
|
359
|
+
|
360
|
+
|
361
|
+
|
362
|
+
/*-------------------------------------------------------------------------
|
363
|
+
*
|
364
|
+
* NAME WriteBits
|
365
|
+
*
|
366
|
+
* DESCRIPTION Put the given number of bits to the outfile.
|
367
|
+
*
|
368
|
+
* INPUT bits bits to write from (right justified)
|
369
|
+
* numbits number of bits to write
|
370
|
+
*
|
371
|
+
* RETURNS bits written, or -1 on error.
|
372
|
+
*
|
373
|
+
*/
|
374
|
+
static int
|
375
|
+
WriteBits(int bits, int numbits)
|
376
|
+
{
|
377
|
+
int bitswritten = 0;
|
378
|
+
Byte numbytes = 255;
|
379
|
+
|
380
|
+
do {
|
381
|
+
/* if the buffer is full, write it */
|
382
|
+
if ((Index == 254 && !BitsLeft) || Index > 254) {
|
383
|
+
if (WriteByte(numbytes) != GIF_OK)
|
384
|
+
return -1;
|
385
|
+
|
386
|
+
if (Write(Buffer, numbytes) != GIF_OK)
|
387
|
+
return -1;
|
388
|
+
|
389
|
+
Buffer[Index = 0] = 0;
|
390
|
+
BitsLeft = 8;
|
391
|
+
}
|
392
|
+
|
393
|
+
/* now take care of the two specialcases */
|
394
|
+
if (numbits <= BitsLeft) {
|
395
|
+
Buffer[Index] |= (bits & ((1 << numbits) - 1)) << (8 - BitsLeft);
|
396
|
+
bitswritten += numbits;
|
397
|
+
BitsLeft -= numbits;
|
398
|
+
numbits = 0;
|
399
|
+
} else {
|
400
|
+
Buffer[Index] |= (bits & ((1 << BitsLeft) - 1)) << (8 - BitsLeft);
|
401
|
+
bitswritten += BitsLeft;
|
402
|
+
bits >>= BitsLeft;
|
403
|
+
numbits -= BitsLeft;
|
404
|
+
|
405
|
+
Buffer[++Index] = 0;
|
406
|
+
BitsLeft = 8;
|
407
|
+
}
|
408
|
+
} while (numbits);
|
409
|
+
|
410
|
+
return bitswritten;
|
411
|
+
}
|
412
|
+
|
413
|
+
|
414
|
+
|
415
|
+
/*========================================================================*
|
416
|
+
= Routines to maintain an LZW-string table =
|
417
|
+
*========================================================================*/
|
418
|
+
|
419
|
+
/*-------------------------------------------------------------------------
|
420
|
+
*
|
421
|
+
* NAME FreeStrtab
|
422
|
+
*
|
423
|
+
* DESCRIPTION Free arrays used in string table routines
|
424
|
+
*/
|
425
|
+
static void
|
426
|
+
FreeStrtab(void)
|
427
|
+
{
|
428
|
+
if (StrHsh) {
|
429
|
+
free(StrHsh);
|
430
|
+
StrHsh = NULL;
|
431
|
+
}
|
432
|
+
if (StrNxt) {
|
433
|
+
free(StrNxt);
|
434
|
+
StrNxt = NULL;
|
435
|
+
}
|
436
|
+
if (StrChr) {
|
437
|
+
free(StrChr);
|
438
|
+
StrChr = NULL;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
|
442
|
+
|
443
|
+
|
444
|
+
/*-------------------------------------------------------------------------
|
445
|
+
*
|
446
|
+
* NAME AllocStrtab
|
447
|
+
*
|
448
|
+
* DESCRIPTION Allocate arrays used in string table routines
|
449
|
+
*
|
450
|
+
* RETURNS GIF_OK - OK
|
451
|
+
* GIF_OUTMEM - Out of memory
|
452
|
+
*/
|
453
|
+
static int
|
454
|
+
AllocStrtab(void)
|
455
|
+
{
|
456
|
+
/* just in case */
|
457
|
+
FreeStrtab();
|
458
|
+
|
459
|
+
if ((StrChr = (Byte *) malloc(MAXSTR * sizeof(Byte))) == 0) {
|
460
|
+
FreeStrtab();
|
461
|
+
return GIF_OUTMEM;
|
462
|
+
}
|
463
|
+
if ((StrNxt = (Word *) malloc(MAXSTR * sizeof(Word))) == 0) {
|
464
|
+
FreeStrtab();
|
465
|
+
return GIF_OUTMEM;
|
466
|
+
}
|
467
|
+
if ((StrHsh = (Word *) malloc(HASHSIZE * sizeof(Word))) == 0) {
|
468
|
+
FreeStrtab();
|
469
|
+
return GIF_OUTMEM;
|
470
|
+
}
|
471
|
+
return GIF_OK;
|
472
|
+
}
|
473
|
+
|
474
|
+
|
475
|
+
|
476
|
+
/*-------------------------------------------------------------------------
|
477
|
+
*
|
478
|
+
* NAME AddCharString
|
479
|
+
*
|
480
|
+
* DESCRIPTION Add a string consisting of the string of index plus
|
481
|
+
* the byte b.
|
482
|
+
*
|
483
|
+
* If a string of length 1 is wanted, the index should
|
484
|
+
* be 0xFFFF.
|
485
|
+
*
|
486
|
+
* INPUT index index to first part of string, or 0xFFFF is
|
487
|
+
* only 1 byte is wanted
|
488
|
+
* b last byte in new string
|
489
|
+
*
|
490
|
+
* RETURNS Index to new string, or 0xFFFF if no more room
|
491
|
+
*/
|
492
|
+
static Word
|
493
|
+
AddCharString(Word index, Byte b)
|
494
|
+
{
|
495
|
+
Word hshidx;
|
496
|
+
|
497
|
+
/* check if there is more room */
|
498
|
+
if (NumStrings >= MAXSTR)
|
499
|
+
return 0xFFFF;
|
500
|
+
|
501
|
+
/* search the string table until a free position is found */
|
502
|
+
hshidx = HASH(index, b);
|
503
|
+
while (StrHsh[hshidx] != 0xFFFF)
|
504
|
+
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
|
505
|
+
|
506
|
+
/* insert new string */
|
507
|
+
StrHsh[hshidx] = NumStrings;
|
508
|
+
StrChr[NumStrings] = b;
|
509
|
+
StrNxt[NumStrings] = (index != 0xFFFF) ? index : NEXT_FIRST;
|
510
|
+
|
511
|
+
return NumStrings++;
|
512
|
+
}
|
513
|
+
|
514
|
+
|
515
|
+
|
516
|
+
/*-------------------------------------------------------------------------
|
517
|
+
*
|
518
|
+
* NAME FindCharString
|
519
|
+
*
|
520
|
+
* DESCRIPTION Find index of string consisting of the string of index
|
521
|
+
* plus the byte b.
|
522
|
+
*
|
523
|
+
* If a string of length 1 is wanted, the index should
|
524
|
+
* be 0xFFFF.
|
525
|
+
*
|
526
|
+
* INPUT index index to first part of string, or 0xFFFF is
|
527
|
+
* only 1 byte is wanted
|
528
|
+
* b last byte in string
|
529
|
+
*
|
530
|
+
* RETURNS Index to string, or 0xFFFF if not found
|
531
|
+
*/
|
532
|
+
static Word
|
533
|
+
FindCharString(Word index, Byte b)
|
534
|
+
{
|
535
|
+
Word hshidx, nxtidx;
|
536
|
+
|
537
|
+
/* check if index is 0xFFFF. in that case we need only return b,
|
538
|
+
* since all one-character strings has their bytevalue as their
|
539
|
+
* index */
|
540
|
+
if (index == 0xFFFF)
|
541
|
+
return b;
|
542
|
+
|
543
|
+
/* search the string table until the string is found, or we find
|
544
|
+
* HASH_FREE. in that case the string does not exist. */
|
545
|
+
hshidx = HASH(index, b);
|
546
|
+
while ((nxtidx = StrHsh[hshidx]) != 0xFFFF) {
|
547
|
+
if (StrNxt[nxtidx] == index && StrChr[nxtidx] == b)
|
548
|
+
return nxtidx;
|
549
|
+
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
|
550
|
+
}
|
551
|
+
|
552
|
+
/* no match is found */
|
553
|
+
return 0xFFFF;
|
554
|
+
}
|
555
|
+
|
556
|
+
|
557
|
+
|
558
|
+
/*-------------------------------------------------------------------------
|
559
|
+
*
|
560
|
+
* NAME ClearStrtab
|
561
|
+
*
|
562
|
+
* DESCRIPTION Mark the entire table as free, enter the 2**codesize
|
563
|
+
* one-byte strings, and reserve the RES_CODES reserved
|
564
|
+
* codes.
|
565
|
+
*
|
566
|
+
* INPUT codesize
|
567
|
+
* number of bits to encode one pixel
|
568
|
+
*/
|
569
|
+
static void
|
570
|
+
ClearStrtab(int codesize)
|
571
|
+
{
|
572
|
+
int q, w;
|
573
|
+
Word *wp;
|
574
|
+
|
575
|
+
/* no strings currently in the table */
|
576
|
+
NumStrings = 0;
|
577
|
+
|
578
|
+
/* mark entire hashtable as free */
|
579
|
+
wp = StrHsh;
|
580
|
+
for (q = 0; q < HASHSIZE; q++)
|
581
|
+
*wp++ = HASH_FREE;
|
582
|
+
|
583
|
+
/* insert 2**codesize one-character strings, and reserved codes */
|
584
|
+
w = (1 << codesize) + RES_CODES;
|
585
|
+
for (q = 0; q < w; q++)
|
586
|
+
AddCharString(0xFFFF, q);
|
587
|
+
}
|
588
|
+
|
589
|
+
|
590
|
+
|
591
|
+
/*========================================================================*
|
592
|
+
= LZW compression routine =
|
593
|
+
*========================================================================*/
|
594
|
+
|
595
|
+
/*-------------------------------------------------------------------------
|
596
|
+
*
|
597
|
+
* NAME LZW_Compress
|
598
|
+
*
|
599
|
+
* DESCRIPTION Perform LZW compression as specified in the
|
600
|
+
* GIF-standard.
|
601
|
+
*
|
602
|
+
* INPUT codesize
|
603
|
+
* number of bits needed to represent
|
604
|
+
* one pixelvalue.
|
605
|
+
* inputbyte
|
606
|
+
* function that fetches each byte to compress.
|
607
|
+
* must return -1 when no more bytes.
|
608
|
+
*
|
609
|
+
* RETURNS GIF_OK - OK
|
610
|
+
* GIF_OUTMEM - Out of memory
|
611
|
+
*/
|
612
|
+
static int
|
613
|
+
LZW_Compress(int codesize, int (*inputbyte)(void))
|
614
|
+
{
|
615
|
+
register int c;
|
616
|
+
register Word index;
|
617
|
+
int clearcode, endofinfo, numbits, limit, errcode;
|
618
|
+
Word prefix = 0xFFFF;
|
619
|
+
|
620
|
+
/* set up the given outfile */
|
621
|
+
InitBitFile();
|
622
|
+
|
623
|
+
/* set up variables and tables */
|
624
|
+
clearcode = 1 << codesize;
|
625
|
+
endofinfo = clearcode + 1;
|
626
|
+
|
627
|
+
numbits = codesize + 1;
|
628
|
+
limit = (1 << numbits) - 1;
|
629
|
+
|
630
|
+
if ((errcode = AllocStrtab()) != GIF_OK)
|
631
|
+
return errcode;
|
632
|
+
ClearStrtab(codesize);
|
633
|
+
|
634
|
+
/* first send a code telling the unpacker to clear the stringtable */
|
635
|
+
WriteBits(clearcode, numbits);
|
636
|
+
|
637
|
+
/* pack image */
|
638
|
+
while ((c = inputbyte()) != -1) {
|
639
|
+
/* now perform the packing. check if the prefix + the new
|
640
|
+
* character is a string that exists in the table */
|
641
|
+
if ((index = FindCharString(prefix, c)) != 0xFFFF) {
|
642
|
+
/* the string exists in the table. make this string the
|
643
|
+
* new prefix. */
|
644
|
+
prefix = index;
|
645
|
+
} else {
|
646
|
+
/* the string does not exist in the table. first write
|
647
|
+
* code of the old prefix to the file. */
|
648
|
+
WriteBits(prefix, numbits);
|
649
|
+
|
650
|
+
/* add the new string (the prefix + the new character) to
|
651
|
+
* the stringtable */
|
652
|
+
if (AddCharString(prefix, c) > limit) {
|
653
|
+
if (++numbits > 12) {
|
654
|
+
WriteBits(clearcode, numbits - 1);
|
655
|
+
ClearStrtab(codesize);
|
656
|
+
numbits = codesize + 1;
|
657
|
+
}
|
658
|
+
limit = (1 << numbits) - 1;
|
659
|
+
}
|
660
|
+
|
661
|
+
/* set prefix to a string containing only the character
|
662
|
+
* read. since all possible one-character strings exists
|
663
|
+
* int the table, there's no need to check if it is found. */
|
664
|
+
prefix = c;
|
665
|
+
}
|
666
|
+
}
|
667
|
+
|
668
|
+
/* end of info is reached. write last prefix. */
|
669
|
+
if (prefix != 0xFFFF)
|
670
|
+
WriteBits(prefix, numbits);
|
671
|
+
|
672
|
+
/* erite end of info -mark, flush the buffer, and tidy up */
|
673
|
+
WriteBits(endofinfo, numbits);
|
674
|
+
ResetOutBitFile();
|
675
|
+
FreeStrtab();
|
676
|
+
|
677
|
+
return GIF_OK;
|
678
|
+
}
|
679
|
+
|
680
|
+
|
681
|
+
|
682
|
+
/*========================================================================*
|
683
|
+
= Other routines =
|
684
|
+
*========================================================================*/
|
685
|
+
|
686
|
+
/*-------------------------------------------------------------------------
|
687
|
+
*
|
688
|
+
* NAME BitsNeeded
|
689
|
+
*
|
690
|
+
* DESCRIPTION Calculates number of bits needed to store numbers
|
691
|
+
* between 0 and n - 1
|
692
|
+
*
|
693
|
+
* INPUT n number of numbers to store (0 to n - 1)
|
694
|
+
*
|
695
|
+
* RETURNS Number of bits needed
|
696
|
+
*/
|
697
|
+
static int
|
698
|
+
BitsNeeded(Word n)
|
699
|
+
{
|
700
|
+
int ret = 1;
|
701
|
+
|
702
|
+
if (!n--)
|
703
|
+
return 0;
|
704
|
+
while (n >>= 1)
|
705
|
+
++ret;
|
706
|
+
return ret;
|
707
|
+
}
|
708
|
+
|
709
|
+
|
710
|
+
|
711
|
+
/*-------------------------------------------------------------------------
|
712
|
+
*
|
713
|
+
* NAME InputByte
|
714
|
+
*
|
715
|
+
* DESCRIPTION Get next pixel from image. Called by the
|
716
|
+
* LZW_Compress()-function
|
717
|
+
*
|
718
|
+
* RETURNS Next pixelvalue, or -1 if no more pixels
|
719
|
+
*/
|
720
|
+
static int
|
721
|
+
InputByte(void)
|
722
|
+
{
|
723
|
+
int ret;
|
724
|
+
|
725
|
+
if (RelPixY >= ImageHeight)
|
726
|
+
return -1;
|
727
|
+
ret = GetPixel(ImageLeft + RelPixX, ImageTop + RelPixY);
|
728
|
+
if (++RelPixX >= ImageWidth) {
|
729
|
+
RelPixX = 0;
|
730
|
+
++RelPixY;
|
731
|
+
}
|
732
|
+
return ret;
|
733
|
+
}
|
734
|
+
|
735
|
+
|
736
|
+
|
737
|
+
/*-------------------------------------------------------------------------
|
738
|
+
*
|
739
|
+
* NAME WriteScreenDescriptor
|
740
|
+
*
|
741
|
+
* DESCRIPTION Output a screen descriptor to the current GIF-file
|
742
|
+
*
|
743
|
+
* INPUT sd pointer to screen descriptor to output
|
744
|
+
*
|
745
|
+
* RETURNS GIF_OK - OK
|
746
|
+
* GIF_ERRWRITE - Error writing to the file
|
747
|
+
*/
|
748
|
+
static int
|
749
|
+
WriteScreenDescriptor(ScreenDescriptor *sd)
|
750
|
+
{
|
751
|
+
Byte tmp;
|
752
|
+
|
753
|
+
if (WriteWord(sd->LocalScreenWidth) != GIF_OK)
|
754
|
+
return GIF_ERRWRITE;
|
755
|
+
if (WriteWord(sd->LocalScreenHeight) != GIF_OK)
|
756
|
+
return GIF_ERRWRITE;
|
757
|
+
tmp = (sd->GlobalColorTableFlag << 7)
|
758
|
+
| (sd->ColorResolution << 4)
|
759
|
+
| (sd->SortFlag << 3)
|
760
|
+
| sd->GlobalColorTableSize;
|
761
|
+
if (WriteByte(tmp) != GIF_OK)
|
762
|
+
return GIF_ERRWRITE;
|
763
|
+
if (WriteByte(sd->BackgroundColorIndex) != GIF_OK)
|
764
|
+
return GIF_ERRWRITE;
|
765
|
+
if (WriteByte(sd->PixelAspectRatio) != GIF_OK)
|
766
|
+
return GIF_ERRWRITE;
|
767
|
+
|
768
|
+
return GIF_OK;
|
769
|
+
}
|
770
|
+
|
771
|
+
|
772
|
+
|
773
|
+
/*-------------------------------------------------------------------------
|
774
|
+
*
|
775
|
+
* NAME WriteTransparentColorIndex (added by j.forkosh)
|
776
|
+
*
|
777
|
+
* DESCRIPTION Output a graphic extension block setting transparent
|
778
|
+
* colormap index
|
779
|
+
*
|
780
|
+
* INPUT colornum colormap index of color to be transparent
|
781
|
+
*
|
782
|
+
* RETURNS GIF_OK - OK
|
783
|
+
* GIF_ERRWRITE - Error writing to the file
|
784
|
+
*/
|
785
|
+
static int
|
786
|
+
WriteTransparentColorIndex(int colornum)
|
787
|
+
{
|
788
|
+
if ( colornum < 0 ) return GIF_OK; /*no transparent color set*/
|
789
|
+
if (WriteByte((Byte)(0x21)) != GIF_OK) /*magic:Extension Introducer*/
|
790
|
+
return GIF_ERRWRITE;
|
791
|
+
if (WriteByte((Byte)(0xf9)) != GIF_OK) /*magic:Graphic Control Label*/
|
792
|
+
return GIF_ERRWRITE;
|
793
|
+
if (WriteByte((Byte)(4)) != GIF_OK) /* #bytes in block */
|
794
|
+
return GIF_ERRWRITE;
|
795
|
+
if (WriteByte((Byte)(1)) != GIF_OK) /*transparent index indicator*/
|
796
|
+
return GIF_ERRWRITE;
|
797
|
+
if (WriteWord((Word)(0)) != GIF_OK) /* delay time */
|
798
|
+
return GIF_ERRWRITE;
|
799
|
+
if (WriteByte((Byte)(colornum)) != GIF_OK) /* transparent color index */
|
800
|
+
return GIF_ERRWRITE;
|
801
|
+
if (WriteByte((Byte)(0)) != GIF_OK) /* terminator */
|
802
|
+
return GIF_ERRWRITE;
|
803
|
+
|
804
|
+
return GIF_OK;
|
805
|
+
}
|
806
|
+
|
807
|
+
|
808
|
+
|
809
|
+
/*-------------------------------------------------------------------------
|
810
|
+
*
|
811
|
+
* NAME WriteImageDescriptor
|
812
|
+
*
|
813
|
+
* DESCRIPTION Output an image descriptor to the current GIF-file
|
814
|
+
*
|
815
|
+
* INPUT id pointer to image descriptor to output
|
816
|
+
*
|
817
|
+
* RETURNS GIF_OK - OK
|
818
|
+
* GIF_ERRWRITE - Error writing to the file
|
819
|
+
*/
|
820
|
+
static int
|
821
|
+
WriteImageDescriptor(ImageDescriptor *id)
|
822
|
+
{
|
823
|
+
Byte tmp;
|
824
|
+
|
825
|
+
if (WriteByte(id->Separator) != GIF_OK)
|
826
|
+
return GIF_ERRWRITE;
|
827
|
+
if (WriteWord(id->LeftPosition) != GIF_OK)
|
828
|
+
return GIF_ERRWRITE;
|
829
|
+
if (WriteWord(id->TopPosition) != GIF_OK)
|
830
|
+
return GIF_ERRWRITE;
|
831
|
+
if (WriteWord(id->Width) != GIF_OK)
|
832
|
+
return GIF_ERRWRITE;
|
833
|
+
if (WriteWord(id->Height) != GIF_OK)
|
834
|
+
return GIF_ERRWRITE;
|
835
|
+
tmp = (id->LocalColorTableFlag << 7)
|
836
|
+
| (id->InterlaceFlag << 6)
|
837
|
+
| (id->SortFlag << 5)
|
838
|
+
| (id->Reserved << 3)
|
839
|
+
| id->LocalColorTableSize;
|
840
|
+
if (WriteByte(tmp) != GIF_OK)
|
841
|
+
return GIF_ERRWRITE;
|
842
|
+
|
843
|
+
return GIF_OK;
|
844
|
+
}
|
845
|
+
|
846
|
+
|
847
|
+
|
848
|
+
/**************************************************************************
|
849
|
+
* *
|
850
|
+
* P U B L I C F U N C T I O N S *
|
851
|
+
* *
|
852
|
+
**************************************************************************/
|
853
|
+
|
854
|
+
/*-------------------------------------------------------------------------
|
855
|
+
*
|
856
|
+
* NAME GIF_Create
|
857
|
+
*
|
858
|
+
* DESCRIPTION Create a GIF-file, and write headers for both screen
|
859
|
+
* and image.
|
860
|
+
*
|
861
|
+
* INPUT filename
|
862
|
+
* name of file to create (including extension)
|
863
|
+
* width number of horisontal pixels on screen
|
864
|
+
* height number of vertical pixels on screen
|
865
|
+
* numcolors
|
866
|
+
* number of colors in the colormaps
|
867
|
+
* colorres
|
868
|
+
* color resolution. Number of bits for each
|
869
|
+
* primary color
|
870
|
+
*
|
871
|
+
* RETURNS GIF_OK - OK
|
872
|
+
* GIF_ERRCREATE - Couldn't create file
|
873
|
+
* GIF_ERRWRITE - Error writing to the file
|
874
|
+
* GIF_OUTMEM - Out of memory allocating color table
|
875
|
+
*/
|
876
|
+
int
|
877
|
+
GIF_Create(char *buffer, int width, int height,
|
878
|
+
int numcolors, int colorres)
|
879
|
+
{
|
880
|
+
int q, tabsize;
|
881
|
+
Byte *bp;
|
882
|
+
ScreenDescriptor SD;
|
883
|
+
|
884
|
+
/* initiate variables for new GIF-file */
|
885
|
+
NumColors = numcolors ? (1 << BitsNeeded(numcolors)) : 0;
|
886
|
+
BitsPrPrimColor = colorres;
|
887
|
+
ScreenHeight = height;
|
888
|
+
ScreenWidth = width;
|
889
|
+
|
890
|
+
/* create file specified */
|
891
|
+
if (Create(buffer) != GIF_OK)
|
892
|
+
return GIF_ERRCREATE;
|
893
|
+
|
894
|
+
/* write GIF signature */
|
895
|
+
if ((Write("GIF87a", 6)) != GIF_OK)
|
896
|
+
return GIF_ERRWRITE;
|
897
|
+
|
898
|
+
/* initiate and write screen descriptor */
|
899
|
+
SD.LocalScreenWidth = width;
|
900
|
+
SD.LocalScreenHeight = height;
|
901
|
+
if (NumColors) {
|
902
|
+
SD.GlobalColorTableSize = BitsNeeded(NumColors) - 1;
|
903
|
+
SD.GlobalColorTableFlag = 1;
|
904
|
+
} else {
|
905
|
+
SD.GlobalColorTableSize = 0;
|
906
|
+
SD.GlobalColorTableFlag = 0;
|
907
|
+
}
|
908
|
+
SD.SortFlag = 0;
|
909
|
+
SD.ColorResolution = colorres - 1;
|
910
|
+
SD.BackgroundColorIndex = 0;
|
911
|
+
SD.PixelAspectRatio = 0;
|
912
|
+
if (WriteScreenDescriptor(&SD) != GIF_OK)
|
913
|
+
return GIF_ERRWRITE;
|
914
|
+
|
915
|
+
/* allocate color table */
|
916
|
+
if (ColorTable) {
|
917
|
+
free(ColorTable);
|
918
|
+
ColorTable = NULL;
|
919
|
+
}
|
920
|
+
if (NumColors) {
|
921
|
+
tabsize = NumColors * 3;
|
922
|
+
if ((ColorTable = (Byte *) malloc(tabsize * sizeof(Byte))) == NULL)
|
923
|
+
return GIF_OUTMEM;
|
924
|
+
else {
|
925
|
+
bp = ColorTable;
|
926
|
+
for (q = 0; q < tabsize; q++)
|
927
|
+
*bp++ = 0;
|
928
|
+
}
|
929
|
+
}
|
930
|
+
return 0;
|
931
|
+
}
|
932
|
+
|
933
|
+
|
934
|
+
|
935
|
+
/*-------------------------------------------------------------------------
|
936
|
+
*
|
937
|
+
* NAME GIF_SetColor
|
938
|
+
*
|
939
|
+
* DESCRIPTION Set red, green and blue components of one of the
|
940
|
+
* colors. The color components are all in the range
|
941
|
+
* [0, (1 << BitsPrPrimColor) - 1]
|
942
|
+
*
|
943
|
+
* INPUT colornum
|
944
|
+
* color number to set. [0, NumColors - 1]
|
945
|
+
* red red component of color
|
946
|
+
* green green component of color
|
947
|
+
* blue blue component of color
|
948
|
+
*/
|
949
|
+
void
|
950
|
+
GIF_SetColor(int colornum, int red, int green, int blue)
|
951
|
+
{
|
952
|
+
long maxcolor;
|
953
|
+
Byte *p;
|
954
|
+
|
955
|
+
maxcolor = (1L << BitsPrPrimColor) - 1L;
|
956
|
+
p = ColorTable + colornum * 3;
|
957
|
+
*p++ = (Byte) ((red * 255L) / maxcolor);
|
958
|
+
*p++ = (Byte) ((green * 255L) / maxcolor);
|
959
|
+
*p++ = (Byte) ((blue * 255L) / maxcolor);
|
960
|
+
}
|
961
|
+
|
962
|
+
|
963
|
+
|
964
|
+
/*-------------------------------------------------------------------------
|
965
|
+
*
|
966
|
+
* NAME GIF_SetTransparent (added by j.forkosh)
|
967
|
+
*
|
968
|
+
* DESCRIPTION Set colormap index of color to be transparent
|
969
|
+
*
|
970
|
+
* INPUT colornum
|
971
|
+
* color number to set transparent. [0, NumColors - 1]
|
972
|
+
*/
|
973
|
+
void
|
974
|
+
GIF_SetTransparent(int colornum)
|
975
|
+
{
|
976
|
+
TransparentColorIndex = colornum;
|
977
|
+
}
|
978
|
+
|
979
|
+
|
980
|
+
|
981
|
+
/*-------------------------------------------------------------------------
|
982
|
+
*
|
983
|
+
* NAME GIF_CompressImage
|
984
|
+
*
|
985
|
+
* DESCRIPTION Compress an image into the GIF-file previousely
|
986
|
+
* created using GIF_Create(). All color values should
|
987
|
+
* have been specified before this function is called.
|
988
|
+
*
|
989
|
+
* The pixels are retrieved using a user defined callback
|
990
|
+
* function. This function should accept two parameters,
|
991
|
+
* x and y, specifying which pixel to retrieve. The pixel
|
992
|
+
* values sent to this function are as follows:
|
993
|
+
*
|
994
|
+
* x : [ImageLeft, ImageLeft + ImageWidth - 1]
|
995
|
+
* y : [ImageTop, ImageTop + ImageHeight - 1]
|
996
|
+
*
|
997
|
+
* The function should return the pixel value for the
|
998
|
+
* point given, in the interval [0, NumColors - 1]
|
999
|
+
*
|
1000
|
+
* INPUT left screen-relative leftmost pixel x-coordinate
|
1001
|
+
* of the image
|
1002
|
+
* top screen-relative uppermost pixel y-coordinate
|
1003
|
+
* of the image
|
1004
|
+
* width width of the image, or -1 if as wide as
|
1005
|
+
* the screen
|
1006
|
+
* height height of the image, or -1 if as high as
|
1007
|
+
* the screen
|
1008
|
+
* getpixel
|
1009
|
+
* address of user defined callback function.
|
1010
|
+
* (see above)
|
1011
|
+
*
|
1012
|
+
* RETURNS GIF_OK - OK
|
1013
|
+
* GIF_OUTMEM - Out of memory
|
1014
|
+
* GIF_ERRWRITE - Error writing to the file
|
1015
|
+
*/
|
1016
|
+
int
|
1017
|
+
GIF_CompressImage(int left, int top, int width, int height,
|
1018
|
+
int (*getpixel)(int x, int y))
|
1019
|
+
{
|
1020
|
+
int codesize, errcode;
|
1021
|
+
ImageDescriptor ID;
|
1022
|
+
|
1023
|
+
if (width < 0) {
|
1024
|
+
width = ScreenWidth;
|
1025
|
+
left = 0;
|
1026
|
+
}
|
1027
|
+
if (height < 0) {
|
1028
|
+
height = ScreenHeight;
|
1029
|
+
top = 0;
|
1030
|
+
}
|
1031
|
+
if (left < 0)
|
1032
|
+
left = 0;
|
1033
|
+
if (top < 0)
|
1034
|
+
top = 0;
|
1035
|
+
|
1036
|
+
/* write global colortable if any */
|
1037
|
+
if (NumColors)
|
1038
|
+
if ((Write(ColorTable, NumColors * 3)) != GIF_OK)
|
1039
|
+
return GIF_ERRWRITE;
|
1040
|
+
|
1041
|
+
/* write graphic extension block with transparent color index */
|
1042
|
+
if ( TransparentColorIndex >= 0 ) /* (added by j.forkosh) */
|
1043
|
+
if ( WriteTransparentColorIndex(TransparentColorIndex)
|
1044
|
+
!= GIF_OK ) return GIF_ERRWRITE;
|
1045
|
+
|
1046
|
+
/* initiate and write image descriptor */
|
1047
|
+
ID.Separator = ',';
|
1048
|
+
ID.LeftPosition = ImageLeft = left;
|
1049
|
+
ID.TopPosition = ImageTop = top;
|
1050
|
+
ID.Width = ImageWidth = width;
|
1051
|
+
ID.Height = ImageHeight = height;
|
1052
|
+
ID.LocalColorTableSize = 0;
|
1053
|
+
ID.Reserved = 0;
|
1054
|
+
ID.SortFlag = 0;
|
1055
|
+
ID.InterlaceFlag = 0;
|
1056
|
+
ID.LocalColorTableFlag = 0;
|
1057
|
+
|
1058
|
+
if (WriteImageDescriptor(&ID) != GIF_OK)
|
1059
|
+
return GIF_ERRWRITE;
|
1060
|
+
|
1061
|
+
/* write code size */
|
1062
|
+
codesize = BitsNeeded(NumColors);
|
1063
|
+
if (codesize == 1)
|
1064
|
+
++codesize;
|
1065
|
+
if (WriteByte(codesize) != GIF_OK)
|
1066
|
+
return GIF_ERRWRITE;
|
1067
|
+
|
1068
|
+
/* perform compression */
|
1069
|
+
RelPixX = RelPixY = 0;
|
1070
|
+
GetPixel = getpixel;
|
1071
|
+
if ((errcode = LZW_Compress(codesize, InputByte)) != GIF_OK)
|
1072
|
+
return errcode;
|
1073
|
+
|
1074
|
+
/* write terminating 0-byte */
|
1075
|
+
if (WriteByte(0) != GIF_OK)
|
1076
|
+
return GIF_ERRWRITE;
|
1077
|
+
|
1078
|
+
return GIF_OK;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
|
1082
|
+
|
1083
|
+
/*-------------------------------------------------------------------------
|
1084
|
+
*
|
1085
|
+
* NAME GIF_Close
|
1086
|
+
*
|
1087
|
+
* DESCRIPTION Close the GIF-file
|
1088
|
+
*
|
1089
|
+
* RETURNS GIF_OK - OK
|
1090
|
+
* GIF_ERRWRITE - Error writing to file
|
1091
|
+
*/
|
1092
|
+
int
|
1093
|
+
GIF_Close(void)
|
1094
|
+
{
|
1095
|
+
ImageDescriptor ID;
|
1096
|
+
|
1097
|
+
/* initiate and write ending image descriptor */
|
1098
|
+
ID.Separator = ';';
|
1099
|
+
ID.LeftPosition = 0; /* (added by j.forkosh) */
|
1100
|
+
ID.TopPosition = 0; /* " initialize entire ID structure */
|
1101
|
+
ID.Width = 0; /* " and ditto for other ID.x=0; below */
|
1102
|
+
ID.Height = 0;
|
1103
|
+
ID.LocalColorTableSize = 0;
|
1104
|
+
ID.Reserved = 0;
|
1105
|
+
ID.SortFlag = 0;
|
1106
|
+
ID.InterlaceFlag = 0;
|
1107
|
+
ID.LocalColorTableFlag = 0;
|
1108
|
+
|
1109
|
+
if (WriteImageDescriptor(&ID) != GIF_OK)
|
1110
|
+
return GIF_ERRWRITE;
|
1111
|
+
|
1112
|
+
/* close file */
|
1113
|
+
Close();
|
1114
|
+
|
1115
|
+
/* release color table */
|
1116
|
+
if (ColorTable) {
|
1117
|
+
free(ColorTable);
|
1118
|
+
ColorTable = NULL;
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
return gifSize;
|
1122
|
+
}
|
1123
|
+
/* --- end-of-file gifsave.c --- */
|