room101/DIB.CPP

241 lines
4.8 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int size;
int width;
int height;
short planes;
short bitcount;
int compression;
int sizeimage;
int xpelspermeter;
int ypelspermeter;
int clrused;
int clrimportant;
} DIB;
int DIBSize (void* dib) {return ((DIB*)dib)->size ;}
int DIBWidth (void* dib) {return ((DIB*)dib)->width ;}
int DIBHeight (void* dib) {return ((DIB*)dib)->height;}
int DIBPlanes (void* dib) {return DIBSize(dib) < 14 ? 1 : ((DIB*)dib)->planes ;}
int DIBBitCount (void* dib) {return DIBSize(dib) < 16 ? 24 : ((DIB*)dib)->bitcount ;}
int DIBCompression (void* dib) {return DIBSize(dib) < 20 ? 0 : ((DIB*)dib)->compression ;}
int DIBSizeImage (void* dib) {return DIBSize(dib) < 24 ? 0 : ((DIB*)dib)->sizeimage ;}
int DIBXPelsPerMeter(void* dib) {return DIBSize(dib) < 28 ? 0 : ((DIB*)dib)->xpelspermeter;}
int DIBYPelsPerMeter(void* dib) {return DIBSize(dib) < 32 ? 0 : ((DIB*)dib)->ypelspermeter;}
int DIBClrUsed (void* dib) {return DIBSize(dib) < 36 ? 0 : ((DIB*)dib)->clrused; }
int DIBClrImportant (void* dib) {return DIBSize(dib) < 40 ? 0 : ((DIB*)dib)->clrimportant; }
int
DIBNumberOfColors(void* dib)
{
return 1 << DIBBitCount(dib);
}
int
DIBPaletteSize(void* dib)
{
return DIBClrUsed(dib) ? DIBClrUsed(dib) : DIBNumberOfColors(dib) > 256 ? 0 : DIBNumberOfColors(dib);
}
void*
DIBColorTable(void* dib)
{
return &((char*)dib)[DIBSize(dib)];
}
void*
DIBPixels(void* dib)
{
return &((int*)DIBColorTable(dib))[DIBPaletteSize(dib)];
}
int
DIBWidthInBytes(void* dib)
{
return (DIBWidth(dib) * DIBBitCount(dib) + 7) >> 3;
}
int
DIBBytesPerRow(void* dib)
{
return (DIBWidthInBytes(dib) + 3) >> 2 << 2;
}
int
DIBPitch(void* dib)
{
return DIBBytesPerRow(dib) * DIBPlanes(dib);
}
void*
DIBPixelRow(void* dib, int i)
{
return &((char*)DIBPixels(dib))[DIBPitch(dib) * i];
}
char
DIBRed(void* dib, int i)
{
return ((char*)DIBColorTable(dib))[(i << 2) + 2];
}
char
DIBGreen(void* dib, int i)
{
return ((char*)DIBColorTable(dib))[(i << 2) + 1];
}
char
DIBBlue(void* dib, int i)
{
return ((char*)DIBColorTable(dib))[(i << 2) + 0];
}
int
DIBMemoryUsage(void* dib)
{
return DIBSize(dib) + DIBPaletteSize(dib) * 4 + DIBPitch(dib) * DIBHeight(dib);
}
void*
DIBCreate(int width, int height, int planes, int bitcount)
{
DIB* dib;
dib = (DIB*) calloc(1, sizeof(DIB));
dib->size = sizeof(DIB);
dib->width = width;
dib->height = height;
dib->planes = planes;
dib->bitcount = bitcount;
dib->clrused = DIBPaletteSize(dib);
dib = (DIB*) realloc(dib, DIBMemoryUsage(dib));
return dib;
}
void
DIBDelete(void* dib)
{
free(dib);
}
void*
DIBLoad(char* name)
{
FILE* fp;
void* dib = NULL;
if ((fp = fopen(name, "rb")) != NULL)
{
fseek(fp, 0, SEEK_END);
int size = ftell(fp) - 14;
if ((dib = malloc(size)) != NULL)
{
fseek(fp, 14, SEEK_SET);
fread(dib, size, 1, fp);
}
fclose(fp);
}
return dib;
}
void*
DIBSave(void* dib, char* name)
{
FILE* fp;
if ((fp = fopen(name, "wb")) != NULL)
{
/* TODO: Write out bitmap file header */
fwrite(dib, DIBMemoryUsage(dib), 1, fp);
fclose(fp);
}
return dib;
}
void*
DIBFlip(void* dib)
{
int height = DIBHeight(dib);
int pitch = DIBPitch(dib);
char* top = (char*) DIBPixelRow(dib, 0);
char* bot = (char*) DIBPixelRow(dib, height - 1);
char* buf = (char*) malloc(pitch);
if (buf)
{
for (height >>= 1; height--; top += pitch, bot -= pitch)
{
memcpy(buf, top, pitch);
memcpy(top, bot, pitch);
memcpy(bot, buf, pitch);
}
free(buf);
}
return dib;
}
typedef struct
{
short width;
short height;
short bitcount;
} Image;
int
ImageWidth(void* image)
{
return ((Image*)image)->width;
}
int
ImageHeight(void* image)
{
return ((Image*)image)->height;
}
int
ImageBitCount(void* image)
{
return ((Image*)image)->bitcount;
}
void*
ImageFromDIB(void* dib)
{
Image* image = &((Image*)DIBPixels(dib))[-1];
image->width = DIBPitch(dib);
image->height = DIBHeight(dib);
image->bitcount = DIBBitCount(dib);
return image;
}
long*
PaletteFromDIB(long* palette, void* dib)
{
for (int i = 0; i < DIBPaletteSize(dib); i++)
{
palette[i] =
(DIBRed (dib, i) >> 2 >> 0) |
(DIBGreen(dib, i) >> 2 << 8) |
(DIBBlue (dib, i) >> 2 << 16);
}
return palette;
}