home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
REND.LZH
/
PIC1600
/
F_BMP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-16
|
14KB
|
524 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WINDOWS
#undef LittleEndian
#include <windows.h>
#define LittleEndian
#endif
#include "piclib.h"
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef WINDOWS
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} BITMAPINFOHEADER;
#endif
typedef struct {
#ifdef WINDOWS
HFILE hfile;
OFSTRUCT openbuf;
#endif
FILE *fp;
unsigned char buffer[BUFFERSIZE];
int bufferlines, buffercount;
int offset, paloffset;
int width, skip;
unsigned char *p;
unsigned char *paletdata;
Pixel palettedata[256];
int palettecolors;
int paletteoverflow;
int lines;
PicReduceData *reduce;
Pixel *pixelbuffer;
} PicWork;
static inline int palettecode(PicWork *work, Pixel c)
{
int i;
for (i = 0; i < work->palettecolors; ++i) {
if (work->palettedata[i] == c) {
return i;
}
}
if (work->palettecolors >= 256) {
work->paletteoverflow++;
return 0;
}
work->palettedata[work->palettecolors] = c;
return work->palettecolors++;
}
static void paletteget(PicWork *work, unsigned char *p)
{
int i;
for (i = 0; i < work->palettecolors; ++i) {
*p++ = (unsigned char)((work->palettedata[i] >> 8) & 0xff);
*p++ = (unsigned char)((work->palettedata[i] >> 24));
*p++ = (unsigned char)((work->palettedata[i] >> 16) & 0xff);
*p++ = 0;
}
for (; i < 256; ++i) {
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
}
#define inline
#ifdef WINDOWS
static void outputshort(unsigned short n, HFILE hf)
{
unsigned char c[2];
c[0] = (unsigned char)( n & 255);
c[1] = (unsigned char)((n>>8) & 255);
_lwrite(hf, (char*)c, 2);
}
static void outputlong(unsigned long n, HFILE hf)
{
unsigned char c[4];
c[0] = (unsigned char)( n & 255);
c[1] = (unsigned char)((n>> 8) & 255);
c[2] = (unsigned char)((n>>16) & 255);
c[3] = (unsigned char)((n>>24) & 255);
_lwrite(hf, (char*)c, 4);
}
#else
static inline void outputshort(unsigned short n, FILE *fp)
{
fputc( n & 255, fp );
fputc( ( n >> 8 ) & 255, fp );
}
static inline void outputlong(unsigned long n, FILE *fp)
{
outputshort((short)( n & 0xffffL ), fp);
outputshort((short)( ( n >> 16 ) & 0xffffL ), fp);
}
#endif
static inline unsigned short inputshort(FILE *fp)
{
unsigned short i;
i = (unsigned short)fgetc(fp);
i += (unsigned short)(fgetc(fp) * 256);
return i;
}
static inline unsigned long inputlong(FILE *fp)
{
unsigned long i;
i = fgetc(fp);
i += fgetc(fp) << 8;
i += fgetc(fp) << 16;
i += fgetc(fp) << 24;
return i;
}
int PicReadHeader_BMP(PicData *pd, FILE *fp, unsigned char *magic)
{
extern PicFunction PicFunction_BMP;
if (memcmp(magic, "BM", 2) != 0) {
return FALSE;
}
pd->func = &PicFunction_BMP;
return TRUE;
}
#define HEADER1 14
#define HEADER2 40
#define HEADERSIZE (HEADER1+HEADER2)
#define DPM 3937
static int PicReadHeader_BMP_Main(PicData *pd, FILE *fp)
{
int i;
PicWork *work = pd->work;
inputshort(fp);
inputlong(fp); /*bfSize*/
inputlong(fp); /*bfReserved1, bfReserved2*/
work->offset = inputlong(fp); /*bfOffBits*/
/*printf("offset = %x\n", work->offset);*/
i = inputlong(fp); /*biSize*/
work->paloffset = HEADER1 + i;
/*printf("paletoffset = %x\n", work->paloffset);*/
pd->pixelX = (short)inputlong(fp); /*biWidth*/
pd->pixelY = (short)inputlong(fp); /*biHeight*/
/*printf("(%d,%d)\n", pd->pixelX, pd->pixelY);*/
inputshort(fp); /*biPlanes*/
i = inputshort(fp); /*biBitCount*/
/*printf("BitCount = %d\n", i);*/
if (i == 8) {
pd->mode = BMP_PALETTE;
} else if (i == 24) {
pd->mode = BMP_TRUECOLOR;
} else {
return FALSE;
}
i = inputlong(fp); /*biCompression, BI_RGB=0*/
/*printf("BiCompression = %d\n", i);*/
if (i != 0) {
return FALSE;
}
#if 0
outputlong(length, fp); /*biSizeImage*/
outputlong(DPM, fp); /*biXPixPerMeter*/
outputlong(DPM, fp); /*biYPixPerMeter*/
outputlong(0, fp); /*biClrUsed*/
outputlong(0, fp); /*biClrImportant*/
#endif
return TRUE;
}
#ifdef WINDOWS
int PicWriteHeader_BMP(PicData *pd, HFILE fp)
#else
int PicWriteHeader_BMP(PicData *pd, FILE *fp)
#endif
{
PicWork *work = pd->work;
int length;
#ifdef WINDOWS
_lwrite(fp, "BM", 2);
#else
fputc('B', fp);
fputc('M', fp);
#endif
length = work->width * pd->pixelY;
/*printf("length=%dx%d=%d\n",work->width, pd->pixelY, length);*/
if (pd->mode != BMP_TRUECOLOR) {
outputlong(length + HEADER1 + HEADER2, fp);
outputlong(0, fp);
outputlong((long)(HEADER1+HEADER2+256*4), fp);
} else {
outputlong(length + HEADER1 + HEADER2, fp);
outputlong(0, fp);
outputlong((long)(HEADER1+HEADER2), fp);
}
outputlong((long)HEADER2, fp); /*biSize*/
outputlong((long)pd->pixelX, fp); /*biWidth*/
outputlong((long)pd->pixelY, fp); /*biHeight*/
outputshort(1, fp); /*biPlanes*/
outputshort(pd->mode == BMP_TRUECOLOR ? 24 : 8, fp);
/*biBitCount*/
outputlong(0L, fp); /*biCompression, BI_RGB=0*/
outputlong(length, fp); /*biSizeImage*/
outputlong(DPM, fp); /*biXPixPerMeter*/
outputlong(DPM, fp); /*biYPixPerMeter*/
outputlong(0, fp); /*biClrUsed*/
outputlong(0, fp); /*biClrImportant*/
#ifndef WINDOWS
if (ferror(fp)) return FALSE;
#endif
return TRUE;
}
static int PicOpen_BMP(PicData *pd, FILE *fp, int flag)
{
PicWork *work;
unsigned char pal[256*4];
int i;
/*printf("Open BMP\n");*/
if ((work = malloc(sizeof(PicWork))) == NULL) {
return FALSE;
}
pd->work = work;
work->fp = fp;
work->lines = 0;
work->reduce = NULL;
work->pixelbuffer = NULL;
if (pd->flag == PIC_READ) {
if (PicReadHeader_BMP_Main(pd, fp) == FALSE) return FALSE;
if (pd->mode == BMP_TRUECOLOR) {
work->width = ( ( pd->pixelX * 3 + 3 ) / 4 ) * 4;
work->skip = work->width - pd->pixelX * 3;
} else {
work->width = ( ( pd->pixelX + 3 ) / 4 ) * 4;
work->skip = work->width - pd->pixelX;
fseek(fp, work->paloffset, SEEK_SET);
if (ferror(work->fp)) return FALSE;
fread(pal, 1, 256*4, fp);
if (ferror(work->fp)) return FALSE;
for (i = 0; i < 256; i++) {
work->palettedata[i] = (pal[i*4+1] << 24)
| (pal[i*4+2] << 16)
| (pal[i*4 ] << 8);
}
}
/*printf("width=%d, skip=%d\n", work->width, work->skip);*/
work->bufferlines = BUFFERSIZE / work->width;
work->buffercount = work->bufferlines-1;
} else {
pd->mode = flag;
if (pd->mode == BMP_TRUECOLOR) {
work->width = ( ( pd->pixelX * 3 + 3 ) / 4 ) * 4;
work->skip = work->width - pd->pixelX * 3;
} else {
work->width = ( ( pd->pixelX + 3 ) / 4 ) * 4;
work->skip = work->width - pd->pixelX;
work->paletteoverflow = FALSE;
work->palettecolors = 0;
if ((work->reduce = PicColorReduceOpen(pd->pixelX, REDUCE_DITHER_ERROR216)) == NULL) {
return FALSE;
}
if ((work->pixelbuffer = malloc(sizeof(Pixel) * pd->pixelX)) == NULL) {
return FALSE;
}
}
work->bufferlines = BUFFERSIZE / work->width;
work->buffercount = work->bufferlines-1;
#ifdef WINDOWS
fclose(fp);
work->hfile = OpenFile(pd->filename, &work->openbuf, OF_WRITE | OF_SHARE_EXCLUSIVE);
if (work->hfile == HFILE_ERROR) return FALSE;
if (PicWriteHeader_BMP(pd, work->hfile) == FALSE) return FALSE;
#else
if (PicWriteHeader_BMP(pd, fp) == FALSE) return FALSE;
#endif
}
return TRUE;
}
static int PicOutput_BMP(PicData *pd, Pixel *pixel)
{
unsigned char *p;
PicWork *work = pd->work;
Pixel *in;
int i;
if (work->reduce && work->pixelbuffer) {
PicColorReduce(work->reduce, work->pixelbuffer, pixel);
pixel = work->pixelbuffer;
}
if (pd->mode == BMP_TRUECOLOR) {
p = work->buffer + work->width * work->buffercount;
in = pixel;
for (i = 0; i < pd->pixelX; ++i) {
*p++ = (unsigned char)((*in >> 8) & 0xff);
*p++ = (unsigned char)((*in >> 24));
*p++ = (unsigned char)((*in >> 16) & 0xff);
in++;
}
for (i = work->skip; i > 0; --i) {
*p++ = 0;
}
if (work->buffercount-- == 0) {
work->buffercount = work->bufferlines-1;
#ifdef WINDOWS
if (_llseek(work->hfile, HEADERSIZE + (pd->pixelY-work->lines-1) * work->width, 0) == HFILE_ERROR) {
return FALSE;
}
if (_lwrite(work->hfile, (char*)work->buffer, work->width * work->bufferlines) == HFILE_ERROR) {
return FALSE;
}
#else
fseek(work->fp, HEADERSIZE + (pd->pixelY-work->lines-1) * work->width, SEEK_SET);
if (ferror(work->fp)) return FALSE;
fwrite(work->buffer, 1, work->width * work->bufferlines, work->fp);
if (ferror(work->fp)) return FALSE;
#endif
}
} else {
p = work->buffer + work->width * work->buffercount;
in = pixel;
for (i = 0; i < pd->pixelX; ++i) {
*p++ = palettecode(work, *in++);
}
for (i = work->skip; i > 0; --i) {
*p++ = 0;
}
if (work->buffercount-- == 0) {
work->buffercount = work->bufferlines-1;
#ifdef WINDOWS
if (_llseek(work->hfile, HEADERSIZE + 256*4 + (pd->pixelY-work->lines-1) * work->width, 0) == HFILE_ERROR) {
return FALSE;
}
if (_lwrite(work->hfile, (char*)work->buffer, work->width * work->bufferlines) == HFILE_ERROR) {
return FALSE;
}
#else
fseek(work->fp, HEADERSIZE + 256 * 4 + (pd->pixelY-work->lines-1) * work->width, SEEK_SET);
if (ferror(work->fp)) return FALSE;
fwrite(work->buffer, 1, work->width * work->bufferlines, work->fp);
if (ferror(work->fp)) return FALSE;
#endif
}
}
work->lines++;
return TRUE;
}
static int PicInput_BMP(PicData *pd, Pixel *pixel)
{
unsigned char *p;
PicWork *work = pd->work;
Pixel *out;
int i;
if (pd->mode == BMP_TRUECOLOR) {
if (work->buffercount == work->bufferlines-1) {
if (work->buffercount > pd->pixelY-work->lines - 1) {
work->buffercount = pd->pixelY-work->lines - 1;
}
fseek(work->fp, work->offset + (pd->pixelY-work->lines-work->buffercount - 1) * work->width, SEEK_SET);
if (ferror(work->fp)) return FALSE;
fread(work->buffer, 1, work->width * work->bufferlines, work->fp);
if (ferror(work->fp)) return FALSE;
}
p = work->buffer + work->width * work->buffercount;
out = pixel;
for (i = 0; i < pd->pixelX; ++i) {
*out++ = (p[1] << 24) | (p[0] << 8) | (p[2] << 16);
p += 3;
}
if (work->buffercount-- == 0) {
work->buffercount = work->bufferlines-1;
}
} else {
if (work->buffercount == work->bufferlines-1) {
if (work->buffercount > pd->pixelY-work->lines - 1) {
work->buffercount = pd->pixelY-work->lines - 1;
}
fseek(work->fp, work->offset + (pd->pixelY-work->lines-work->buffercount - 1) * work->width, SEEK_SET);
if (ferror(work->fp)) return FALSE;
fread(work->buffer, 1, work->width * work->bufferlines, work->fp);
if (ferror(work->fp)) return FALSE;
}
p = work->buffer + work->width * work->buffercount;
out = pixel;
for (i = 0; i < pd->pixelX; ++i) {
*out++ = work->palettedata[*p++];
}
if (work->buffercount-- == 0) {
work->buffercount = work->bufferlines-1;
}
}
work->lines++;
return TRUE;
}
static int PicClose_BMP(PicData *pd)
{
int ret = TRUE;
PicWork *work = pd->work;
if (pd->flag == PIC_READ) {
} else {
if (pd->mode == BMP_TRUECOLOR) {
if (work->buffercount < work->bufferlines-1) {
#ifdef WINDOWS
if (_llseek(work->hfile, HEADERSIZE, 0) == HFILE_ERROR) {
ret = FALSE;
}
if (_lwrite(work->hfile,
(char*)(work->buffer + work->width * (work->buffercount+1)),
work->width * (work->bufferlines-1-work->buffercount)) == HFILE_ERROR) {
ret = FALSE;
}
#else
fseek(work->fp, HEADERSIZE, SEEK_SET);
if (ferror(work->fp)) ret = FALSE;
fwrite(work->buffer + work->width * (work->buffercount+1),
1, work->width * (work->bufferlines-1-work->buffercount), work->fp);
if (ferror(work->fp)) ret = FALSE;
#endif
}
} else {
unsigned char pal[256*4];
if (work->buffercount < work->bufferlines-1) {
#ifdef WINDOWS
if (_llseek(work->hfile, HEADERSIZE + 256*4, 0) == HFILE_ERROR) {
ret = FALSE;
}
if (_lwrite(work->hfile,
(char*)(work->buffer + work->width * (work->buffercount+1)),
work->width * (work->bufferlines-1-work->buffercount)) == HFILE_ERROR) {
ret = FALSE;
}
#else
fseek(work->fp, HEADERSIZE + 256 * 4, SEEK_SET);
if (ferror(work->fp)) ret = FALSE;
fwrite(work->buffer + work->width * (work->buffercount+1),
1, work->width * (work->bufferlines-1-work->buffercount), work->fp);
if (ferror(work->fp)) ret = FALSE;
#endif
}
paletteget(work, pal);
#ifdef WINDOWS
if (_llseek(work->hfile, HEADERSIZE, 0) == HFILE_ERROR) {
ret = FALSE;
}
if (_lwrite(work->hfile, (char*)pal, 256*4) == HFILE_ERROR) {
ret = FALSE;
}
#else
fseek(work->fp, HEADERSIZE, SEEK_SET);
if (ferror(work->fp)) ret = FALSE;
fwrite(pal, 1, 256*4, work->fp);
if (ferror(work->fp)) ret= FALSE;
#endif
}
if (work->reduce) {
PicColorReduceClose(work->reduce);
}
free(work->pixelbuffer);
}
#ifdef WINDOWS
if (pd->flag == PIC_READ) {
fclose(work->fp);
} else {
_lclose(work->hfile);
}
#else
fclose(work->fp);
#endif
free(work);
return ret;
}
PicFunction PicFunction_BMP = {
"BMP",
PicReadHeader_BMP,
PicOpen_BMP,
PicOutput_BMP,
PicInput_BMP,
PicClose_BMP
};