Old tools that got removed a long time ago.
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1545 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
/*--pbio.c----------------------------------------------------------*
|
||||
* *
|
||||
* Routines to read & write PC Paintbrush files. *
|
||||
* *
|
||||
* Date Who Changes *
|
||||
* --------- --- -------------------------------------------------- *
|
||||
* 31-Mar-89 mjc band read & write to allow large files. *
|
||||
* 19-Apr-89 mjc 256 color palette added at end of paintbrush file. *
|
||||
* *
|
||||
* TBD: haven't added scroll-offset logic to "to planar" case, since
|
||||
* ANIMDISK is only 8 bpp.
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
#include "main.h"
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <sys\types.h>
|
||||
#include <sys\stat.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define local static
|
||||
|
||||
/* RowBytes computes the number of bytes in a row, from the width in pixels.*/
|
||||
#define RowBytes(w) (((w) + 15) >> 4 << 1)
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
* 256 Color Palette
|
||||
*
|
||||
* When reading the paintbrush file, the 256 color palette is
|
||||
* sought only if the version number in the header is 5 and the
|
||||
* bits per pixel * planes == 8. The last 769 bytes of the file
|
||||
* must start with 0x0C, and be followed by the 768 byte palette.
|
||||
*
|
||||
* When writing the paintbrush file, we write
|
||||
* version 5 in the header, and append the palette to the end of
|
||||
* the file in the same format as above (0x0C followed by 768
|
||||
* bytes of palette).
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Return SUCCESS, FAIL, or specific errors ... */
|
||||
#define PB_NOT_ENUF_MEM 2
|
||||
#define PB_NO_256_PALETTE 3
|
||||
|
||||
local WORD readCount; /* For compression. */
|
||||
local UBYTE readChar;
|
||||
|
||||
/* --- Forward declarations. */
|
||||
void GetByte(WORD file);
|
||||
BOOL PutBytes(BYTE far * ptr, WORD bytes, WORD file);
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
typedef struct {
|
||||
BYTE manufacturer;
|
||||
BYTE version;
|
||||
BYTE encoding;
|
||||
BYTE bitsperpixel;
|
||||
WORD xmin, ymin, xmax, ymax;
|
||||
WORD hres, vres;
|
||||
BYTE colormap[16][3];
|
||||
BYTE reserved;
|
||||
BYTE nplanes;
|
||||
WORD bytesperline;
|
||||
} PCPAINTBRUSH_HEADER;
|
||||
|
||||
local PCPAINTBRUSH_HEADER *pbh = NULL; /* paintbrush header pointer */
|
||||
/* Global pointer so can allocate in header, use fields in body. */
|
||||
|
||||
/*--------------------- Bad Paintbrush Header ----------------------*/
|
||||
#define BadPbHeader(s) (FAIL)
|
||||
|
||||
/*-------------------- Invalid Paintbrush File ---------------------*/
|
||||
#define InvalidPbFile() (FAIL)
|
||||
|
||||
#define WrongPbFileType() (FAIL) /* Expected different data format.*/
|
||||
#define PCXNo256PaletteMsg()
|
||||
|
||||
/*-----------------------------------------------------------------*
|
||||
* Read the header of a pc paintbrush file.
|
||||
* Sets bmHdr fields. Calls reSize if necessary.
|
||||
* Returns SUCCESS or FAIL.
|
||||
*-----------------------------------------------------------------*/
|
||||
|
||||
BOOL ReadPCX_Header(WORD file, BITMAP *bitmap, LONG *palette,
|
||||
BitMapHeader *bmHdr)
|
||||
{
|
||||
register WORD i;
|
||||
UBYTE c, palet[256][3];
|
||||
|
||||
if (!pbh) /* Test in case we come through twice w/o freeing. */
|
||||
pbh = malloc(sizeof(PCPAINTBRUSH_HEADER) + 4);
|
||||
if (!pbh)
|
||||
return (FAIL);
|
||||
|
||||
if (read(file, (char *)pbh, sizeof(PCPAINTBRUSH_HEADER)) !=
|
||||
sizeof(PCPAINTBRUSH_HEADER))
|
||||
return (InvalidPbFile());
|
||||
|
||||
/* --- To start of pixel data. */
|
||||
if (0 > lseek(file, (LONG) 128, SEEK_SET))
|
||||
return (InvalidPbFile());
|
||||
|
||||
/* --- Check that the header info is valid. */
|
||||
if (pbh->manufacturer != 10)
|
||||
return (InvalidPbFile());
|
||||
|
||||
/* --- Expecting version with palette at end. */
|
||||
if (pbh->version != 5)
|
||||
return (BadPbHeader(s_wrongPBVersion));
|
||||
|
||||
if (pbh->encoding != 1)
|
||||
return (BadPbHeader(s_unknownEncoding));
|
||||
|
||||
if (pbh->bitsperpixel != 1 && pbh->nplanes != 1)
|
||||
return (BadPbHeader(s_wrongLayout));
|
||||
|
||||
if (pbh->bitsperpixel != 8)
|
||||
return (WrongPbFileType());
|
||||
|
||||
/* --- Compute dimensions and # colors. */
|
||||
setmem(bmHdr, sizeof(BitMapHeader), 0);
|
||||
bmHdr->w = 1 + pbh->xmax - pbh->xmin;
|
||||
bmHdr->h = 1 + pbh->ymax - pbh->ymin;
|
||||
bmHdr->nPlanes = pbh->bitsperpixel * pbh->nplanes;
|
||||
/* MAY BE PACKED. */
|
||||
|
||||
/* --- Get the color map. */
|
||||
if (palette != NULL) {
|
||||
/* If a 256 color palette should be present at the end of the
|
||||
* file, try to fetch it from disk and copy it to the palette.
|
||||
*/
|
||||
c = 0;
|
||||
if (lseek(file, (LONG)-769, SEEK_END) >= 0)
|
||||
if (read(file, &c, 1) == 1)
|
||||
if (read(file, (UBYTE *)&palet[0][0], 768) == 768)
|
||||
if (c == 0x0C)
|
||||
for (i = 0; i < 256; ++i)
|
||||
palette[i] = ((LONG)palet[i][0] << 16) +
|
||||
((LONG)palet[i][1] << 8) +
|
||||
((LONG)palet[i][2]);
|
||||
/* --- To start of pixel data (again). */
|
||||
lseek(file, (LONG)128, SEEK_SET);
|
||||
if (c != 0x0C) {
|
||||
/* ---- We couldn't read a 256 color palette at the end
|
||||
* of the file.
|
||||
*/
|
||||
PCXNo256PaletteMsg();
|
||||
return (PB_NO_256_PALETTE);
|
||||
}
|
||||
}
|
||||
return (SUCCESS); /* Header done; BODY yet to do. */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*
|
||||
* Read the pixel data into the bitmap. Return SUCCESS or FAIL.
|
||||
*-----------------------------------------------------------------*/
|
||||
#define MaxPCXPlanes 8 /* 256-color, no mask. */
|
||||
|
||||
BOOL ReadPCX_BODY(WORD file, BITMAP *bitmap, BitMapHeader *bmHdr)
|
||||
{
|
||||
register WORD i, iPlane;
|
||||
BOOL result = SUCCESS;
|
||||
BYTE far *dest;
|
||||
WORD bodyNRows, srcPlanesToUse;
|
||||
WORD bodyIRow; /* Increment from 0..bodyNRows-1. */
|
||||
BYTE far *dests[MaxPCXPlanes]; /* Ptrs to dest scan lines. */
|
||||
WORD useBytes;
|
||||
|
||||
/* --------- Initialization. ---------- */
|
||||
readCount = 0; /* For compression. */
|
||||
|
||||
bodyNRows = MIN(bmHdr->h, bitmap->box.h);
|
||||
srcPlanesToUse = MIN(bitmap->planes + bpp_minus1, bmHdr->nPlanes);
|
||||
|
||||
/* ---------- Read all scan lines. ---------- */
|
||||
OpenIOBuffer(FALSE);
|
||||
|
||||
for (bodyIRow = 0; bodyIRow < bodyNRows; ++bodyIRow) {
|
||||
readCount = 0; /* Just in case, supposed to start anew each line. */
|
||||
|
||||
useBytes = MIN(bitmap->width, pbh->bytesperline);
|
||||
|
||||
/* ----- Read a scan line. */
|
||||
dest = (BYTE far *)BMLineStart(bitmap, bodyIRow, 0);
|
||||
for (i = 0; i < pbh->bytesperline; i++) {
|
||||
GetByte(file);
|
||||
if (i < useBytes)
|
||||
*dest++ = readChar;
|
||||
}
|
||||
}
|
||||
CloseIOBuffer(file);
|
||||
|
||||
done:
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*--------------------- Close Paintbrush File ---------------------*/
|
||||
/* --- NOTE: if change, must change WritePCX_Done, since it calls this. */
|
||||
|
||||
void ReadPCX_Done()
|
||||
{
|
||||
/* --- Free pbh, which is shared by header & body routines. */
|
||||
if (pbh)
|
||||
free(pbh);
|
||||
pbh = NULL;
|
||||
}
|
||||
|
||||
void WritePCX_Done()
|
||||
{
|
||||
ReadPCX_Done();
|
||||
}
|
||||
|
||||
/*---------------------------- Get Byte ---------------------------*/
|
||||
/* Set readCount & readChar. At EOF or file error, returns 0's forever. */
|
||||
|
||||
void GetByte(WORD file)
|
||||
{
|
||||
UBYTE c;
|
||||
|
||||
/* --- if in the middle of a run of encoded bytes, don't read any
|
||||
* more
|
||||
*/
|
||||
if (readCount > 0) {
|
||||
--readCount;
|
||||
return;
|
||||
}
|
||||
readCount = 0;
|
||||
if (GReadOne(file, &c) != 1) {
|
||||
sawEOF:
|
||||
readCount = 32767; /* Huge count of 0's to pad the end. */
|
||||
readChar = 0;
|
||||
return;
|
||||
}
|
||||
if ((c & 0xc0) == 0xc0) {
|
||||
readCount = (0x3f & c) - 1; /* "-1": consuming one of count. */
|
||||
if (GReadOne(file, &c) != 1)
|
||||
goto sawEOF;
|
||||
}
|
||||
readChar = c;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
Output File Routines & Variables
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------*
|
||||
Output header for a PC Paintbrush file with the given number
|
||||
of bitsperpixel and planes. One of these two parms must be 1.
|
||||
ASSUMES OKAY TO TRASH buffer[].
|
||||
Returns SUCCESS or FAIL.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
BOOL WritePCX_Header(WORD file, BITMAP *bitmap, LONG *palette)
|
||||
{
|
||||
register PCPAINTBRUSH_HEADER *ppbh;
|
||||
WORD i;
|
||||
#define GAP_SIZE (128 - sizeof(PCPAINTBRUSH_HEADER))
|
||||
UBYTE buffer1[GAP_SIZE];
|
||||
|
||||
/* --- init the header that we'll write.
|
||||
* Note: since DPaint never reads & writes at the same time,
|
||||
* it is okay to share the same read & write structure,
|
||||
* unlike in CONVERT.EXE.
|
||||
*/
|
||||
if (!pbh) /* Test in case we come through twice w/o
|
||||
* freeing. */
|
||||
pbh = malloc(sizeof(PCPAINTBRUSH_HEADER) + 4);
|
||||
if (!pbh)
|
||||
return (FAIL);
|
||||
ppbh = pbh; /* Register variable for smaller, faster code. */
|
||||
|
||||
setmem(ppbh, sizeof(PCPAINTBRUSH_HEADER) + 4, 0);
|
||||
ppbh->manufacturer = 10;
|
||||
ppbh->version = 5;
|
||||
ppbh->encoding = 1;
|
||||
|
||||
ppbh->bitsperpixel = bpp;
|
||||
ppbh->xmin = ppbh->ymin = 0;
|
||||
ppbh->xmax = bitmap->box.w - 1;
|
||||
ppbh->ymax = bitmap->box.h - 1;
|
||||
ppbh->hres = N_COLUMNS;
|
||||
ppbh->vres = N_LINES;
|
||||
|
||||
/* --- bytesperline doesn't take into account multiple planes.
|
||||
* Output in same format as bitmap (planar vs packed).
|
||||
*/
|
||||
ppbh->bytesperline = bitmap->width;
|
||||
|
||||
ppbh->nplanes = bitmap->planes;
|
||||
ppbh->reserved = 0;
|
||||
|
||||
/* --- First 16 colors of our palette info. */
|
||||
for (i = 0; i < 16; ++i) {
|
||||
ppbh->colormap[i][0] = (BYTE)(palette[i] >> 16);
|
||||
ppbh->colormap[i][1] = (BYTE)(palette[i] >> 8);
|
||||
ppbh->colormap[i][2] = (BYTE) palette[i];
|
||||
}
|
||||
|
||||
/* --- write the 128-byte header */
|
||||
if (GWrite(file, (char *)ppbh, sizeof(PCPAINTBRUSH_HEADER))
|
||||
!= sizeof(PCPAINTBRUSH_HEADER))
|
||||
goto error;
|
||||
|
||||
setmem(buffer1, GAP_SIZE, 0);
|
||||
if (GWrite(file, buffer1, GAP_SIZE) != GAP_SIZE)
|
||||
error:
|
||||
return (FAIL);
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
||||
/* --------------- WritePCX_BODY ---------------
|
||||
* Write the pixel data.
|
||||
* Returns SUCCESS or an error condition.
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
WORD WritePCX_BODY(WORD file, BITMAP *bitmap)
|
||||
{
|
||||
register WORD y;
|
||||
|
||||
/* --- Write to a bit-packed file. */
|
||||
for (y = 0; y < bitmap->box.h; ++y) { /* for each line in band */
|
||||
if (PutBytes((BYTE far *)BMLineStart(bitmap, y, 0),
|
||||
pbh->bytesperline, file))
|
||||
return FAIL;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*-------------------- Output any 256-color palette ------------------------*/
|
||||
BOOL WritePCX_256Palette(WORD file, LONG *palette)
|
||||
{
|
||||
register WORD i;
|
||||
UBYTE c, palet[256][3];
|
||||
|
||||
if (pbh->version == 5 && pbh->bitsperpixel == 8) {
|
||||
for (i = 0; i < 256; ++i) {
|
||||
palet[i][0] = (BYTE)(palette[i] >> 16);
|
||||
palet[i][1] = (BYTE)(palette[i] >> 8);
|
||||
palet[i][2] = (BYTE) palette[i];
|
||||
}
|
||||
c = 0x0C;
|
||||
if (GWrite(file, &c, 1) != 1 ||
|
||||
GWrite(file, (char *)&palet[0][0], 768) != 768)
|
||||
return FAIL;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
* Write bytes to a file, handling packing as it goes.
|
||||
* Returns SUCCESS or FAIL.
|
||||
*-------------------------------------------------------------------
|
||||
*/
|
||||
BOOL PutBytes(BYTE far *ptr, WORD bytes, WORD file)
|
||||
{
|
||||
register WORD startbyte, count;
|
||||
char b;
|
||||
|
||||
while (bytes > 0) {
|
||||
/* --- check for a repeating byte value */
|
||||
startbyte = *ptr++;
|
||||
--bytes;
|
||||
count = 1;
|
||||
while (*ptr == startbyte && bytes > 0 && count < 63) {
|
||||
++ptr;
|
||||
--bytes;
|
||||
++count;
|
||||
}
|
||||
/* --- If we can pack the sequence, or if we have to add a
|
||||
* byte before it because the top 2 bits of the value
|
||||
* are 1's, write a packed sequence of 2 bytes.
|
||||
* Otherwise, just write the byte value.
|
||||
*/
|
||||
if (count > 1 || (startbyte & 0xc0) == 0xc0) {
|
||||
b = 0xc0 | count;
|
||||
if (GWrite(file, &b, 1) != 1)
|
||||
return FAIL;
|
||||
}
|
||||
b = startbyte;
|
||||
if (GWrite(file, &b, 1) != 1)
|
||||
return FAIL;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user