📄 images.cpp
字号:
// constructor opens the file as binary, readonly. It reads the dac palette
// into the member p_rec structure palette, corrects it for shift, sets sev-
// eral status variables, and closes the file. On error it sets pcx.status to
// Failed, and reports the error in the images module error record imag_err.
// **************************************************************************
pcx::pcx(char *fspec)
{
char check_pal;
int i,j;
FILE *filptr;
status = NoErr;
if ((filptr = fopen(fspec,"rb"))==NULL)
{
status = FileOpenErr;
return;
}
if (fseek(filptr,-769L,SEEK_END) != 0)
{
status= FileReadErr;
fclose(filptr);
return;
}
fread(&check_pal,1,1,filptr);
// check for 256 color PCX palette tag 0x0C at filelength-769
if (check_pal!=0x0C)
{
status = FileFormatErr;
fclose(filptr);
return;
}
// read in the palette and store in class member data palette
if (fread(palette,1,768,filptr) != 768)
{
status = FileReadErr;
fclose(filptr);
return;
}
// shift the palette values right by two bits (pcx specific detail)
for (i=0;i<256;i++)
{
for (j=0;j<3;j++)
{
palette[i][j]=palette[i][j]>>2;
}
}
// leave the file pointer on the first byte of image data
if (fseek(filptr,128,SEEK_SET) != 0)
{
status = FileReadErr;
fclose(filptr);
return;
}
fclose(filptr);
buffer=NULL; // pcx:image.buffer
for (j=0;fspec[j]!=0;j++); // these two lines copy the path to
memcpy(fpath,fspec,j+1); // to storage in the object data
in_ram = 0; // pcx.in_ram
packed = 0; // pcx.packed
return;
}
// **************************************************************************
// unpacktoram unpacks the rle encoded into the buffer pointed to by dest.
// No size checking is performed on the buffer. The unpacking process cont-
// inues until num_bytes have been moved to dest. The function checks the
// state of the in_ram member variable. If the image is not in memory it is
// unpacked from the disk file. If the image is in memory in compressed mode
// it is unpacked from memory. If the image is in memory, but is already
// uncompressed the function returns UnknownErr.
// **************************************************************************
char pcx::unpacktoram(char far *dest, unsigned int num_bytes)
{
unsigned int bytes=0; // counts unpacked bytes
char c; // byte being processed
int runlen; // length of packet
unsigned int src_cntr = 0; // counts through ram buffer if any
char far *streambuf;
FILE *filptr;
if (!in_ram)
{
if ((filptr=fopen(fpath,"rb"))==NULL)
return(FileOpenErr);
if ((streambuf=new char[5000]) != NULL)
{
setbuf(filptr,streambuf);
}
if (fseek(filptr,128L,SEEK_SET) != 0)
{
fclose(filptr);
if (streambuf != NULL)
delete(streambuf);
return(FileReadErr);
}
do
{
c=fgetc(filptr);
if ((c & 0xc0) == 0xc0)
{
runlen = (c & 0x3f);
c=fgetc(filptr);
while(runlen--) (dest[bytes++]=c);
}
else
dest[bytes++]=c;
} while (bytes<num_bytes);
fclose(filptr);
if (streambuf!=NULL)
delete(streambuf);
}
else
{
if (!packed)
return(UnknownErr);
else
{
do
{
c=buffer[src_cntr++];
if ((c & 0xc0) == 0xc0)
{
runlen = (c & 0x3f);
c=buffer[src_cntr++];
while(runlen--) (dest[bytes++]=c);
}
else
dest[bytes++]=c;
} while (bytes<num_bytes);
}
}
return(NoErr);
}
// **************************************************************************
// the load() member function reads the pcx file into a memory buffer. The
// pointer to the buffer and the buffer size are internal to the class, and
// do not need to be taken into account by the programmer. The data is loaded
// based on the value of method. A set of three constants is defined for this
// value; Packed, Unpacked, and Bestfit. If method = packed the data will be
// read into the memory buffer in compressed PCX format, but the palette and
// header data will be stripped. If method = unpacked the data is uncompress-
// to memory using the unpacktoram() function. In either case, if there is
// not sufficient memory, the function returns MemErr. If method = Bestfit
// the function will unpack the data is possible, or load it packed if not,
// and finally returns MemErr if neither method can be used. If successfull
// the function sets internal switches so that other pcx member functions
// will know that the image data is already loaded, and in what form it has
// been loaded.
// **************************************************************************
char pcx::load(char method)
{
unsigned readsize;
FILE *filptr;
// make sure the image isn't already loaded
if (!in_ram)
{
if (method == Bestfit)
{
// if enough ram for the image load unpacked
if (coreleft() >= 64000U)
{
method = Unpacked;
}
else
// if not enough ram open the file, compare it's size to the
// available memory, and load it packed if there's enough room
// or return a MemErr if there isn't.
{
if ((filptr=fopen(fpath,"rb"))==NULL)
{
return(FileOpenErr);
}
readsize = filelength(fileno(filptr))-(128+769);
fclose(filptr);
if (coreleft() >= readsize)
method = Packed;
else
return(MemErr);
}
}
// if method = packed then allocate a buffer the size of the image
// file with the header and palette data stripped out. Zero the
// buffer, then read the packed data into it. Finally, set in_ram
// and packed = 1 (pcx class member data used by display() member
// function)
if (method == Packed)
{
if ((filptr=fopen(fpath,"rb"))==NULL)
return(FileOpenErr);
readsize = filelength(fileno(filptr))-(128+769);
if ((buffer = new char[readsize]) == NULL)
{
fclose(filptr);
return(MemErr);
}
_fmemset(buffer,0,readsize);
if (fseek(filptr, 128L, SEEK_SET) != 0)
{
fclose(filptr);
delete(buffer);
return(FileReadErr);
}
if (fread(buffer, 1, readsize, filptr) != readsize)
{
fclose(filptr);
delete(buffer);
return(FileReadErr);
}
fclose(filptr);
in_ram = 1;
packed = 1;
}
else
// if method = Unpacked then allocate a 64000 byte buffer, and
// unpack the data into it.
{
if ((buffer = new char[64000U]) == NULL)
return(MemErr);
_fmemset(buffer,0,64000U);
if(unpacktoram(buffer,64000U) != NoErr)
{
delete(buffer);
in_ram = 0;
return(SecondaryErr);
}
else
{
in_ram = 1;
packed = 0;
}
}
}
return(NoErr);
}
// **************************************************************************
// the unload() member function frees the memory allocated to the pcx data,
// and updates the internal switches so that other member functions will
// know that the image is no longer in memory.
// **************************************************************************
void pcx::unload()
{
if (in_ram)
{
delete(buffer);
in_ram = 0;
packed = 0;
}
}
// **************************************************************************
// pcx::display can be used to display a PCX class object to screen using
// various fade types, wipes, and dissolves. All fade types other than Soft-
// Fade and SnapWipe require a screen buffer of 64000 bytes. If that memory
// is not available the function returns MemErr. The PCX will be displayed
// whether it is: on disk, in ram packed, or in ram unpacked (in order of
// decreasing execution time).
//
// The following fade types are available:
//
// SnapWipe - snaps the pcx to screen, basic block mem move.
// SplitVerticalWipe - fades from the top and bottom toward center.
// SplitHorizWipe - fades from the right and left toward center.
// SlideVerticalWipe - slides pic in from left and right
// SlideHorizWipe - slides pic in from top and bottom
// VerticalDissolve - overlays multiple vertical slices
// HorizDissolve - overlays multiple horizontal slices
// SparkleDissolve - fades with random block placement
// SoftFade - dac palette intensity fade, 64 passes
// **************************************************************************
char pcx::display(char fadetype)
{
char far *do_buffer;
char loaded_here = 0;
// SoftFade (palette fade) requires the palette to be cleared.
if (fadetype == SoftFade)
{
wait_vbi();
clrpalette(0,256);
}
else
// all other types require the new palette to be loaded
{
wait_vbi();
loadpalette(0,256,palette);
}
// if the image is not in ram, or is in ram compressed, then it
// needs to be unpacked, from either disk or memory, to either the
// video buffer or a memory buffer depending on the fade type.
if ((!in_ram) || ((in_ram) && (packed)))
{
// these two fade types simply require the data unpacked to vseg.
if ((fadetype == SoftFade) || (fadetype == SnapWipe))
{
if (unpacktoram((char far *)MK_FP(0xa000,0), 64000U) != NoErr)
return(SecondaryErr);
}
else
// all the others require the data in a 64K memory buffer
// so one is allocated, and the data is unpacked to it
{
if ((do_buffer = new char[64100U]) == NULL)
return(MemErr);
if (unpacktoram(do_buffer, 64000U) != NoErr)
{
delete(do_buffer);
return(SecondaryErr);
}
loaded_here = 1;
}
}
else
// if the data is in ram uncompressed it's ready to go. The only
// action necessary is to copy it to the video buffer for the two
// simple fade types. The buffer identifier is member data of the
// image class, and stores a pointer to the image buffer. In both
// cases do_buffer is assigned the value of buffer, and then the
// operations are performed on it. This simplifies the calls to
// the fade functions below.
{
do_buffer = buffer;
// for these two fade types copy the data over to vseg
if ((fadetype == SoftFade) || (fadetype == SnapWipe))
{
wait_vbi();
asm {
push es
push ds
push cx
push si
push di
mov es, GRAPH_SEG
xor di, di
lds si, do_buffer
mov cx, 32000
rep movsw
pop di
pop si
pop cx
pop ds
pop es
}
}
}
switch (fadetype)
{
case SoftFade: fadepalettein(0,256,palette); break;
case SplitVerticalWipe: doSplitVerticalWipe(do_buffer); break;
case SplitHorizWipe: doSplitHorizWipe(do_buffer); break;
case SlideVerticalWipe: doSlideVerticalWipe(do_buffer); break;
case SlideHorizWipe: doSlideHorizWipe(do_buffer); break;
case VerticalDissolve: doVerticalDissolve(do_buffer); break;
case HorizDissolve: doHorizDissolve(do_buffer); break;
case SparkleDissolve: doSparkleDissolve(do_buffer); break;
}
if (loaded_here)
delete(do_buffer);
return(NoErr);
}
// **************************************************************************
// remove() clears the current image from the screen using the passed fade
// type. It will clear the screen regardless of what image is on it. No
// checking is performed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -