Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Windows BMP file functions for OpenGL.
- *
- * Written by Michael Sweet.
- */
- #include "bitmap.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #ifdef WIN32
- /*
- * 'LoadDIBitmap()' - Load a DIB/BMP file from disk.
- *
- * Returns a pointer to the bitmap if successful, NULL otherwise...
- */
- GLubyte * /* O - Bitmap data */
- LoadDIBitmap(const char *filename, /* I - File to load */
- BITMAPINFO **info) /* O - Bitmap information */
- {
- FILE *fp; /* Open file pointer */
- GLubyte *bits; /* Bitmap pixel bits */
- int bitsize; /* Size of bitmap */
- int infosize; /* Size of header information */
- BITMAPFILEHEADER header; /* File header */
- /* Try opening the file; use "rb" mode to read this *binary* file. */
- if ((fp = fopen(filename, "rb")) == NULL)
- return (NULL);
- /* Read the file header and any following bitmap information... */
- if (fread(&header, sizeof(BITMAPFILEHEADER), 1, fp) < 1)
- {
- /* Couldn't read the file header - return NULL... */
- fclose(fp);
- return (NULL);
- }
- if (header.bfType != 'MB') /* Check for BM reversed... */
- {
- /* Not a bitmap file - return NULL... */
- fclose(fp);
- return (NULL);
- }
- infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER);
- if ((*info = (BITMAPINFO *)malloc(infosize)) == NULL)
- {
- /* Couldn't allocate memory for bitmap info - return NULL... */
- fclose(fp);
- return (NULL);
- }
- if (fread(*info, 1, infosize, fp) < infosize)
- {
- /* Couldn't read the bitmap header - return NULL... */
- free(*info);
- fclose(fp);
- return (NULL);
- }
- /* Now that we have all the header info read in, allocate memory for *
- * the bitmap and read *it* in... */
- if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
- bitsize = ((*info)->bmiHeader.biWidth *
- (*info)->bmiHeader.biBitCount + 7) / 8 *
- abs((*info)->bmiHeader.biHeight);
- if ((bits = malloc(bitsize)) == NULL)
- {
- /* Couldn't allocate memory - return NULL! */
- free(*info);
- fclose(fp);
- return (NULL);
- }
- if (fread(bits, 1, bitsize, fp) < bitsize)
- {
- /* Couldn't read bitmap - free memory and return NULL! */
- free(*info);
- free(bits);
- fclose(fp);
- return (NULL);
- }
- /* OK, everything went fine - return the allocated bitmap... */
- fclose(fp);
- return (bits);
- }
- /*
- * 'SaveDIBitmap()' - Save a DIB/BMP file to disk.
- *
- * Returns 0 on success or -1 on failure...
- */
- int /* O - 0 = success, -1 = failure */
- SaveDIBitmap(const char *filename, /* I - File to load */
- BITMAPINFO *info, /* I - Bitmap information */
- GLubyte *bits) /* I - Bitmap data */
- {
- FILE *fp; /* Open file pointer */
- int size, /* Size of file */
- infosize, /* Size of bitmap info */
- bitsize; /* Size of bitmap pixels */
- BITMAPFILEHEADER header; /* File header */
- /* Try opening the file; use "wb" mode to write this *binary* file. */
- if ((fp = fopen(filename, "wb")) == NULL)
- return (-1);
- /* Figure out the bitmap size */
- if (info->bmiHeader.biSizeImage == 0)
- bitsize = (info->bmiHeader.biWidth *
- info->bmiHeader.biBitCount + 7) / 8 *
- abs(info->bmiHeader.biHeight);
- else
- bitsize = info->bmiHeader.biSizeImage;
- /* Figure out the header size */
- infosize = sizeof(BITMAPINFOHEADER);
- switch (info->bmiHeader.biCompression)
- {
- case BI_BITFIELDS :
- infosize += 12; /* Add 3 RGB doubleword masks */
- if (info->bmiHeader.biClrUsed == 0)
- break;
- case BI_RGB :
- if (info->bmiHeader.biBitCount > 8 &&
- info->bmiHeader.biClrUsed == 0)
- break;
- case BI_RLE8 :
- case BI_RLE4 :
- if (info->bmiHeader.biClrUsed == 0)
- infosize += (1 << info->bmiHeader.biBitCount) * 4;
- else
- infosize += info->bmiHeader.biClrUsed * 4;
- break;
- }
- size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;
- /* Write the file header, bitmap information, and bitmap pixel data... */
- header.bfType = 'MB'; /* Non-portable... sigh */
- header.bfSize = size;
- header.bfReserved1 = 0;
- header.bfReserved2 = 0;
- header.bfOffBits = sizeof(BITMAPFILEHEADER) + infosize;
- if (fwrite(&header, 1, sizeof(BITMAPFILEHEADER), fp) < sizeof(BITMAPFILEHEADER))
- {
- /* Couldn't write the file header - return... */
- fclose(fp);
- return (-1);
- }
- if (fwrite(info, 1, infosize, fp) < infosize)
- {
- /* Couldn't write the bitmap header - return... */
- fclose(fp);
- return (-1);
- }
- if (fwrite(bits, 1, bitsize, fp) < bitsize)
- {
- /* Couldn't write the bitmap - return... */
- fclose(fp);
- return (-1);
- }
- /* OK, everything went fine - return... */
- fclose(fp);
- return (0);
- }
- #else /* !WIN32 */
- /*
- * Functions for reading and writing 16- and 32-bit little-endian integers.
- */
- static unsigned short read_word(FILE *fp);
- static unsigned int read_dword(FILE *fp);
- static int read_long(FILE *fp);
- static int write_word(FILE *fp, unsigned short w);
- static int write_dword(FILE *fp, unsigned int dw);
- static int write_long(FILE *fp, int l);
- /*
- * 'LoadDIBitmap()' - Load a DIB/BMP file from disk.
- *
- * Returns a pointer to the bitmap if successful, NULL otherwise...
- */
- GLubyte * /* O - Bitmap data */
- LoadDIBitmap(const char *filename, /* I - File to load */
- BITMAPINFO **info) /* O - Bitmap information */
- {
- FILE *fp; /* Open file pointer */
- GLubyte *bits; /* Bitmap pixel bits */
- GLubyte *ptr; /* Pointer into bitmap */
- GLubyte temp; /* Temporary variable to swap red and blue */
- int x, y; /* X and Y position in image */
- int length; /* Line length */
- int bitsize; /* Size of bitmap */
- int infosize; /* Size of header information */
- BITMAPFILEHEADER header; /* File header */
- /* Try opening the file; use "rb" mode to read this *binary* file. */
- if ((fp = fopen(filename, "rb")) == NULL)
- return (NULL);
- /* Read the file header and any following bitmap information... */
- header.bfType = read_word(fp);
- header.bfSize = read_dword(fp);
- header.bfReserved1 = read_word(fp);
- header.bfReserved2 = read_word(fp);
- header.bfOffBits = read_dword(fp);
- if (header.bfType != BF_TYPE) /* Check for BM reversed... */
- {
- /* Not a bitmap file - return NULL... */
- fclose(fp);
- return (NULL);
- }
- infosize = header.bfOffBits - 18;
- if ((*info = (BITMAPINFO *)malloc(sizeof(BITMAPINFO))) == NULL)
- {
- /* Couldn't allocate memory for bitmap info - return NULL... */
- fclose(fp);
- return (NULL);
- }
- (*info)->bmiHeader.biSize = read_dword(fp);
- (*info)->bmiHeader.biWidth = read_long(fp);
- (*info)->bmiHeader.biHeight = read_long(fp);
- (*info)->bmiHeader.biPlanes = read_word(fp);
- (*info)->bmiHeader.biBitCount = read_word(fp);
- (*info)->bmiHeader.biCompression = read_dword(fp);
- (*info)->bmiHeader.biSizeImage = read_dword(fp);
- (*info)->bmiHeader.biXPelsPerMeter = read_long(fp);
- (*info)->bmiHeader.biYPelsPerMeter = read_long(fp);
- (*info)->bmiHeader.biClrUsed = read_dword(fp);
- (*info)->bmiHeader.biClrImportant = read_dword(fp);
- if (infosize > 40)
- if (fread((*info)->bmiColors, infosize - 40, 1, fp) < 1)
- {
- /* Couldn't read the bitmap header - return NULL... */
- free(*info);
- fclose(fp);
- return (NULL);
- }
- /* Now that we have all the header info read in, allocate memory for *
- * the bitmap and read *it* in... */
- if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
- bitsize = ((*info)->bmiHeader.biWidth *
- (*info)->bmiHeader.biBitCount + 7) / 8 *
- abs((*info)->bmiHeader.biHeight);
- if ((bits = malloc(bitsize)) == NULL)
- {
- /* Couldn't allocate memory - return NULL! */
- free(*info);
- fclose(fp);
- return (NULL);
- }
- if (fread(bits, 1, bitsize, fp) < bitsize)
- {
- /* Couldn't read bitmap - free memory and return NULL! */
- free(*info);
- free(bits);
- fclose(fp);
- return (NULL);
- }
- /* Swap red and blue */
- length = ((*info)->bmiHeader.biWidth * 3 + 3) & ~3;
- for (y = 0; y < (*info)->bmiHeader.biHeight; y ++)
- for (ptr = bits + y * length, x = (*info)->bmiHeader.biWidth;
- x > 0;
- x --, ptr += 3)
- {
- temp = ptr[0];
- ptr[0] = ptr[2];
- ptr[2] = temp;
- }
- /* OK, everything went fine - return the allocated bitmap... */
- fclose(fp);
- return (bits);
- }
- /*
- * 'SaveDIBitmap()' - Save a DIB/BMP file to disk.
- *
- * Returns 0 on success or -1 on failure...
- */
- int /* O - 0 = success, -1 = failure */
- SaveDIBitmap(const char *filename, /* I - File to load */
- BITMAPINFO *info, /* I - Bitmap information */
- GLubyte *bits) /* I - Bitmap data */
- {
- FILE *fp; /* Open file pointer */
- int size, /* Size of file */
- infosize, /* Size of bitmap info */
- bitsize; /* Size of bitmap pixels */
- /* Try opening the file; use "wb" mode to write this *binary* file. */
- if ((fp = fopen(filename, "wb")) == NULL)
- return (-1);
- /* Figure out the bitmap size */
- if (info->bmiHeader.biSizeImage == 0)
- bitsize = (info->bmiHeader.biWidth *
- info->bmiHeader.biBitCount + 7) / 8 *
- abs(info->bmiHeader.biHeight);
- else
- bitsize = info->bmiHeader.biSizeImage;
- /* Figure out the header size */
- infosize = sizeof(BITMAPINFOHEADER);
- switch (info->bmiHeader.biCompression)
- {
- case BI_BITFIELDS :
- infosize += 12; /* Add 3 RGB doubleword masks */
- if (info->bmiHeader.biClrUsed == 0)
- break;
- case BI_RGB :
- if (info->bmiHeader.biBitCount > 8 &&
- info->bmiHeader.biClrUsed == 0)
- break;
- case BI_RLE8 :
- case BI_RLE4 :
- if (info->bmiHeader.biClrUsed == 0)
- infosize += (1 << info->bmiHeader.biBitCount) * 4;
- else
- infosize += info->bmiHeader.biClrUsed * 4;
- break;
- }
- size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;
- /* Write the file header, bitmap information, and bitmap pixel data... */
- write_word(fp, BF_TYPE); /* bfType */
- write_dword(fp, size); /* bfSize */
- write_word(fp, 0); /* bfReserved1 */
- write_word(fp, 0); /* bfReserved2 */
- write_dword(fp, 18 + infosize); /* bfOffBits */
- write_dword(fp, info->bmiHeader.biSize);
- write_long(fp, info->bmiHeader.biWidth);
- write_long(fp, info->bmiHeader.biHeight);
- write_word(fp, info->bmiHeader.biPlanes);
- write_word(fp, info->bmiHeader.biBitCount);
- write_dword(fp, info->bmiHeader.biCompression);
- write_dword(fp, info->bmiHeader.biSizeImage);
- write_long(fp, info->bmiHeader.biXPelsPerMeter);
- write_long(fp, info->bmiHeader.biYPelsPerMeter);
- write_dword(fp, info->bmiHeader.biClrUsed);
- write_dword(fp, info->bmiHeader.biClrImportant);
- if (infosize > 40)
- if (fwrite(info->bmiColors, infosize - 40, 1, fp) < 1)
- {
- /* Couldn't write the bitmap header - return... */
- fclose(fp);
- return (-1);
- }
- if (fwrite(bits, 1, bitsize, fp) < bitsize)
- {
- /* Couldn't write the bitmap - return... */
- fclose(fp);
- return (-1);
- }
- /* OK, everything went fine - return... */
- fclose(fp);
- return (0);
- }
- /*
- * 'read_word()' - Read a 16-bit unsigned integer.
- */
- static unsigned short /* O - 16-bit unsigned integer */
- read_word(FILE *fp) /* I - File to read from */
- {
- unsigned char b0, b1; /* Bytes from file */
- b0 = getc(fp);
- b1 = getc(fp);
- return ((b1 << 8) | b0);
- }
- /*
- * 'read_dword()' - Read a 32-bit unsigned integer.
- */
- static unsigned int /* O - 32-bit unsigned integer */
- read_dword(FILE *fp) /* I - File to read from */
- {
- unsigned char b0, b1, b2, b3; /* Bytes from file */
- b0 = getc(fp);
- b1 = getc(fp);
- b2 = getc(fp);
- b3 = getc(fp);
- return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
- }
- /*
- * 'read_long()' - Read a 32-bit signed integer.
- */
- static int /* O - 32-bit signed integer */
- read_long(FILE *fp) /* I - File to read from */
- {
- unsigned char b0, b1, b2, b3; /* Bytes from file */
- b0 = getc(fp);
- b1 = getc(fp);
- b2 = getc(fp);
- b3 = getc(fp);
- return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
- }
- /*
- * 'write_word()' - Write a 16-bit unsigned integer.
- */
- static int /* O - 0 on success, -1 on error */
- write_word(FILE *fp, /* I - File to write to */
- unsigned short w) /* I - Integer to write */
- {
- putc(w, fp);
- return (putc(w >> 8, fp));
- }
- /*
- * 'write_dword()' - Write a 32-bit unsigned integer.
- */
- static int /* O - 0 on success, -1 on error */
- write_dword(FILE *fp, /* I - File to write to */
- unsigned int dw) /* I - Integer to write */
- {
- putc(dw, fp);
- putc(dw >> 8, fp);
- putc(dw >> 16, fp);
- return (putc(dw >> 24, fp));
- }
- /*
- * 'write_long()' - Write a 32-bit signed integer.
- */
- static int /* O - 0 on success, -1 on error */
- write_long(FILE *fp, /* I - File to write to */
- int l) /* I - Integer to write */
- {
- putc(l, fp);
- putc(l >> 8, fp);
- putc(l >> 16, fp);
- return (putc(l >> 24, fp));
- }
- #endif /* WIN32 */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement