source: trunk/src/oleaut32/libgif/dev2gif.c@ 10366

Last change on this file since 10366 was 10266, checked in by sandervl, 22 years ago

PF: GIF and JPEG static libs for IPicture interface implementation

File size: 16.0 KB
Line 
1/*****************************************************************************
2* "Gif-Lib" - Yet another gif library. *
3* *
4* Written by: Gershon Elber IBM PC Ver 1.1, Jun. 1989 *
5******************************************************************************
6* Module to dump graphic devices into a GIF file. Current supported devices: *
7* 1. EGA, VGA, SVGA (800x600), Hercules on the IBM PC (#define __MSDOS__). *
8* 2. SGI 4D Irix using gl library (#define __SGI_GL__). *
9* 3. X11 using libX.a (#define __X11__). *
10******************************************************************************
11* History: *
12* 22 Jun 89 - Version 1.0 by Gershon Elber. *
13* 12 Aug 90 - Version 1.1 by Gershon Elber (added devices). *
14*****************************************************************************/
15
16#ifdef __MSDOS__
17#include <dos.h>
18#include <alloc.h>
19#include <graphics.h>
20#endif /* __MSDOS__ */
21
22#ifdef __SGI_GL__
23#include <gl/gl.h>
24#endif /* __SGI_GL__ */
25
26#ifdef __X11__
27#include <X11/Xlib.h>
28#endif /* __X11__ */
29
30#if (defined(__IBMC__) || defined(__IBMCPP__))
31#include <io.h>
32#endif
33
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
37#include "gif_lib.h"
38
39#define PROGRAM_NAME "GIF_LIBRARY"
40
41#define SVGA_SPECIAL 999 /* 800 by 600 Super VGA mode. */
42
43static int GraphDriver = -1, /* Device parameters - reasonable values. */
44 GraphMode = -1,
45 ScreenColorBits = 1;
46static long ScreenXMax = 100,
47 ScreenYMax = 100;
48static unsigned int ScreenBase;
49
50#ifdef SYSV
51static char *VersionStr =
52 "Gif library module,\t\tEric S. Raymond\n\
53 (C) Copyright 1997 Eric S. Raymond\n";
54#else
55static char *VersionStr =
56 PROGRAM_NAME
57 " IBMPC "
58 GIF_LIB_VERSION
59 " Eric S. Raymond, "
60 __DATE__ ", " __TIME__ "\n"
61 "(C) Copyright 1997 Eric S. Raymond\n";
62#endif /* SYSV */
63
64#if defined(__SGI_GL__) || defined(__X11__)
65 GifByteType *GlblGifBuffer = NULL, *GlblGifBufferPtr = NULL;
66#endif /* __SGI_GL__ || __X11__ */
67
68#ifdef __SGI_GL__
69static int QuantizeRGBBuffer(int Width, int Height, long *RGBBuffer,
70 GifColorType *ColorMap, GifByteType *GIFBuffer);
71#endif /* __SGI_GL__ */
72
73static void GetScanLine(GifPixelType *ScanLine, int Y);
74static int HandleGifError(GifFileType *GifFile);
75
76/******************************************************************************
77* Dump the given Device, into given File as GIF format: *
78* Return 0 on success, -1 if device not supported, or GIF-LIB error number. *
79* Device is selected via the ReqGraphDriver. Device mode is selected via *
80* ReqGraphMode1/2 as follows: *
81* 1. IBM PC Hercules card: HERCMONO (one mode only) in ReqGraphMode1, *
82* ReqGraphMode2/3 are ignored. *
83* 2. IBM PC EGA card: EGALO/EGAHI in ReqGraphMode1, *
84* ReqGraphMode2/3 are ignored. *
85* 3. IBM PC EGA64 card: EGA64LO/EGA64HI in ReqGraphMode1, *
86* ReqGraphMode2/3 are ignored. *
87* 4. IBM PC EGAMONO card: EGAMONOHI (one mode only) in ReqGraphMode1, *
88* ReqGraphMode2/3 are ignored. *
89* 5. IBM PC VGA card: VGALO/VGAMED/VGAHI in ReqGraphMode1, *
90* ReqGraphMode2/3 are ignored. *
91* 6. IBM PC SVGA card: ReqGraphMode1/2 are both ignored. Fixed mode (800x600 *
92* 16 colors) is assumed. *
93* 7. SGI 4D using GL: window id to dump (as returned by winget()) in *
94* ReqGraphMode1, ReqGraphMode2/3 are ignored. *
95* 8. X11: Window id in ReqGraphMode1, Display id in ReqGraphMode2, Color *
96* map id in ReqGraphMode3. *
97******************************************************************************/
98int DumpScreen2Gif(char *FileName, int ReqGraphDriver, int ReqGraphMode1,
99 int ReqGraphMode2,
100 int ReqGraphMode3)
101{
102 int i, j, k;
103 GifPixelType *ScanLine;
104 GifFileType *GifFile;
105 ColorMapObject *ColorMap = NULL;
106#ifdef __MSDOS__
107 static GifColorType MonoChromeColorMap[] = {
108 { 0, 0, 0 },
109 { 255, 255, 255 }
110 };
111 /* I have no idea what default EGA64 (4 colors) should be (I guessed...).*/
112 static GifColorType EGA64ColorMap[] = {
113 { 0, 0, 0 }, /* 0. Black */
114 { 255, 0, 0 }, /* 1. Red */
115 { 0, 255, 0 }, /* 2. Green */
116 { 0, 0, 255 }, /* 3. Blue */
117 };
118 static GifColorType EGAColorMap[] = {
119 { 0, 0, 0 }, /* 0. Black */
120 { 0, 0, 170 }, /* 1. Blue */
121 { 0, 170, 0 }, /* 2. Green */
122 { 0, 170, 170 }, /* 3. Cyan */
123 { 170, 0, 0 }, /* 4. Red */
124 { 170, 0, 170 }, /* 5. Magenta */
125 { 170, 170, 0 }, /* 6. Brown */
126 { 170, 170, 170 }, /* 7. LightGray */
127 { 85, 85, 85 }, /* 8. DarkGray */
128 { 85, 85, 255 }, /* 9. LightBlue */
129 { 85, 255, 85 }, /* 10. LightGreen */
130 { 85, 255, 255 }, /* 11. LightCyan */
131 { 255, 85, 85 }, /* 12. LightRed */
132 { 255, 85, 255 }, /* 13. LightMagenta */
133 { 255, 255, 85 }, /* 14. Yellow */
134 { 255, 255, 255 }, /* 15. White */
135 };
136#endif /* __MSDOS__ */
137#if defined(__SGI_GL__) || defined(__X11__)
138 long *RGBBuffer;
139 GifColorType ColorMap256[256];
140#endif
141#ifdef __X11__
142 XImage *XImg;
143 unsigned long XPixel;
144 XColor XColorTable[256]; /* Up to 256 colors in X. */
145 XWindowAttributes WinAttr;
146#endif /* __X11__ */
147
148 switch (ReqGraphDriver) { /* Return on non supported screens. */
149#ifdef __MSDOS__
150 case HERCMONO:
151 ScreenXMax = 720;
152 ScreenYMax = 350;
153 ScreenColorBits = 1;
154 ScreenBase = 0xb000;
155 ColorMap = MakeMapObject(2, MonoChromeColorMap);
156 break;
157 case EGA:
158 switch (ReqGraphMode1) {
159 case EGALO:
160 ScreenYMax = 200;
161 break;
162 case EGAHI:
163 ScreenYMax = 350;
164 break;
165 default:
166 return -1;
167 }
168 ScreenXMax = 640;
169 ScreenColorBits = 4;
170 ScreenBase = 0xa000;
171 ColorMap = MakeMapObject(16, EGAColorMap);
172 break;
173 case EGA64:
174 switch (ReqGraphMode1) {
175 case EGA64LO:
176 ScreenYMax = 200;
177 break;
178 case EGA64HI:
179 ScreenYMax = 350;
180 break;
181 default:
182 return -1;
183 }
184 ScreenXMax = 640;
185 ScreenColorBits = 2;
186 ScreenBase = 0xa000;
187 ColorMap = MakeMapObject(4, EGA64ColorMap);
188 break;
189 case EGAMONO:
190 switch (ReqGraphMode1) {
191 case EGAMONOHI:
192 ScreenYMax = 350;
193 break;
194 default:
195 return -1;
196 }
197 ScreenXMax = 640;
198 ScreenColorBits = 1;
199 ScreenBase = 0xa000;
200 ColorMap = MakeMapObject(2, MonoChromeColorMap);
201 break;
202 case VGA:
203 switch (ReqGraphMode1) {
204 case VGALO:
205 ScreenYMax = 200;
206 break;
207 case VGAMED:
208 ScreenYMax = 350;
209 break;
210 case VGAHI:
211 ScreenYMax = 480;
212 break;
213 default:
214 return -1;
215 }
216 ScreenXMax = 640;
217 ScreenColorBits = 4;
218 ScreenBase = 0xa000;
219 ColorMap = MakeMapObject(16, EGAColorMap);
220 break;
221 case SVGA_SPECIAL:
222 ScreenXMax = 800;
223 ScreenYMax = 600;
224 ScreenColorBits = 4;
225 ScreenBase = 0xa000;
226 ColorMap = MakeMapObject(16, EGAColorMap);
227 break;
228#endif /* __MSDOS__ */
229#ifdef __SGI_GL__
230 case GIF_DUMP_SGI_WINDOW:
231 winset(ReqGraphMode1); /* Select window as active window. */
232 getsize(&ScreenXMax, &ScreenYMax);
233
234 RGBBuffer = (long *) malloc(sizeof(long) * ScreenXMax * ScreenYMax);
235 readsource(SRC_FRONT);
236 if (lrectread((short) 0,
237 (short) 0,
238 (short) (ScreenXMax - 1),
239 (short) (ScreenYMax - 1), RGBBuffer) !=
240 ScreenXMax * ScreenYMax) { /* Get data. */
241 free(RGBBuffer);
242 return -1;
243 }
244 GlblGifBuffer = (GifByteType *) malloc(sizeof(GifByteType) *
245 ScreenXMax * ScreenYMax);
246 i = QuantizeRGBBuffer(ScreenXMax, ScreenYMax, RGBBuffer,
247 ColorMap256, GlblGifBuffer);
248 /* Find minimum color map size to hold all quantized colors. */
249 for (ScreenColorBits = 1;
250 (1 << ScreenColorBits) < i && ScreenColorBits < 8;
251 ScreenColorBits++);
252
253 /* Start to dump with top line as GIF expects it. */
254 GlblGifBufferPtr = GlblGifBuffer + ScreenXMax * (ScreenYMax - 1);
255 ColorMap = MakeMapObject(256, ColorMap256);
256 free(RGBBuffer);
257 break;
258#endif /* __SGI_GL__ */
259#ifdef __X11__
260 case GIF_DUMP_X_WINDOW:
261 XGetWindowAttributes((Display *) ReqGraphMode2,
262 (Window) ReqGraphMode1,
263 &WinAttr);
264 ScreenXMax = WinAttr.width;
265 ScreenYMax = WinAttr.height;
266
267 XImg = XGetImage((Display *) ReqGraphMode2,
268 (Window) ReqGraphMode1,
269 0, 0, ScreenXMax - 1, ScreenYMax - 1,
270 AllPlanes, XYPixmap);
271
272 GlblGifBuffer = (GifByteType *) malloc(sizeof(GifByteType) *
273 ScreenXMax * ScreenYMax);
274
275 /* Scan the image for all different colors exists. */
276 for (i = 0; i < 256; i++) XColorTable[i].pixel = 0;
277 k = FALSE;
278 for (i = 0; i < ScreenXMax; i++)
279 for (j = 0; j < ScreenYMax; j++) {
280 XPixel = XGetPixel(XImg, i, j);
281 if (XPixel > 255) {
282 if (!k) {
283 /* Make sure we state it once only.*/
284 fprintf(stderr, "X Color table - truncated.\n");
285 k = TRUE;
286 }
287 XPixel = 255;
288 }
289 XColorTable[XPixel].pixel = XPixel;
290 }
291 /* Find the RGB representation of the colors. */
292 XQueryColors((Display *) ReqGraphMode2,
293 (Colormap) ReqGraphMode3,
294 XColorTable,
295 256);
296 /* Count number of active colors (Note color 0 is always in) */
297 /* and create the Gif color map from it. */
298 ColorMap = MakeMapObject(256, ColorMap256);
299 ColorMap->Colors[0].Red = ColorMap->Colors[0].Green = ColorMap->Colors[0].Blue = 0;
300 for (i = j = 1; i < 256; i++)
301 if (XColorTable[i].pixel) {
302 ColorMap->Colors[j].Red = XColorTable[i].red / 256;
303 ColorMap->Colors[j].Green = XColorTable[i].green / 256;
304 ColorMap->Colors[j].Blue = XColorTable[i].blue / 256;
305 /* Save the X color index into the Gif table: */
306 XColorTable[i].pixel = j++;
307 }
308 /* and set the number of colors in the Gif color map. */
309 for (ScreenColorBits = 1;
310 (1 << ScreenColorBits) < j && ScreenColorBits < 8;
311 ScreenColorBits++);
312
313 /* Prepare the Gif image buffer as indices into the Gif color */
314 /* map from the X image. */
315 GlblGifBufferPtr = GlblGifBuffer;
316 for (i = 0; i < ScreenXMax; i++)
317 for (j = 0; j < ScreenYMax; j++)
318 *GlblGifBufferPtr++ =
319 XColorTable[XGetPixel(XImg, j, i) & 0xff].pixel;
320 XDestroyImage(XImg);
321
322 GlblGifBufferPtr = GlblGifBuffer;
323 ColorMap = MakeMapObject(256, ColorMap256);
324 break;
325#endif /* __X11__ */
326 default:
327 return -1;
328 }
329
330 ScanLine = (GifPixelType *) malloc(sizeof(GifPixelType) * ScreenXMax);
331
332 GraphDriver = ReqGraphDriver;
333 GraphMode = ReqGraphMode1;
334
335 if ((GifFile = EGifOpenFileName(FileName, FALSE)) == NULL ||
336 EGifPutScreenDesc(GifFile, ScreenXMax, ScreenYMax, ScreenColorBits,
337 0, ColorMap) == GIF_ERROR ||
338 EGifPutImageDesc(GifFile, 0, 0, ScreenXMax, ScreenYMax, FALSE,
339 NULL) == GIF_ERROR) {
340 free((char *) ScanLine);
341#if defined(__SGI_GL__) || defined(__X11__)
342 free((char *) GlblGifBuffer);
343#endif
344 return HandleGifError(GifFile);
345 }
346
347 for (i = 0; i < ScreenYMax; i++) {
348 GetScanLine(ScanLine, i);
349 if (EGifPutLine(GifFile, ScanLine, ScreenXMax) == GIF_ERROR) {
350 free((char *) ScanLine);
351#if defined(__SGI_GL__) || defined(__X11__)
352 free((char *) GlblGifBuffer);
353#endif
354 return HandleGifError(GifFile);
355 }
356 }
357
358 if (EGifCloseFile(GifFile) == GIF_ERROR) {
359 free((char *) ScanLine);
360#if defined(__SGI_GL__) || defined(__X11__)
361 free((char *) GlblGifBuffer);
362#endif
363 return HandleGifError(GifFile);
364 }
365
366 free((char *) ScanLine);
367#if defined(__SGI_GL__) || defined(__X11__)
368 free((char *) GlblGifBuffer);
369#endif
370 return 0;
371}
372
373#ifdef __SGI_GL__
374/******************************************************************************
375* Quantize the given 24 bit (8 per RGB) into 256 colors. *
376******************************************************************************/
377static int QuantizeRGBBuffer(int Width, int Height, long *RGBBuffer,
378 GifColorType *ColorMap, GifByteType *GIFBuffer)
379{
380 int i;
381 GifByteType *RedInput, *GreenInput, *BlueInput;
382
383 /* Convert the RGB Buffer into 3 seperated buffers: */
384 RedInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
385 GreenInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
386 BlueInput = (GifByteType *) malloc(sizeof(GifByteType) * Width * Height);
387
388 for (i = 0; i < Width * Height; i++) {
389 RedInput[i] = RGBBuffer[i] & 0xff;
390 GreenInput[i] = (RGBBuffer[i] >> 8) & 0xff;
391 BlueInput[i] = (RGBBuffer[i] >> 16) & 0xff;
392 }
393 for (i = 0; i < 256; i++)
394 ColorMap[i].Red = ColorMap[i].Green = ColorMap[i].Blue = 0;
395
396 i = 256;
397 QuantizeBuffer(Width, Height, &i,
398 RedInput, GreenInput, BlueInput,
399 GIFBuffer, ColorMap);
400
401 free(RedInput);
402 free(GreenInput);
403 free(BlueInput);
404
405 return i; /* Real number of colors in color table. */
406}
407#endif /* __SGI_GL__ */
408
409/******************************************************************************
410* Update the given scan line buffer with the pixel levels of the Y line. *
411* This routine is device specific, so make sure you know was you are doing *
412******************************************************************************/
413static void GetScanLine(GifPixelType *ScanLine, int Y)
414{
415 unsigned char ScreenByte;
416 int i, j, k;
417 unsigned int BufferOffset, Bit;
418#ifdef __MSDOS__
419 union REGS InRegs, OutRegs;
420#endif /* __MSDOS__ */
421
422 switch (GraphDriver) {
423#ifdef __MSDOS__
424 case HERCMONO:
425 BufferOffset = 0x2000 * (Y % 4) + (Y / 4) * (ScreenXMax / 8);
426 /* In one scan lines we have ScreenXMax / 8 bytes: */
427 for (i = 0, k = 0; i < ScreenXMax / 8; i++) {
428 ScreenByte = (unsigned char) peekb(ScreenBase, BufferOffset++);
429 for (j = 0, Bit = 0x80; j < 8; j++) {
430 ScanLine[k++] = (ScreenByte & Bit ? 1 : 0);
431 Bit >>= 1;
432 }
433 }
434 break;
435 case EGA:
436 case EGA64:
437 case EGAMONO:
438 case VGA:
439 case SVGA_SPECIAL:
440 InRegs.x.dx = Y;
441 InRegs.h.bh = 0;
442 InRegs.h.ah = 0x0d; /* BIOS Read dot. */
443 for (i = 0; i < ScreenXMax; i++) {
444 InRegs.x.cx = i;
445 int86(0x10, &InRegs, &OutRegs);
446 ScanLine[i] = OutRegs.h.al;
447 }
448
449 /* Makr this line as done by putting a xored dot on the left. */
450 InRegs.x.dx = Y;
451 InRegs.h.bh = 0;
452 InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
453 InRegs.h.al = 0x81; /* Xor with color 1. */
454 InRegs.x.cx = 0;
455 int86(0x10, &InRegs, &OutRegs);
456 InRegs.x.dx = Y;
457 InRegs.h.bh = 0;
458 InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
459 InRegs.h.al = 0x81; /* Xor with color 1. */
460 InRegs.x.cx = 1;
461 int86(0x10, &InRegs, &OutRegs);
462
463 if (Y == ScreenYMax - 1) {/* Last row - clear all marks we made. */
464 for (i = 0; i < ScreenYMax; i++) {
465 InRegs.h.bh = 0;
466 InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
467 InRegs.h.al = 0x81; /* Xor back with color 1. */
468 InRegs.x.dx = i;
469 InRegs.x.cx = 0;
470 int86(0x10, &InRegs, &OutRegs);
471 InRegs.h.bh = 0;
472 InRegs.h.ah = 0x0c; /* BIOS Write dot (xor mode). */
473 InRegs.h.al = 0x81; /* Xor back with color 1. */
474 InRegs.x.dx = i;
475 InRegs.x.cx = 1;
476 int86(0x10, &InRegs, &OutRegs);
477 }
478 }
479 break;
480#endif /* __MSDOS__ */
481#ifdef __SGI_GL__
482 case GIF_DUMP_SGI_WINDOW:
483 memcpy(ScanLine, GlblGifBufferPtr, ScreenXMax * sizeof(GifPixelType));
484 GlblGifBufferPtr -= ScreenXMax;
485 break;
486#endif /* __SGI_GL__ */
487#ifdef __X11__
488 case GIF_DUMP_X_WINDOW:
489 memcpy(ScanLine, GlblGifBufferPtr, ScreenXMax * sizeof(GifPixelType));
490 GlblGifBufferPtr += ScreenXMax;
491 break;
492#endif /* __X11__ */
493 default:
494 break;
495 }
496}
497
498/******************************************************************************
499* Handle last GIF error. Try to close the file and free all allocated memory. *
500******************************************************************************/
501static int HandleGifError(GifFileType *GifFile)
502{
503 int i = GifLastError();
504
505 if (EGifCloseFile(GifFile) == GIF_ERROR) {
506 GifLastError();
507 }
508 return i;
509}
510
511
512
513
514
515
516
517
518
Note: See TracBrowser for help on using the repository browser.