First commit ~0,10
This commit is contained in:
941
G/UTIL/GIF2BGI.C
Normal file
941
G/UTIL/GIF2BGI.C
Normal file
@ -0,0 +1,941 @@
|
||||
/*****************************************************************************
|
||||
* "Gif-Lib" - Yet another gif library. *
|
||||
* *
|
||||
* Written by: Gershon Elber Ver 0.1, Jul. 1989 *
|
||||
******************************************************************************
|
||||
* Program to display GIF file using the BGI device indepedent routines *
|
||||
* Options: *
|
||||
* -q : quite printing mode. *
|
||||
* -d BGI path : specify the directory where to look for bgi drivers. *
|
||||
* -u BGIUserDriverName.Mode : use user driver instead of auto detection. *
|
||||
* -z factor : zoom the pixels by the given factor. *
|
||||
* -b : beeps disabled. *
|
||||
* -h : on line help. *
|
||||
* *
|
||||
* In this file Screen refers to GIF file screen, while Device to BGI size. *
|
||||
******************************************************************************
|
||||
* History: *
|
||||
* 31 Jul 90 - Version 1.0 by Gershon Elber. *
|
||||
*****************************************************************************/
|
||||
|
||||
#include <graphics.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <alloc.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <fcntl.h>
|
||||
#include "gif_lib.h"
|
||||
#include "getarg.h"
|
||||
|
||||
#define PROGRAM_NAME "Gif2BGI"
|
||||
|
||||
#define KEY_LEFT 256 /* Key Codes returned for operational keys */
|
||||
#define KEY_RIGHT 257 /* as return by the GetKey routine. */
|
||||
#define KEY_UP 258
|
||||
#define KEY_DOWN 259
|
||||
#define KEY_RETURN 260
|
||||
#define KEY_DELETE 261
|
||||
#define KEY_INSERT 262
|
||||
#define KEY_BSPACE 263
|
||||
#define KEY_ESC 264
|
||||
#define KEY_HOME 265
|
||||
#define KEY_END 266
|
||||
#define KEY_PGUP 267
|
||||
#define KEY_PGDN 268
|
||||
|
||||
#define SET_POSITION_RESET 0 /* Situations need positionings: */
|
||||
#define SET_POSITION_ZOOM_U 1
|
||||
#define SET_POSITION_ZOOM_D 2
|
||||
#define SET_POSITION_PAN 3
|
||||
|
||||
#define CURSOR_TEXT_X 120
|
||||
|
||||
#define BGI_USER_INSTALL 999 /* BGI User installed driver device. */
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
extern unsigned int
|
||||
_stklen = 16384; /* Increase default stack size. */
|
||||
|
||||
static char
|
||||
*VersionStr =
|
||||
PROGRAM_NAME
|
||||
GIF_LIB_VERSION
|
||||
" Gershon Elber, "
|
||||
__DATE__ ", " __TIME__ "\n"
|
||||
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
|
||||
static char
|
||||
*CtrlStr =
|
||||
PROGRAM_NAME
|
||||
" q%- d%-BGI|Directory!s u%-UserBGIDrv.Mode!s z%-ZoomFactor!d b%- h%- GifFile!*s";
|
||||
static char
|
||||
*GifFileName,
|
||||
*BGIPath = "",
|
||||
*BGIUserDriverName = NULL;
|
||||
|
||||
/* Make some variables global, so we could access them faster: */
|
||||
static int
|
||||
ImageNum = 0,
|
||||
BackGround = 0,
|
||||
ForeGround = 1, /* As close to white as possible. */
|
||||
BeepsDisabled = FALSE,
|
||||
ZoomFactor = 1,
|
||||
MaximumScreenHeight = 1,
|
||||
BGIUserDriverMode = -1,
|
||||
DeviceMaxX = 640, DeviceMaxY = 400, /* Physical device dimensions. */
|
||||
ScreenWidth = 320, ScreenHeight = 200, /* Gif image screen size. */
|
||||
InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
|
||||
InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */
|
||||
static GifColorType
|
||||
*ColorMap;
|
||||
|
||||
static int huge detectVGA(void);
|
||||
static void BGIInstallUserDriver(char *BGIUserDriverNameMode);
|
||||
static void DisplayScreen(GifRowType *ScreenBuffer, GifFileType *GifFile);
|
||||
static void PrintSettingStatus(GifFileType *GifFile);
|
||||
static void CPrintStr(char *Str, int y);
|
||||
static void SetPosition(int Why,
|
||||
int *ScreenLeft, int *ScreenTop,
|
||||
int *DeviceLeft, int *DeviceTop,
|
||||
int MoveX, int MoveY);
|
||||
static void DrawScreen(GifRowType *ScreenBuffer,
|
||||
int ScreenLeft, int ScreenTop, int DeviceLeft, int DeviceTop);
|
||||
static void DoCursorMode(GifRowType *ScreenBuffer,
|
||||
int ScreenLeft, int ScreenTop, int DeviceLeft, int DeviceTop);
|
||||
static int MyKbHit(void);
|
||||
static int MyGetCh(void);
|
||||
static int GetKey(void);
|
||||
static void Tone(int Frequency, int Time);
|
||||
|
||||
/******************************************************************************
|
||||
* Interpret the command line and scan the given GIF file. *
|
||||
******************************************************************************/
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
int i, j, k, Error, NumFiles, Size, Row, Col, Width, Height, ExtCode,
|
||||
Count, ColorMapSize, GraphDriver, GraphMode, Sum,
|
||||
HelpFlag = FALSE,
|
||||
BGIPathFlag = FALSE,
|
||||
BGIUserDriverFlag = FALSE,
|
||||
ZoomFlag = FALSE;
|
||||
GifRecordType RecordType;
|
||||
GifByteType *Extension;
|
||||
char Str[80], *BGIUserDriverNameMode,
|
||||
**FileName = NULL;
|
||||
GifRowType *ScreenBuffer;
|
||||
GifFileType *GifFile;
|
||||
struct text_info TextInfo; /* So we can restore starting text mode. */
|
||||
|
||||
if ((Error = GAGetArgs(argc, argv, CtrlStr,
|
||||
&GifQuitePrint, &BGIPathFlag, &BGIPath,
|
||||
&BGIUserDriverFlag, &BGIUserDriverNameMode,
|
||||
&ZoomFlag, &ZoomFactor,
|
||||
&BeepsDisabled, &HelpFlag,
|
||||
&NumFiles, &FileName)) != FALSE ||
|
||||
(NumFiles > 1 && !HelpFlag)) {
|
||||
if (Error)
|
||||
GAPrintErrMsg(Error);
|
||||
else if (NumFiles > 1)
|
||||
GIF_MESSAGE("Error in command line parsing - one GIF file please.");
|
||||
GAPrintHowTo(CtrlStr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (HelpFlag) {
|
||||
fprintf(stderr, VersionStr);
|
||||
GAPrintHowTo(CtrlStr);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (BGIUserDriverFlag) {
|
||||
/* Use the driver supplied by the user! */
|
||||
BGIInstallUserDriver(BGIUserDriverNameMode);
|
||||
installuserdriver(BGIUserDriverName, detectVGA);
|
||||
GraphDriver = BGI_USER_INSTALL;
|
||||
}
|
||||
else {
|
||||
/* Sense type of display we have and attempt to load right driver. */
|
||||
detectgraph(&GraphDriver, &GraphMode);
|
||||
if (GraphDriver < 0)
|
||||
GIF_EXIT("BGI Auto detect: No graphics device detected.");
|
||||
}
|
||||
|
||||
/* Put in the following any graphic driver specific setup: */
|
||||
switch (GraphDriver) {
|
||||
case CGA:
|
||||
GraphMode = CGAHI;
|
||||
break;
|
||||
case EGA:
|
||||
GraphMode = EGAHI;
|
||||
break;
|
||||
case EGA64:
|
||||
GraphMode = EGA64HI;
|
||||
break;
|
||||
case EGAMONO:
|
||||
GraphMode = EGAMONOHI;
|
||||
break;
|
||||
case HERCMONO:
|
||||
GraphMode = HERCMONOHI;
|
||||
break;
|
||||
case VGA:
|
||||
GraphMode = VGAHI;
|
||||
break;
|
||||
case BGI_USER_INSTALL:
|
||||
GraphDriver = DETECT;
|
||||
GraphMode = BGIUserDriverMode;
|
||||
break;
|
||||
default:
|
||||
GIF_EXIT("Requested graphic device is not supported.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (NumFiles == 1) {
|
||||
GifFileName = *FileName;
|
||||
if ((GifFile = DGifOpenFileName(*FileName)) == NULL) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Use the stdin instead: */
|
||||
GifFileName = "Stdin";
|
||||
setmode(0, O_BINARY);
|
||||
if ((GifFile = DGifOpenFileHandle(0)) == NULL) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the screen as vector of column of rows. We cannt allocate */
|
||||
/* the all screen at once, as this broken minded CPU can allocate up to */
|
||||
/* 64k at a time and our image can be bigger than that: */
|
||||
/* Note this screen is device independent - its the screen as defined by */
|
||||
/* the GIF file parameters itself. */
|
||||
if ((ScreenBuffer = (GifRowType *)
|
||||
malloc(GifFile -> SHeight * sizeof(GifRowType *))) == NULL)
|
||||
GIF_EXIT("Failed to allocate memory required, aborted.");
|
||||
|
||||
Size = GifFile -> SWidth * sizeof(GifPixelType);/* Size in bytes of one row.*/
|
||||
if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */
|
||||
GIF_EXIT("Failed to allocate memory required, aborted.");
|
||||
|
||||
for (i = 0; i < GifFile -> SWidth; i++) /* Set its color to BackGround. */
|
||||
ScreenBuffer[0][i] = GifFile -> SBackGroundColor;
|
||||
MaximumScreenHeight = GifFile -> SHeight - 1;
|
||||
for (i = 1; i < GifFile -> SHeight; i++) {
|
||||
/* Allocate the other rows, and set their color to background too: */
|
||||
if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL) {
|
||||
if (i > 30) {
|
||||
/* Free some memory for the BGI driver and auxilary. */
|
||||
for (j = 1; j < 28; j++)
|
||||
free((char *) ScreenBuffer[i - j]);
|
||||
MaximumScreenHeight = i - 28;
|
||||
fprintf(stderr, "\n%s: Failed to allocate all memory required, last line %d.\n",
|
||||
PROGRAM_NAME, MaximumScreenHeight);
|
||||
break;
|
||||
}
|
||||
else
|
||||
GIF_EXIT("Failed to allocate memory required, aborted.");
|
||||
}
|
||||
|
||||
memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
|
||||
}
|
||||
|
||||
/* Scan the content of the GIF file and load the image(s) in: */
|
||||
do {
|
||||
if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
break;
|
||||
}
|
||||
switch (RecordType) {
|
||||
case IMAGE_DESC_RECORD_TYPE:
|
||||
if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
Row = GifFile -> ITop; /* Image Position relative to Screen. */
|
||||
Col = GifFile -> ILeft;
|
||||
Width = GifFile -> IWidth;
|
||||
Height = GifFile -> IHeight;
|
||||
GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ",
|
||||
PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
|
||||
if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth ||
|
||||
GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) {
|
||||
fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n");
|
||||
exit(-2);
|
||||
}
|
||||
if (GifFile -> IInterlace) {
|
||||
/* Need to perform 4 passes on the images: */
|
||||
for (Count = i = 0; i < 4; i++)
|
||||
for (j = Row + InterlacedOffset[i]; j < Row + Height;
|
||||
j += InterlacedJumps[i]) {
|
||||
GifQprintf("\b\b\b\b%-4d", Count++);
|
||||
if (DGifGetLine(GifFile,
|
||||
&ScreenBuffer[MIN(j, MaximumScreenHeight)][Col],
|
||||
Width) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < Height; i++, Row++) {
|
||||
GifQprintf("\b\b\b\b%-4d", i);
|
||||
if (DGifGetLine(GifFile, &ScreenBuffer[MIN(Row, MaximumScreenHeight)][Col],
|
||||
Width) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
MaximumScreenHeight = MIN(i - 1, MaximumScreenHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXTENSION_RECORD_TYPE:
|
||||
/* Skip any extension blocks in file: */
|
||||
if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
while (Extension != NULL) {
|
||||
if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TERMINATE_RECORD_TYPE:
|
||||
break;
|
||||
default: /* Should be traps by DGifGetRecordType. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (RecordType != TERMINATE_RECORD_TYPE);
|
||||
|
||||
/* Lets display it - set the global variables required and do it: */
|
||||
BackGround = GifFile -> SBackGroundColor;
|
||||
ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap :
|
||||
GifFile -> SColorMap);
|
||||
ColorMapSize = 1 << (GifFile -> IColorMap ? GifFile -> IBitsPerPixel :
|
||||
GifFile -> SBitsPerPixel);
|
||||
|
||||
gettextinfo(&TextInfo); /* Save current mode so we can recover. */
|
||||
|
||||
initgraph(&GraphDriver, &GraphMode, BGIPath);
|
||||
if (graphresult() != grOk) /* Error occured during init. */
|
||||
GIF_EXIT("Graphics System Error, failed to initialize driver.");
|
||||
|
||||
if (getmaxcolor() + 1 < ColorMapSize) {
|
||||
sprintf(Str, "GIF Image color map (%d) is too big for device (%d).\n",
|
||||
ColorMapSize, getmaxcolor() + 1);
|
||||
closegraph();
|
||||
GIF_EXIT(Str);
|
||||
}
|
||||
|
||||
/* Initialize hardware pallete and also select fore/background color. */
|
||||
BackGround = ForeGround = 1;
|
||||
Sum = ((int) ColorMap[1].Red) +
|
||||
((int) ColorMap[1].Green) +
|
||||
((int) ColorMap[1].Blue);
|
||||
j = k = Sum;
|
||||
for (i = 0; i < ColorMapSize; i++) {
|
||||
setrgbpalette(i, ColorMap[i].Red >> 2,
|
||||
ColorMap[i].Green >> 2,
|
||||
ColorMap[i].Blue >> 2);
|
||||
|
||||
Sum = ((int) ColorMap[i].Red) +
|
||||
((int) ColorMap[i].Green) +
|
||||
((int) ColorMap[i].Blue);
|
||||
if (i != 0 && Sum > j) { /* Dont use color 0. */
|
||||
ForeGround = i;
|
||||
j = Sum;
|
||||
}
|
||||
if (i != 0 && Sum <= k) { /* Dont use color 0. */
|
||||
BackGround = i;
|
||||
k = Sum;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceMaxX = getmaxx(); /* Read size of physical screen. */
|
||||
DeviceMaxY = getmaxy();
|
||||
ScreenWidth = GifFile -> SWidth;
|
||||
ScreenHeight = MIN(GifFile -> SHeight, MaximumScreenHeight);
|
||||
|
||||
Tone(500, 10);
|
||||
DisplayScreen(ScreenBuffer, GifFile);
|
||||
|
||||
if (DGifCloseFile(GifFile) == GIF_ERROR) {
|
||||
PrintGifError();
|
||||
closegraph();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
closegraph();
|
||||
|
||||
textmode(TextInfo.currmode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Routine to be called for the user installed driver: *
|
||||
****************************************************************************/
|
||||
static int huge detectVGA(void)
|
||||
{
|
||||
return BGIUserDriverMode;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Routine to install the user BGI driver information. *
|
||||
****************************************************************************/
|
||||
static void BGIInstallUserDriver(char *BGIUserDriverNameMode)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(BGIUserDriverNameMode, '/')) != NULL ||
|
||||
(p = strrchr(BGIUserDriverNameMode, '\\')) != NULL) {
|
||||
p[0] = 0;
|
||||
BGIPath = strdup(BGIUserDriverNameMode);
|
||||
p++;
|
||||
}
|
||||
|
||||
p = strtok(p, ".");
|
||||
BGIUserDriverName = strdup(p);
|
||||
|
||||
p = strtok(NULL, ".");
|
||||
if (sscanf(p, "%d", &BGIUserDriverMode) != 1 || BGIUserDriverName == NULL)
|
||||
GIF_EXIT("User [-u] BGI specification has wrong format.");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Given the screen buffer, display it: *
|
||||
* The following commands are available (case insensitive). *
|
||||
* 1. Four arrow to move along the screen (only if ScreenBuffer > physical *
|
||||
* screen in that direction. *
|
||||
* 2. C - goto cursor mode - print current color & position in GIF screen *
|
||||
* of the current pixel cursor is on. *
|
||||
* 3. D - zoom out by factor of 2. *
|
||||
* 4. R - redraw current image. *
|
||||
* 5. S - Print Current status/options. *
|
||||
* 6. U - zoom in by factor of 2. *
|
||||
* 7. ' ' - stop drawing current image. *
|
||||
* 8. ESC - to quit. *
|
||||
******************************************************************************/
|
||||
static void DisplayScreen(GifRowType *ScreenBuffer, GifFileType *GifFile)
|
||||
{
|
||||
int DeviceTop, DeviceLeft, /* Where ScreenBuffer is to mapped to ours. */
|
||||
ScreenTop, ScreenLeft, /* Porsion of ScreenBuffer to start display. */
|
||||
XPanning, YPanning, /* Amount to move using the arrows. */
|
||||
GetK, DrawIt = TRUE;
|
||||
|
||||
XPanning = DeviceMaxX / 2;
|
||||
YPanning = DeviceMaxY / 2;
|
||||
|
||||
SetPosition(SET_POSITION_RESET,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
0, 0);
|
||||
|
||||
do {
|
||||
if (DrawIt && !MyKbHit()) {
|
||||
DrawScreen(ScreenBuffer, ScreenLeft, ScreenTop,
|
||||
DeviceLeft, DeviceTop);
|
||||
Tone(2000, 200);
|
||||
}
|
||||
DrawIt = TRUE;
|
||||
switch (GetK = GetKey()) {
|
||||
case 'C':
|
||||
DoCursorMode(ScreenBuffer, ScreenLeft, ScreenTop,
|
||||
DeviceLeft, DeviceTop);
|
||||
DrawIt = TRUE;
|
||||
break;
|
||||
case 'D':
|
||||
if (ZoomFactor > 1) {
|
||||
ZoomFactor >>= 1;
|
||||
SetPosition(SET_POSITION_ZOOM_D,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
0, 0);
|
||||
}
|
||||
else {
|
||||
Tone(1000, 100);
|
||||
DrawIt = FALSE;
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
break;
|
||||
case 'S':
|
||||
PrintSettingStatus(GifFile);
|
||||
break;
|
||||
case 'U':
|
||||
if (ZoomFactor < 256) {
|
||||
ZoomFactor <<= 1;
|
||||
SetPosition(SET_POSITION_ZOOM_U,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
0, 0);
|
||||
}
|
||||
else {
|
||||
Tone(1000, 100);
|
||||
DrawIt = FALSE;
|
||||
}
|
||||
break;
|
||||
case KEY_ESC:
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
SetPosition(SET_POSITION_PAN,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
-XPanning, 0);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
SetPosition(SET_POSITION_PAN,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
XPanning, 0);
|
||||
break;
|
||||
case KEY_UP:
|
||||
SetPosition(SET_POSITION_PAN,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
0, -YPanning);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
SetPosition(SET_POSITION_PAN,
|
||||
&ScreenLeft, &ScreenTop,
|
||||
&DeviceLeft, &DeviceTop,
|
||||
0, YPanning);
|
||||
break;
|
||||
default:
|
||||
DrawIt = FALSE;
|
||||
Tone(800, 100);
|
||||
Tone(300, 200);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (GetK != KEY_ESC);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Routine to print (in text mode), current program status. *
|
||||
******************************************************************************/
|
||||
static void PrintSettingStatus(GifFileType *GifFile)
|
||||
{
|
||||
char s[80];
|
||||
|
||||
setcolor(ForeGround);
|
||||
|
||||
CPrintStr(PROGRAM_NAME, 1);
|
||||
|
||||
sprintf(s, "GIF File - %s.", GifFileName);
|
||||
CPrintStr(s, 10);
|
||||
|
||||
sprintf(s, "Gif Screen Size = [%d, %d]. Contains %d image(s).",
|
||||
GifFile -> SWidth, GifFile -> SHeight, ImageNum);
|
||||
CPrintStr(s, 20);
|
||||
|
||||
if (GifFile -> SColorMap)
|
||||
sprintf(s,
|
||||
"Has Screen Color map of %d bits. BackGround = [%d, %d, %d].",
|
||||
GifFile -> SBitsPerPixel,
|
||||
GifFile -> SColorMap[GifFile -> SBackGroundColor].Red,
|
||||
GifFile -> SColorMap[GifFile -> SBackGroundColor].Green,
|
||||
GifFile -> SColorMap[GifFile -> SBackGroundColor].Blue);
|
||||
else
|
||||
sprintf(s, "No Screen color map.");
|
||||
CPrintStr(s, 30);
|
||||
|
||||
if (GifFile -> IColorMap)
|
||||
sprintf(s, "Has Image map of %d bits (last image). Image is %s.",
|
||||
GifFile -> IBitsPerPixel,
|
||||
(GifFile -> IInterlace ? "interlaced" : "non interlaced"));
|
||||
else
|
||||
sprintf(s, "No Image color map.");
|
||||
CPrintStr(s, 40);
|
||||
|
||||
CPrintStr("Press anything to continue:", 60);
|
||||
MyGetCh();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Routine to cprintf given string centered at given Y level, and attr: *
|
||||
******************************************************************************/
|
||||
static void CPrintStr(char *Str, int y)
|
||||
{
|
||||
setfillstyle(SOLID_FILL, BackGround);
|
||||
bar(0, y, textwidth(Str) + 2, y + textheight(Str) + 2);
|
||||
|
||||
setcolor(ForeGround);
|
||||
outtextxy(1, y + 1, Str);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Routine to set the position of Screen in Device, and what porsion of the *
|
||||
* screen should be visible: *
|
||||
* MoveX, MoveY are the panning factors (if both zero - initialize). *
|
||||
******************************************************************************/
|
||||
static void SetPosition(int Why,
|
||||
int *ScreenLeft, int *ScreenTop,
|
||||
int *DeviceLeft, int *DeviceTop,
|
||||
int MoveX, int MoveY)
|
||||
{
|
||||
|
||||
MoveX /= ZoomFactor; /* Make sure move move same amount independent. */
|
||||
MoveY /= ZoomFactor; /* of what ZommFactor is. */
|
||||
|
||||
/* Figure out position of GIF file in real device X axis: */
|
||||
if (ScreenWidth * ZoomFactor <= DeviceMaxX + 1) {
|
||||
/* Device is big enough to hold all the image X axis: */
|
||||
*ScreenLeft = 0;
|
||||
*DeviceLeft = (DeviceMaxX - ScreenWidth * ZoomFactor) / 2;
|
||||
}
|
||||
else {
|
||||
/* Device is too small to hold all the image X axis: */
|
||||
switch (Why) {
|
||||
case SET_POSITION_RESET:
|
||||
*ScreenLeft = 0;
|
||||
break;
|
||||
case SET_POSITION_ZOOM_U:
|
||||
*ScreenLeft += DeviceMaxX / (2 * ZoomFactor);
|
||||
break;
|
||||
case SET_POSITION_ZOOM_D:
|
||||
*ScreenLeft -= DeviceMaxX / (4 * ZoomFactor);
|
||||
break;
|
||||
case SET_POSITION_PAN:
|
||||
if (MoveX != 0) *ScreenLeft += MoveX;
|
||||
break;
|
||||
}
|
||||
if (*ScreenLeft < 0) *ScreenLeft = 0;
|
||||
if ((ScreenWidth - *ScreenLeft) * ZoomFactor < DeviceMaxX + 1)
|
||||
*ScreenLeft = (ScreenWidth * ZoomFactor -
|
||||
DeviceMaxX + 1) / ZoomFactor;
|
||||
*DeviceLeft = 0;
|
||||
}
|
||||
|
||||
/* Figure out position of GIF file in real device Y axis: */
|
||||
if (ScreenHeight * ZoomFactor <= DeviceMaxY + 1) {
|
||||
/* Device is big enough to hold all the image Y axis: */
|
||||
*ScreenTop = 0;
|
||||
*DeviceTop = (DeviceMaxY - ScreenHeight * ZoomFactor) / 2;
|
||||
}
|
||||
else {
|
||||
/* Device is too small to hold all the image Y axis: */
|
||||
switch (Why) {
|
||||
case SET_POSITION_RESET:
|
||||
*ScreenTop = 0;
|
||||
break;
|
||||
case SET_POSITION_ZOOM_U:
|
||||
*ScreenTop += DeviceMaxY / (2 * ZoomFactor);
|
||||
break;
|
||||
case SET_POSITION_ZOOM_D:
|
||||
*ScreenTop -= DeviceMaxY / (4 * ZoomFactor);
|
||||
break;
|
||||
case SET_POSITION_PAN:
|
||||
if (MoveY != 0) *ScreenTop += MoveY;
|
||||
break;
|
||||
}
|
||||
if (*ScreenTop < 0) *ScreenTop = 0;
|
||||
if ((ScreenHeight - *ScreenTop) * ZoomFactor < DeviceMaxY + 1)
|
||||
*ScreenTop = (ScreenHeight * ZoomFactor -
|
||||
DeviceMaxY - 1) / ZoomFactor;
|
||||
*DeviceTop = 0;
|
||||
}
|
||||
|
||||
/* Make sure the position is on Byte boundary (8 pixels per byte): */
|
||||
*DeviceLeft &= 0xfff8;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* The real drawing of the image is performed here. Few things are taken into *
|
||||
* account: *
|
||||
* 1. The zoom factor. If > 1 each pixel is multiplied this amount vertically *
|
||||
* and horizontally. *
|
||||
* The image is drawn from ScreenBuffer ScreenTop/Left in the bottom/right *
|
||||
* directions, onto the Device DeviceTop/Left in the bottom/right direction *
|
||||
* Pressing space during drawing will abort this routine. *
|
||||
******************************************************************************/
|
||||
static void DrawScreen(GifRowType *ScreenBuffer,
|
||||
int ScreenLeft, int ScreenTop, int DeviceLeft, int DeviceTop)
|
||||
{
|
||||
int i, j, k, l, CountZoomJ, CountZoomI,
|
||||
DeviceWidth, DeviceRight, ScreenBottom;
|
||||
unsigned char *ImageBuffer, *p;
|
||||
GifPixelType *Line;
|
||||
|
||||
/* Make sure we start from scratch. Note cleardevice() uses color 0 even */
|
||||
/* if it may be non black. */
|
||||
cleardevice();
|
||||
|
||||
if (getmaxcolor() + 1 == 256) {
|
||||
/* Optimize this case - one byte per pixel. */
|
||||
DeviceWidth = ScreenWidth * ZoomFactor;
|
||||
if (DeviceWidth + DeviceLeft > DeviceMaxX)
|
||||
DeviceWidth = DeviceMaxX - DeviceLeft;
|
||||
DeviceRight = DeviceLeft + DeviceWidth - 1;
|
||||
ScreenBottom = ScreenTop + ScreenHeight - 1;
|
||||
|
||||
if ((ImageBuffer = malloc(imagesize(DeviceLeft, DeviceTop,
|
||||
DeviceRight, DeviceTop))) == NULL)
|
||||
GIF_EXIT("Failed to allocate memory required, aborted.");
|
||||
getimage(DeviceLeft, DeviceTop, DeviceRight, DeviceTop, ImageBuffer);
|
||||
|
||||
for (k = DeviceTop; k < DeviceMaxY && ScreenTop <= ScreenBottom;) {
|
||||
Line = ScreenBuffer[ScreenTop++];
|
||||
p = ImageBuffer + 4; /* point on first pixel in bitmap. */
|
||||
if (ZoomFactor == 1)
|
||||
memcpy(p, &Line[ScreenLeft], DeviceWidth);
|
||||
else {
|
||||
for (i = 0, j = ScreenLeft, CountZoomI = ZoomFactor;
|
||||
i < DeviceWidth;
|
||||
i++) {
|
||||
*p++ = Line[j];
|
||||
if (--CountZoomI == 0) {
|
||||
CountZoomI = ZoomFactor;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Abort drawing if space bar was pressed: */
|
||||
if (MyKbHit() && GetKey() == ' ') break;
|
||||
|
||||
for (i = 0; i < ZoomFactor; i++)
|
||||
putimage(DeviceLeft, k++, ImageBuffer, COPY_PUT);
|
||||
}
|
||||
|
||||
free((char *) ImageBuffer);
|
||||
}
|
||||
else {
|
||||
for (CountZoomJ = ZoomFactor, j = ScreenTop, l = DeviceTop;
|
||||
j < ScreenHeight && l <= DeviceMaxY; l++) {
|
||||
Line = ScreenBuffer[j];
|
||||
|
||||
/* Abort drawing if space bar was pressed: */
|
||||
if (MyKbHit() && GetKey() == ' ') break;
|
||||
|
||||
for (CountZoomI = ZoomFactor, i = ScreenLeft, k = DeviceLeft;
|
||||
i < ScreenWidth && k <= DeviceMaxX;) {
|
||||
putpixel(k++, l, Line[i]);
|
||||
|
||||
if (!--CountZoomI) {
|
||||
/* Go to next column: */
|
||||
i++;
|
||||
CountZoomI = ZoomFactor;
|
||||
}
|
||||
}
|
||||
|
||||
if (!--CountZoomJ) {
|
||||
/* Go to next row: */
|
||||
j++;
|
||||
CountZoomJ = ZoomFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Walks along the current image, while printing pixel value and position. *
|
||||
* 4 arrows may be used, and any other key will abort this operation *
|
||||
******************************************************************************/
|
||||
static void DoCursorMode(GifRowType *ScreenBuffer,
|
||||
int ScreenLeft, int ScreenTop, int DeviceLeft, int DeviceTop)
|
||||
{
|
||||
int GetK, DeviceRight, DeviceBottom, x, y, Step;
|
||||
GifPixelType Pixel;
|
||||
char s[80];
|
||||
|
||||
DeviceRight = DeviceLeft + (ScreenWidth - ScreenLeft) * ZoomFactor;
|
||||
if (DeviceRight > DeviceMaxX) DeviceRight = DeviceMaxX;
|
||||
|
||||
DeviceBottom = DeviceTop + (ScreenHeight - ScreenTop) * ZoomFactor;
|
||||
if (DeviceBottom > DeviceMaxY) DeviceBottom = DeviceMaxY;
|
||||
|
||||
x = (DeviceLeft + DeviceRight) / 2;
|
||||
y = (DeviceTop + DeviceBottom) / 2;
|
||||
|
||||
setwritemode(XOR_PUT);
|
||||
|
||||
while (TRUE) {
|
||||
Pixel = ScreenBuffer[ScreenTop + (y - DeviceTop) / ZoomFactor]
|
||||
[ScreenLeft + (x - DeviceLeft) / ZoomFactor];
|
||||
sprintf(s, "Color = %3d [%3d, %3d, %3d], X = %3d, Y = %3d",
|
||||
Pixel,
|
||||
ColorMap[Pixel].Red,
|
||||
ColorMap[Pixel].Green,
|
||||
ColorMap[Pixel].Blue,
|
||||
(x - DeviceLeft) / ZoomFactor,
|
||||
(y - DeviceTop) / ZoomFactor);
|
||||
|
||||
setfillstyle(SOLID_FILL, BackGround);
|
||||
bar(0, 0, textwidth(s) + 2, textheight(s) + 2);
|
||||
|
||||
setcolor(ForeGround);
|
||||
outtextxy(1, 1, s);
|
||||
|
||||
line(0, y, DeviceMaxX, y);
|
||||
line(x, 0, x, DeviceMaxY);
|
||||
GetK = GetKey();
|
||||
line(0, y, DeviceMaxX, y);
|
||||
line(x, 0, x, DeviceMaxY);
|
||||
|
||||
Step = 10;
|
||||
switch (GetK) {
|
||||
case '1':
|
||||
GetK = KEY_END;
|
||||
break;
|
||||
case '2':
|
||||
GetK = KEY_DOWN;
|
||||
break;
|
||||
case '3':
|
||||
GetK = KEY_PGDN;
|
||||
break;
|
||||
case '4':
|
||||
GetK = KEY_LEFT;
|
||||
break;
|
||||
case '6':
|
||||
GetK = KEY_RIGHT;
|
||||
break;
|
||||
case '7':
|
||||
GetK = KEY_HOME;
|
||||
break;
|
||||
case '8':
|
||||
GetK = KEY_UP;
|
||||
break;
|
||||
case '9':
|
||||
GetK = KEY_PGUP;
|
||||
break;
|
||||
default:
|
||||
Step = 1;
|
||||
}
|
||||
|
||||
switch (GetK) {
|
||||
case KEY_LEFT:
|
||||
x -= Step;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
x += Step;
|
||||
break;
|
||||
case KEY_UP:
|
||||
y -= Step;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
y += Step;
|
||||
break;
|
||||
case KEY_PGUP:
|
||||
y -= Step;
|
||||
x += Step;
|
||||
break;
|
||||
case KEY_PGDN:
|
||||
y += Step;
|
||||
x += Step;
|
||||
break;
|
||||
case KEY_HOME:
|
||||
y -= Step;
|
||||
x -= Step;
|
||||
break;
|
||||
case KEY_END:
|
||||
y += Step;
|
||||
x -= Step;
|
||||
break;
|
||||
default:
|
||||
setwritemode(COPY_PUT);
|
||||
return;
|
||||
}
|
||||
if (x < DeviceLeft) x = DeviceLeft;
|
||||
if (x >= DeviceRight) x = DeviceRight;
|
||||
if (y < DeviceTop) y = DeviceTop;
|
||||
if (y >= DeviceBottom) y = DeviceBottom;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Return non zero value if at list one character exists in keyboard queue. *
|
||||
* This routine emulates kbhit() which do uses stdin and useless for us. *
|
||||
******************************************************************************/
|
||||
static int MyKbHit(void)
|
||||
{
|
||||
return bioskey(1);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Get a key from keyboard directly (bypass stdin as we might redirect it). *
|
||||
* This routine emulates getch() which do uses stdin and useless for us. *
|
||||
******************************************************************************/
|
||||
static int MyGetCh(void)
|
||||
{
|
||||
static int Extended = 0;
|
||||
int c;
|
||||
|
||||
if (Extended) {
|
||||
c = Extended;
|
||||
Extended = 0;
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
c = bioskey(0);
|
||||
if (c & 0x0ff)
|
||||
return c;
|
||||
else {
|
||||
Extended = c >> 8;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Get a key from keyboard, and translating operational keys into special *
|
||||
* codes (>255). Lower case characters are upercased. *
|
||||
******************************************************************************/
|
||||
static int GetKey(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (TRUE) switch (c = MyGetCh()) {
|
||||
case 0: /* Extended code - get the next extended char. */
|
||||
switch (MyGetCh()) {
|
||||
case 75: return KEY_LEFT;
|
||||
case 77: return KEY_RIGHT;
|
||||
case 72: return KEY_UP;
|
||||
case 80: return KEY_DOWN;
|
||||
case 71: return KEY_HOME;
|
||||
case 79: return KEY_END;
|
||||
case 73: return KEY_PGUP;
|
||||
case 81: return KEY_PGDN;
|
||||
case 83: return KEY_DELETE;
|
||||
case 82: return KEY_INSERT;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
return KEY_BSPACE;
|
||||
case 10:
|
||||
case 13:
|
||||
return KEY_RETURN;
|
||||
case 27:
|
||||
return KEY_ESC;
|
||||
default:
|
||||
if (isprint(c)) {
|
||||
if (islower(c))
|
||||
return toupper(c);
|
||||
else
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
Tone(800, 100);
|
||||
Tone(300, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Routine to make some sound with given Frequency, Time milliseconds: *
|
||||
******************************************************************************/
|
||||
static void Tone(int Frequency, int Time)
|
||||
{
|
||||
if (BeepsDisabled) return;
|
||||
|
||||
sound(Frequency);
|
||||
delay(Time);
|
||||
nosound();
|
||||
}
|
Reference in New Issue
Block a user