📄 encoder.c
字号:
/*
encoder.c - GIF Encoder and associated routines
This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef XFRACT
#include <io.h>
#endif
#include "fractint.h"
#include "fractype.h"
#include "prototyp.h"
/* MCP 10-27-91 */
#ifdef WINFRACT
extern int OperCancelled;
void OpenStatusBox(void);
void UpdateStatusBox(unsigned long Partial, unsigned long Total);
void CloseStatusBox(void);
#endif
extern char s_cantopen[];
extern char s_cantwrite[];
extern char s_cantcreate[];
extern char s_cantunderstand[];
extern char s_cantfind[];
extern char maxfn;
static void _fastcall setup_save_info(struct fractal_info *);
static int inittable(void);
static int _fastcall shftwrite(BYTE *color,int numcolors);
static int _fastcall raster(unsigned int);
static int _fastcall extend_blk_len(int datalen);
static int _fastcall put_extend_blk(int block_id,int block_len,char far *block_data);
static int _fastcall store_item_name(char *);
extern int initbatch;
extern char far *resume_info; /* pointer to resume info if allocated */
extern int resume_len; /* length of resume info */
extern char LName[];
extern char FormName[]; /* formula name */
extern char IFSName[];
extern int active_system; /* 0=dos, 1=windows */
extern int far *ranges;
extern int rangeslen;
extern int sxdots,sydots; /* # of dots on the physical screen */
extern int sxoffs,syoffs; /* physical top left of logical screen */
extern int xdots, ydots; /* # of dots on the logical screen */
extern int viewwindow; /* 0 for full screen, 1 for window */
extern float finalaspectratio; /* for view shape and rotation */
extern int viewxdots,viewydots; /* explicit view sizing */
extern int colors; /* maximum colors available */
extern int dotmode; /* so we can detect disk-video */
extern char overwrite; /* overwrite on/off */
extern int resave_flag; /* resaving after a timed save */
extern int started_resaves;
extern int timedsave; /* if doing an auto save */
extern int disk16bit; /* 16 bit continuous potential */
extern BYTE dacbox[256][3]; /* Video-DAC (filled in by SETVIDEO) */
extern int gotrealdac; /* DAC valid? */
extern int daclearn, daccount; /* used by the color-cyclers */
extern SEGTYPE extraseg; /* used by Save-to-GIF routines */
extern int debugflag;
extern int gif87a_flag; /* if 1, supress GIF extension blocks */
extern int calc_status;
extern long calctime;
extern char stdcalcmode;
extern int fractype;
extern double xxmin,xxmax;
extern double yymin,yymax;
extern double xx3rd,yy3rd;
extern double param[];
extern int major_method; /* inverse julia parms */
extern int minor_method;
extern int maxit; /* try this many iterations */
extern int fillcolor; /* fill color: -1 = normal */
extern int inside; /* inside color: 1=blue */
extern int outside; /* outside color, if set */
extern int finattract; /* finite attractor option */
extern int forcesymmetry;
extern int LogFlag; /* non-zero if logarithmic palettes */
extern int rflag, rseed;
extern int periodicitycheck;
extern char useinitorbit;
extern _CMPLX initorbit;
extern int pot16bit;
extern float finalaspectratio;
extern double potparam[3]; /* three potential parameters*/
extern double inversion[];
extern int decomp[];
extern int distest; /* non-zero if distance estimator */
extern int distestwidth;
extern int init3d[20]; /* '3d=nn/nn/nn/...' values */
extern char floatflag; /* floating-point fractals? */
extern int usr_biomorph;
extern int bailout; /* user input bailout value */
extern int previewfactor;
extern int xtrans;
extern int ytrans;
extern int red_crop_left;
extern int red_crop_right;
extern int blue_crop_left;
extern int blue_crop_right;
extern int red_bright;
extern int blue_bright;
extern int xadjust;
extern int eyeseparation;
extern int glassestype;
extern int save_system;
extern int save_release;
extern int display3d; /* 3D display flag: 0 = OFF */
extern int Ambient;
extern int RANDOMIZE;
extern int haze;
extern int transparent[2];
extern int rotate_lo,rotate_hi;
extern char busy;
extern float screenaspect;
extern double mxmaxfp;
extern double mxminfp;
extern double mymaxfp;
extern double myminfp;
extern int zdots;
extern float originfp;
extern float depthfp;
extern float heightfp;
extern float widthfp;
extern float distfp;
extern float eyesfp;
extern int neworbittype;
extern short juli3Dmode;
#ifdef XFRACT
extern int decode_fractal_info();
#endif
/*
Save-To-Disk Routines (GIF)
GIF and 'Graphics Interchange Format' are trademarks (tm) of Compuserve
Incorporated, an H&R Block Company.
The following routines perform the GIF encoding when the 's' key is pressed.
The routines refer to several variables that are declared elsewhere
[colors, xdots, ydots, and 'dacbox'], and rely on external routines to
actually read and write screen pixels [getcolor(x,y) and putcolor(x,y,color)].
(Writing pixels is just stuffed in here as a sort of visual status report,
and has nothing to do with any GIF function.) They also rely on the
existence of an externally-defined 64K dataspace and they use the routines
'toextra()' and 'cmpextra()' to deal with that dataspace (in the same manner
as 'memcpy()' and 'memcmp()' would). Otherwise, they perform a generic
GIF-encoder function.
Note that these routines use small string- and hash-tables, and "flush"
the GIF entries whenever the hash-table gets two-thirds full or the string
table gets full. They also use the GIF encoding technique of limiting the
encoded string length to a specific size, "adding" a string to the hash table
at that point even if a matching string exists ("adding" is in quotes, because
if a matching string exists we can increment the code counter but safely throw
the duplicate string away, saving both string space and a hash table entry).
This results in relatively good speed and small data space, but at the
expense of compression efficiency (filesize). These trade-offs could be
adjusted by modifying the #DEFINEd variables below.
Note that the 'strlocn' and 'teststring' routines are declared
to be external just so that they can be defined (and the space re-used)
elsewhere. The actual declarations are in the assembler code.
*/
#define MAXTEST 100 /* maximum single string length */
#define MAXSTRING 64000 /* total space reserved for strings */
/* maximum number of strings available */
#define MAXENTRY 5003 /* (a prime number is best for hashing) */
#ifndef XFRACT
extern unsigned int strlocn[MAXENTRY];
extern BYTE teststring[MAXTEST];
extern BYTE block[266]; /* GIF-encoded blocks go here */
#else
unsigned int strlocn[10240];
BYTE teststring[MAXTEST];
BYTE block[266]; /* GIF-encoded blocks go here */
#endif
static int numsaves = 0; /* For adjusting 'save-to-disk' filenames */
static FILE *out;
static int last_colorbar;
static int save16bit;
static int outcolor1s, outcolor2s;
static int lentest, lastentry, numentries, numrealentries;
static unsigned int nextentry;
static int clearcode, endcode;
static unsigned int hashcode;
static BYTE blockcount;
static int startbits, codebits, bytecount, bitcount;
static char paletteBW[] = { /* B&W palette */
0, 0, 0, 63, 63, 63,
};
static char paletteCGA[] = { /* 4-color (CGA) palette */
0, 0, 0, 21, 63, 63, 63, 21, 63, 63, 63, 63,
};
static char paletteEGA[] = { /* 16-color (EGA/CGA) pal */
0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
};
void encoder_overlay() { } /* for restore_active_ovly */
int savetodisk(filename) /* save-to-disk routine */
char *filename;
{
char tmpmsg[41]; /* before openfile in case of overrun */
char openfile[80], openfiletype[10];
char tmpfile[80];
int newfile;
int i, j, outcolor1, outcolor2, interrupted;
ENTER_OVLY(OVLY_ENCODER);
restart:
save16bit = disk16bit;
if (gif87a_flag) /* not storing non-standard fractal info */
save16bit = 0;
strcpy(openfile,filename); /* decode and open the filename */
strcpy(openfiletype,DEFAULTFRACTALTYPE);/* determine the file extension */
if (save16bit)
strcpy(openfiletype,".pot");
for (i = 0; i < strlen(openfile); i++)
if (openfile[i] == '.') {
strcpy(openfiletype,&openfile[i]);
openfile[i] = 0;
}
if (resave_flag != 1)
updatesavename(filename); /* for next time */
strcat(openfile,openfiletype);
strcpy(tmpfile,openfile);
if (access(openfile,0) != 0) /* file doesn't exist */
newfile = 1;
else { /* file already exists */
if (overwrite == 0) {
if (resave_flag == 0)
goto restart;
if (started_resaves == 0) { /* first save of a savetime set */
updatesavename(filename);
goto restart;
}
}
if (access(openfile,2) != 0) {
sprintf(tmpmsg,s_cantwrite,openfile);
stopmsg(0,tmpmsg);
EXIT_OVLY;
return -1;
}
newfile = 0;
i = strlen(tmpfile);
while (--i >= 0 && tmpfile[i] != SLASHC)
tmpfile[i] = 0;
strcat(tmpfile,"fractint.tmp");
}
started_resaves = (resave_flag == 1) ? 1 : 0;
if (resave_flag == 2) /* final save of savetime set? */
resave_flag = 0;
if ((out=fopen(tmpfile,"wb")) == NULL) {
sprintf(tmpmsg,s_cantcreate,tmpfile);
stopmsg(0,tmpmsg);
EXIT_OVLY;
return -1;
}
if (dotmode == 11) { /* disk-video */
char buf[60];
sprintf(buf,"Saving %s",openfile);
dvid_status(1,buf);
}
#ifdef XFRACT
else {
putstring(3,0,0,"Saving to:");
putstring(4,0,0,openfile);
putstring(5,0,0," ");
}
#endif
busy = 1;
if (debugflag != 200)
interrupted = encoder();
else
interrupted = timer(2,NULL); /* invoke encoder() via timer */
busy = 0;
fclose(out);
if (interrupted) {
char buf[200];
sprintf(buf,"Save of %s interrupted.\nCancel to ",openfile);
if (newfile)
strcat(buf,"delete the file,\ncontinue to keep the partial image.");
else
strcat(buf,"retain the original file,\ncontinue to replace original with new partial image.");
interrupted = 1;
if (stopmsg(2,buf) < 0) {
interrupted = -1;
unlink(tmpfile);
}
}
if (newfile == 0 && interrupted >= 0) { /* replace the real file */
unlink(openfile); /* success assumed since we checked */
rename(tmpfile,openfile); /* earlier with access */
}
if (dotmode != 11) { /* supress this on disk-video */
if (active_system == 0) { /* no bars in Windows version */
outcolor1 = outcolor1s;
outcolor2 = outcolor2s;
for (j = 0; j <= last_colorbar; j++) {
if ((j & 4) == 0) {
if (++outcolor1 >= colors) outcolor1 = 0;
if (++outcolor2 >= colors) outcolor2 = 0;
}
for (i = 0; 250*i < xdots; i++) { /* clear vert status bars */
putcolor(i,j,getcolor(i,j)^outcolor1);
putcolor(xdots-1-i,j,getcolor(xdots-1-i,j)^outcolor2);
}
}
}
#ifdef XFRACT
putstring(5,0,0,"Saving done\n");
#endif
}
else /* disk-video */
dvid_status(1,"");
if (interrupted) {
texttempmsg(" *interrupted* save ");
if (initbatch == 2 || initbatch == 5) initbatch = 3; /* if batch mode, set error level */
EXIT_OVLY;
return -1;
}
if (timedsave == 0) {
buzzer(0);
if (initbatch == 0) {
sprintf(tmpmsg," File saved as %s ",openfile);
texttempmsg(tmpmsg);
}
}
EXIT_OVLY;
return 0;
}
int encoder()
{
int i, ydot, xdot, color, outcolor1, outcolor2;
int width;
int rownum, rowlimit;
unsigned int hashentry;
BYTE bitsperpixel, x;
int entrynum;
struct fractal_info save_info;
if(initbatch) /* flush any impending keystrokes */
while(keypressed())
getakey();
setup_save_info(&save_info);
#ifndef XFRACT
bitsperpixel = 0; /* calculate bits / pixel */
for (i = colors; i >= 2; i /= 2 )
bitsperpixel++;
startbits = bitsperpixel+1; /* start coding with this many bits */
if (colors == 2)
startbits++; /* B&W Klooge */
#else
if (colors==2) {
bitsperpixel = 1;
startbits = 3;
} else {
bitsperpixel = 8;
startbits = 9;
}
#endif
clearcode = 1 << (startbits - 1); /* set clear and end codes */
endcode = clearcode+1;
outcolor1 = 0; /* use these colors to show progress */
outcolor2 = 1; /* (this has nothing to do with GIF) */
if (colors > 2) {
outcolor1 = 2;
outcolor2 = 3;
}
if (((++numsaves) & 1) == 0) { /* reverse the colors on alt saves */
i = outcolor1;
outcolor1 = outcolor2;
outcolor2 = i;
}
outcolor1s = outcolor1;
outcolor2s = outcolor2;
if (gif87a_flag == 1) {
if (fwrite("GIF87a",6,1,out) != 1) goto oops; /* old GIF Signature */
} else {
if (fwrite("GIF89a",6,1,out) != 1) goto oops; /* new GIF Signature */
}
width = xdots;
rowlimit = ydots;
if (save16bit) {
/* pot16bit info is stored as:
file: double width rows, right side of row is low 8 bits
diskvid: ydots rows of colors followed by ydots rows of low 8 bits
decoder: returns (row of color info then row of low 8 bits) * ydots
*/
rowlimit <<= 1;
width <<= 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -