mimetexrb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("mimetexrb")
4
+
5
+ with_cflags("-DAA") do
6
+ create_makefile("mimetexrb", "src")
7
+ end
@@ -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 --- */