diff options
Diffstat (limited to 'graphics/sam2p/input-bmp.ci')
-rw-r--r-- | graphics/sam2p/input-bmp.ci | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/graphics/sam2p/input-bmp.ci b/graphics/sam2p/input-bmp.ci new file mode 100644 index 0000000000..234626d375 --- /dev/null +++ b/graphics/sam2p/input-bmp.ci @@ -0,0 +1,484 @@ +/* This code is ripped from Autotrace-0.29. Small modifications by pts. */ + +/* input-bmp.ci: reads any bitmap I could get for testing */ + +#ifdef __GNUC__ +#ifndef __clang__ +#pragma implementation +#endif +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* #include "types.h" */ +#include "at_bitmap.h" +/* #include "message.h" */ +/* #include "xstd.h" */ +/* #include "input-bmp.h" */ + +#define MAXCOLORS 256 +/* #define Image long */ + +#define BitSet(byte, bit) (((byte) & (bit)) == (bit)) + +#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0) + +struct Bitmap_File_Head_Struct +{ + char zzMagic[2]; /* 00 "BM" */ + unsigned long bfSize; /* 02 */ + unsigned short zzHotX; /* 06 */ + unsigned short zzHotY; /* 08 */ + unsigned long bfOffs; /* 0A */ + unsigned long biSize; /* 0E */ +} Bitmap_File_Head; + +struct Bitmap_Head_Struct +{ + unsigned long biWidth; /* 12 */ + unsigned long biHeight; /* 16 */ + unsigned short biPlanes; /* 1A */ + unsigned short biBitCnt; /* 1C */ + unsigned long biCompr; /* 1E */ + unsigned long biSizeIm; /* 22 */ + unsigned long biXPels; /* 26 */ + unsigned long biYPels; /* 2A */ + unsigned long biClrUsed; /* 2E */ + unsigned long biClrImp; /* 32 */ + /* 36 */ +} Bitmap_Head; + +static long ToL (unsigned char *); +static short ToS (unsigned char *); +static int ReadColorMap (FILE *, + unsigned char[256][3], + int, + int, + int *); +static unsigned char *ReadImage (FILE *, + int, + int, + unsigned char[256][3], + int, + int, + int, + int); + +#if PTS_SAM2P +bitmap_type bmp_load_image (FILE* filename) +#else +bitmap_type bmp_load_image (at_string filename) +#endif +{ + FILE *fd; + unsigned char buffer[64]; + int ColormapSize, rowbytes, Maps=0, Grey; + unsigned char ColorMap[256][3]; + bitmap_type image; + + #if PTS_SAM2P /**** pts ****/ + fd=filename; + #else + fd = fopen (filename, "rb"); + + if (!fd) + FATAL1 ("Can't open \"%s\"\n", filename); + #endif + + /* It is a File. Now is it a Bitmap? Read the shortest possible header.*/ + + if (!ReadOK(fd, buffer, 18) || (strncmp((const char *)buffer,"BM",2))) + #if PTS_SAM2P /**** pts ****/ + FATALP ("BMP: Not a valid BMP file"); + #else + FATAL ("Not a valid BMP file %s\n"); + #endif + + /* bring them to the right byteorder. Not too nice, but it should work */ + + Bitmap_File_Head.bfSize = ToL (&buffer[0x02]); + Bitmap_File_Head.zzHotX = ToS (&buffer[0x06]); + Bitmap_File_Head.zzHotY = ToS (&buffer[0x08]); + Bitmap_File_Head.bfOffs = ToL (&buffer[0x0a]); + Bitmap_File_Head.biSize = ToL (&buffer[0x0e]); + + /* What kind of bitmap is it? */ + + if (Bitmap_File_Head.biSize == 12) /* OS/2 1.x ? */ + { + if (!ReadOK (fd, buffer, 8)) + FATALP ("BMP: Error reading BMP file header #1"); + + Bitmap_Head.biWidth = ToS (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight = ToS (&buffer[0x02]); /* 14 */ + Bitmap_Head.biPlanes = ToS (&buffer[0x04]); /* 16 */ + Bitmap_Head.biBitCnt = ToS (&buffer[0x06]); /* 18 */ + Bitmap_Head.biCompr = 0; + Bitmap_Head.biSizeIm = 0; + Bitmap_Head.biXPels = Bitmap_Head.biYPels = 0; + Bitmap_Head.biClrUsed = 0; + Maps = 3; + } + else if (Bitmap_File_Head.biSize == 40) /* Windows 3.x */ + { + if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4)) + FATALP ("BMP: Error reading BMP file header #2"); + + Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */ + Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */ + Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */ + Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */ + Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */ + Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */ + Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */ + Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */ + Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */ + /* 36 */ + Maps = 4; + } + else if (Bitmap_File_Head.biSize <= 64) /* Probably OS/2 2.x */ + { + if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4)) + FATALP ("BMP: Error reading BMP file header #3"); + + Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */ + Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */ + Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */ + Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */ + Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */ + Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */ + Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */ + Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */ + Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */ + /* 36 */ + Maps = 3; + } + else + FATALP ("BMP: Error reading BMP file header #4"); + + /* Valid options 1, 4, 8, 16, 24, 32 */ + /* 16 is awful, we should probably shoot whoever invented it */ + + /* There should be some colors used! */ + + ColormapSize = (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps; + + if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8)) + Bitmap_Head.biClrUsed = ColormapSize; + + /* Sanity checks */ + + if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0) + FATALP ("BMP: Error reading BMP file header #5"); + + if (Bitmap_Head.biPlanes != 1) + FATALP ("BMP: Error reading BMP file header #6"); + + if (ColormapSize > 256 || Bitmap_Head.biClrUsed > 256) + FATALP ("BMP: Error reading BMP file header #7"); + + /* Windows and OS/2 declare filler so that rows are a multiple of + * word length (32 bits == 4 bytes) + */ + + rowbytes= ( (Bitmap_Head.biWidth * Bitmap_Head.biBitCnt - 1) / 32) * 4 + 4; + +#ifdef DEBUG + printf("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, Comp: %u, Zeile: %u\n", + Bitmap_File_Head.bfSize,Bitmap_Head.biClrUsed,Bitmap_Head.biBitCnt,Bitmap_Head.biWidth, + Bitmap_Head.biHeight, Bitmap_Head.biCompr, rowbytes); +#endif + + /* Get the Colormap */ + + if (ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey) == -1) + FATALP ("BMP: Cannot read the colormap"); + +#ifdef DEBUG + printf("Colormap read\n"); +#endif + + /* Get the Image and return the ID or -1 on error*/ + image.bitmap = ReadImage (fd, + Bitmap_Head.biWidth, + Bitmap_Head.biHeight, + ColorMap, + Bitmap_Head.biBitCnt, + Bitmap_Head.biCompr, + rowbytes, + Grey); + BITMAP_WIDTH (image) = (at_dimen_t) Bitmap_Head.biWidth; + BITMAP_HEIGHT (image) = (at_dimen_t) Bitmap_Head.biHeight; + BITMAP_PLANES (image) = Grey ? 1 : 3; + + return (image); +} + +static int +ReadColorMap (FILE *fd, + unsigned char buffer[256][3], + int number, + int size, + int *grey) +{ + int i; + unsigned char rgb[4]; + + *grey=(number>2); + for (i = 0; i < number ; i++) + { + if (!ReadOK (fd, rgb, size)) + FATALP ("BMP: Bad colormap"); + + /* Bitmap save the colors in another order! But change only once! */ + + buffer[i][0] = rgb[2]; + buffer[i][1] = rgb[1]; + buffer[i][2] = rgb[0]; + *grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2])); + } + return 0; +} + +static unsigned char* +ReadImage (FILE *fd, + int width, + int height, + unsigned char cmap[256][3], + int bpp, + int compression, + int rowbytes, + int grey) +{ + unsigned char v,howmuch; + int xpos = 0, ypos = 0; + unsigned char *image; + unsigned char *temp, *buffer; + long rowstride, channels; + unsigned short rgb; + int i, j; + + if (bpp >= 16) /* color image */ + { + XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char)); + channels = 3; + } + else if (grey) /* grey image */ + { + XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char)); + channels = 1; + } + else /* indexed image */ + { + XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char)); + channels = 1; + } + + XMALLOCT (buffer, unsigned char*, rowbytes); + rowstride = width * channels; + + ypos = height - 1; /* Bitmaps begin in the lower left corner */ + + switch (bpp) { + + case 32: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + *(temp++)= buffer[xpos * 4 + 2]; + *(temp++)= buffer[xpos * 4 + 1]; + *(temp++)= buffer[xpos * 4]; + } + --ypos; /* next line */ + } + } + break; + + case 24: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + *(temp++)= buffer[xpos * 3 + 2]; + *(temp++)= buffer[xpos * 3 + 1]; + *(temp++)= buffer[xpos * 3]; + } + --ypos; /* next line */ + } + } + break; + + case 16: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + rgb= ToS(&buffer[xpos * 2]); + *(temp++)= (unsigned char)(((rgb >> 10) & 0x1f) * 8); + *(temp++)= (unsigned char)(((rgb >> 5) & 0x1f) * 8); + *(temp++)= (unsigned char)(((rgb) & 0x1f) * 8); + } + --ypos; /* next line */ + } + } + break; + + case 8: + case 4: + case 1: + { + if (compression == 0) + { + while (ReadOK (fd, &v, 1)) + { + for (i = 1; (i <= (8 / bpp)) && (xpos < width); i++, xpos++) + { + temp = (unsigned char*) (image + (ypos * rowstride) + (xpos * channels)); + *temp= (unsigned char)(( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp))); + } + if (xpos == width) + { + (void) ReadOK (fd, buffer, rowbytes - 1 - + (width * bpp - 1) / 8); + ypos--; + xpos = 0; + + } + if (ypos < 0) + break; + } + break; + } + else + { + while (ypos >= 0 && xpos <= width) + { + (void) ReadOK (fd, buffer, 2); + if ((unsigned char) buffer[0] != 0) + /* Count + Color - record */ + { + for (j = 0; ((unsigned char) j < (unsigned char) buffer[0]) && (xpos < width);) + { +#ifdef DEBUG2 + printf("%u %u | ",xpos,width); +#endif + for (i = 1; + ((i <= (8 / bpp)) && + (xpos < width) && + ((unsigned char) j < (unsigned char) buffer[0])); + i++, xpos++, j++) + { + temp = image + (ypos * rowstride) + (xpos * channels); + *temp = (unsigned char) ((buffer[1] & (((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp))); + } + } + } + if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1] > 2)) + /* uncompressed record */ + { + howmuch = buffer[1]; + for (j = 0; j < howmuch; j += (8 / bpp)) + { + (void) ReadOK (fd, &v, 1); + i = 1; + while ((i <= (8 / bpp)) && (xpos < width)) + { + temp = image + (ypos * rowstride) + (xpos * channels); + *temp = (unsigned char) ((v & (((1<<bpp)-1) << (8-(i*bpp)))) >> (8-(i*bpp))); + i++; + xpos++; + } + } + + if ((howmuch % 2) && (bpp==4)) + howmuch++; + + if ((howmuch / (8 / bpp)) % 2) + (void) ReadOK (fd, &v, 1); + /*if odd(x div (8 div bpp )) then blockread(f,z^,1);*/ + } + if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1]==0)) + /* Line end */ + { + ypos--; + xpos = 0; + } + if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==1)) + /* Bitmap end */ + { + break; + } + if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==2)) + /* Deltarecord */ + { + (void) ReadOK (fd, buffer, 2); + xpos += (unsigned char) buffer[0]; + ypos -= (unsigned char) buffer[1]; + } + } + break; + } + } + break; + default: + /* This is very bad, we should not be here */ + ; + } + + /* fclose (fd); */ + if (bpp <= 8) + { + unsigned char *temp2, *temp3; + unsigned char index; + temp2 = temp = image; + XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char)); + temp3 = image; + for (ypos = 0; ypos < height; ypos++) + { + for (xpos = 0; xpos < width; xpos++) + { + index = *temp2++; + *temp3++ = cmap[index][0]; + if (!grey) + { + *temp3++ = cmap[index][1]; + *temp3++ = cmap[index][2]; + } + } + } + XFREE (temp); + } + + XFREE (buffer); + return image; +} + +#if 0 /**** pts ****/ +FILE *errorfile; +char *prog_name = "bmp"; +char *filename; +int interactive_bmp; +#endif + +static long +ToL (unsigned char *puffer) +{ + return (puffer[0] | puffer[1]<<8 | puffer[2]<<16 | puffer[3]<<24); +} + +static short +ToS (unsigned char *puffer) +{ + return ((short)(puffer[0] | puffer[1]<<8)); +} |