Advertisement
4da

BMP read [c]

4da
Aug 15th, 2011
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.75 KB | None | 0 0
  1. /*
  2.  * Windows BMP file functions for OpenGL.
  3.  *
  4.  * Written by Michael Sweet.
  5.  */
  6.  
  7. #include "bitmap.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <errno.h>
  11.  
  12.  
  13. #ifdef WIN32
  14. /*
  15.  * 'LoadDIBitmap()' - Load a DIB/BMP file from disk.
  16.  *
  17.  * Returns a pointer to the bitmap if successful, NULL otherwise...
  18.  */
  19.  
  20. GLubyte *                          /* O - Bitmap data */
  21. LoadDIBitmap(const char *filename, /* I - File to load */
  22.              BITMAPINFO **info)    /* O - Bitmap information */
  23.     {
  24.     FILE             *fp;          /* Open file pointer */
  25.     GLubyte          *bits;        /* Bitmap pixel bits */
  26.     int              bitsize;      /* Size of bitmap */
  27.     int              infosize;     /* Size of header information */
  28.     BITMAPFILEHEADER header;       /* File header */
  29.  
  30.  
  31.     /* Try opening the file; use "rb" mode to read this *binary* file. */
  32.     if ((fp = fopen(filename, "rb")) == NULL)
  33.         return (NULL);
  34.  
  35.     /* Read the file header and any following bitmap information... */
  36.     if (fread(&header, sizeof(BITMAPFILEHEADER), 1, fp) < 1)
  37.         {
  38.         /* Couldn't read the file header - return NULL... */
  39.     fclose(fp);
  40.         return (NULL);
  41.         }
  42.  
  43.     if (header.bfType != 'MB')  /* Check for BM reversed... */
  44.         {
  45.         /* Not a bitmap file - return NULL... */
  46.         fclose(fp);
  47.         return (NULL);
  48.         }
  49.  
  50.     infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER);
  51.     if ((*info = (BITMAPINFO *)malloc(infosize)) == NULL)
  52.         {
  53.         /* Couldn't allocate memory for bitmap info - return NULL... */
  54.         fclose(fp);
  55.         return (NULL);
  56.         }
  57.  
  58.     if (fread(*info, 1, infosize, fp) < infosize)
  59.         {
  60.         /* Couldn't read the bitmap header - return NULL... */
  61.         free(*info);
  62.         fclose(fp);
  63.         return (NULL);
  64.         }
  65.  
  66.     /* Now that we have all the header info read in, allocate memory for *
  67.      * the bitmap and read *it* in...                                    */
  68.     if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
  69.         bitsize = ((*info)->bmiHeader.biWidth *
  70.                    (*info)->bmiHeader.biBitCount + 7) / 8 *
  71.                abs((*info)->bmiHeader.biHeight);
  72.  
  73.     if ((bits = malloc(bitsize)) == NULL)
  74.         {
  75.         /* Couldn't allocate memory - return NULL! */
  76.         free(*info);
  77.         fclose(fp);
  78.         return (NULL);
  79.         }
  80.  
  81.     if (fread(bits, 1, bitsize, fp) < bitsize)
  82.         {
  83.         /* Couldn't read bitmap - free memory and return NULL! */
  84.         free(*info);
  85.         free(bits);
  86.         fclose(fp);
  87.         return (NULL);
  88.         }
  89.  
  90.     /* OK, everything went fine - return the allocated bitmap... */
  91.     fclose(fp);
  92.     return (bits);
  93.     }
  94.  
  95.  
  96. /*
  97.  * 'SaveDIBitmap()' - Save a DIB/BMP file to disk.
  98.  *
  99.  * Returns 0 on success or -1 on failure...
  100.  */
  101.  
  102. int                                /* O - 0 = success, -1 = failure */
  103. SaveDIBitmap(const char *filename, /* I - File to load */
  104.              BITMAPINFO *info,     /* I - Bitmap information */
  105.          GLubyte    *bits)     /* I - Bitmap data */
  106.     {
  107.     FILE             *fp;          /* Open file pointer */
  108.     int              size,         /* Size of file */
  109.                      infosize,     /* Size of bitmap info */
  110.                      bitsize;      /* Size of bitmap pixels */
  111.     BITMAPFILEHEADER header;       /* File header */
  112.  
  113.  
  114.     /* Try opening the file; use "wb" mode to write this *binary* file. */
  115.     if ((fp = fopen(filename, "wb")) == NULL)
  116.         return (-1);
  117.  
  118.     /* Figure out the bitmap size */
  119.     if (info->bmiHeader.biSizeImage == 0)
  120.     bitsize = (info->bmiHeader.biWidth *
  121.                info->bmiHeader.biBitCount + 7) / 8 *
  122.           abs(info->bmiHeader.biHeight);
  123.     else
  124.     bitsize = info->bmiHeader.biSizeImage;
  125.  
  126.     /* Figure out the header size */
  127.     infosize = sizeof(BITMAPINFOHEADER);
  128.     switch (info->bmiHeader.biCompression)
  129.     {
  130.     case BI_BITFIELDS :
  131.             infosize += 12; /* Add 3 RGB doubleword masks */
  132.             if (info->bmiHeader.biClrUsed == 0)
  133.           break;
  134.     case BI_RGB :
  135.             if (info->bmiHeader.biBitCount > 8 &&
  136.             info->bmiHeader.biClrUsed == 0)
  137.           break;
  138.     case BI_RLE8 :
  139.     case BI_RLE4 :
  140.             if (info->bmiHeader.biClrUsed == 0)
  141.               infosize += (1 << info->bmiHeader.biBitCount) * 4;
  142.         else
  143.               infosize += info->bmiHeader.biClrUsed * 4;
  144.         break;
  145.     }
  146.  
  147.     size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;
  148.  
  149.     /* Write the file header, bitmap information, and bitmap pixel data... */
  150.     header.bfType      = 'MB'; /* Non-portable... sigh */
  151.     header.bfSize      = size;
  152.     header.bfReserved1 = 0;
  153.     header.bfReserved2 = 0;
  154.     header.bfOffBits   = sizeof(BITMAPFILEHEADER) + infosize;
  155.  
  156.     if (fwrite(&header, 1, sizeof(BITMAPFILEHEADER), fp) < sizeof(BITMAPFILEHEADER))
  157.         {
  158.         /* Couldn't write the file header - return... */
  159.         fclose(fp);
  160.         return (-1);
  161.         }
  162.  
  163.     if (fwrite(info, 1, infosize, fp) < infosize)
  164.         {
  165.         /* Couldn't write the bitmap header - return... */
  166.         fclose(fp);
  167.         return (-1);
  168.         }
  169.  
  170.     if (fwrite(bits, 1, bitsize, fp) < bitsize)
  171.         {
  172.         /* Couldn't write the bitmap - return... */
  173.         fclose(fp);
  174.         return (-1);
  175.         }
  176.  
  177.     /* OK, everything went fine - return... */
  178.     fclose(fp);
  179.     return (0);
  180.     }
  181.  
  182.  
  183. #else /* !WIN32 */
  184. /*
  185.  * Functions for reading and writing 16- and 32-bit little-endian integers.
  186.  */
  187.  
  188. static unsigned short read_word(FILE *fp);
  189. static unsigned int   read_dword(FILE *fp);
  190. static int            read_long(FILE *fp);
  191.  
  192. static int            write_word(FILE *fp, unsigned short w);
  193. static int            write_dword(FILE *fp, unsigned int dw);
  194. static int            write_long(FILE *fp, int l);
  195.  
  196.  
  197. /*
  198.  * 'LoadDIBitmap()' - Load a DIB/BMP file from disk.
  199.  *
  200.  * Returns a pointer to the bitmap if successful, NULL otherwise...
  201.  */
  202.  
  203. GLubyte *                          /* O - Bitmap data */
  204. LoadDIBitmap(const char *filename, /* I - File to load */
  205.              BITMAPINFO **info)    /* O - Bitmap information */
  206.     {
  207.     FILE             *fp;          /* Open file pointer */
  208.     GLubyte          *bits;        /* Bitmap pixel bits */
  209.     GLubyte          *ptr;         /* Pointer into bitmap */
  210.     GLubyte          temp;         /* Temporary variable to swap red and blue */
  211.     int              x, y;         /* X and Y position in image */
  212.     int              length;       /* Line length */
  213.     int              bitsize;      /* Size of bitmap */
  214.     int              infosize;     /* Size of header information */
  215.     BITMAPFILEHEADER header;       /* File header */
  216.  
  217.  
  218.     /* Try opening the file; use "rb" mode to read this *binary* file. */
  219.     if ((fp = fopen(filename, "rb")) == NULL)
  220.         return (NULL);
  221.  
  222.     /* Read the file header and any following bitmap information... */
  223.     header.bfType      = read_word(fp);
  224.     header.bfSize      = read_dword(fp);
  225.     header.bfReserved1 = read_word(fp);
  226.     header.bfReserved2 = read_word(fp);
  227.     header.bfOffBits   = read_dword(fp);
  228.  
  229.     if (header.bfType != BF_TYPE) /* Check for BM reversed... */
  230.         {
  231.         /* Not a bitmap file - return NULL... */
  232.         fclose(fp);
  233.         return (NULL);
  234.         }
  235.  
  236.     infosize = header.bfOffBits - 18;
  237.     if ((*info = (BITMAPINFO *)malloc(sizeof(BITMAPINFO))) == NULL)
  238.         {
  239.         /* Couldn't allocate memory for bitmap info - return NULL... */
  240.         fclose(fp);
  241.         return (NULL);
  242.         }
  243.  
  244.     (*info)->bmiHeader.biSize          = read_dword(fp);
  245.     (*info)->bmiHeader.biWidth         = read_long(fp);
  246.     (*info)->bmiHeader.biHeight        = read_long(fp);
  247.     (*info)->bmiHeader.biPlanes        = read_word(fp);
  248.     (*info)->bmiHeader.biBitCount      = read_word(fp);
  249.     (*info)->bmiHeader.biCompression   = read_dword(fp);
  250.     (*info)->bmiHeader.biSizeImage     = read_dword(fp);
  251.     (*info)->bmiHeader.biXPelsPerMeter = read_long(fp);
  252.     (*info)->bmiHeader.biYPelsPerMeter = read_long(fp);
  253.     (*info)->bmiHeader.biClrUsed       = read_dword(fp);
  254.     (*info)->bmiHeader.biClrImportant  = read_dword(fp);
  255.  
  256.     if (infosize > 40)
  257.     if (fread((*info)->bmiColors, infosize - 40, 1, fp) < 1)
  258.             {
  259.             /* Couldn't read the bitmap header - return NULL... */
  260.             free(*info);
  261.             fclose(fp);
  262.             return (NULL);
  263.             }
  264.  
  265.     /* Now that we have all the header info read in, allocate memory for *
  266.      * the bitmap and read *it* in...                                    */
  267.     if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
  268.         bitsize = ((*info)->bmiHeader.biWidth *
  269.                    (*info)->bmiHeader.biBitCount + 7) / 8 *
  270.                abs((*info)->bmiHeader.biHeight);
  271.  
  272.     if ((bits = malloc(bitsize)) == NULL)
  273.         {
  274.         /* Couldn't allocate memory - return NULL! */
  275.         free(*info);
  276.         fclose(fp);
  277.         return (NULL);
  278.         }
  279.  
  280.     if (fread(bits, 1, bitsize, fp) < bitsize)
  281.         {
  282.         /* Couldn't read bitmap - free memory and return NULL! */
  283.         free(*info);
  284.         free(bits);
  285.         fclose(fp);
  286.         return (NULL);
  287.         }
  288.  
  289.     /* Swap red and blue */
  290.     length = ((*info)->bmiHeader.biWidth * 3 + 3) & ~3;
  291.     for (y = 0; y < (*info)->bmiHeader.biHeight; y ++)
  292.         for (ptr = bits + y * length, x = (*info)->bmiHeader.biWidth;
  293.              x > 0;
  294.          x --, ptr += 3)
  295.         {
  296.         temp   = ptr[0];
  297.         ptr[0] = ptr[2];
  298.         ptr[2] = temp;
  299.         }
  300.  
  301.     /* OK, everything went fine - return the allocated bitmap... */
  302.     fclose(fp);
  303.     return (bits);
  304.     }
  305.  
  306.  
  307. /*
  308.  * 'SaveDIBitmap()' - Save a DIB/BMP file to disk.
  309.  *
  310.  * Returns 0 on success or -1 on failure...
  311.  */
  312.  
  313. int                                /* O - 0 = success, -1 = failure */
  314. SaveDIBitmap(const char *filename, /* I - File to load */
  315.              BITMAPINFO *info,     /* I - Bitmap information */
  316.          GLubyte    *bits)     /* I - Bitmap data */
  317.     {
  318.     FILE *fp;                      /* Open file pointer */
  319.     int  size,                     /* Size of file */
  320.          infosize,                 /* Size of bitmap info */
  321.          bitsize;                  /* Size of bitmap pixels */
  322.  
  323.  
  324.     /* Try opening the file; use "wb" mode to write this *binary* file. */
  325.     if ((fp = fopen(filename, "wb")) == NULL)
  326.         return (-1);
  327.  
  328.     /* Figure out the bitmap size */
  329.     if (info->bmiHeader.biSizeImage == 0)
  330.     bitsize = (info->bmiHeader.biWidth *
  331.                info->bmiHeader.biBitCount + 7) / 8 *
  332.           abs(info->bmiHeader.biHeight);
  333.     else
  334.     bitsize = info->bmiHeader.biSizeImage;
  335.  
  336.     /* Figure out the header size */
  337.     infosize = sizeof(BITMAPINFOHEADER);
  338.     switch (info->bmiHeader.biCompression)
  339.     {
  340.     case BI_BITFIELDS :
  341.             infosize += 12; /* Add 3 RGB doubleword masks */
  342.             if (info->bmiHeader.biClrUsed == 0)
  343.           break;
  344.     case BI_RGB :
  345.             if (info->bmiHeader.biBitCount > 8 &&
  346.             info->bmiHeader.biClrUsed == 0)
  347.           break;
  348.     case BI_RLE8 :
  349.     case BI_RLE4 :
  350.             if (info->bmiHeader.biClrUsed == 0)
  351.               infosize += (1 << info->bmiHeader.biBitCount) * 4;
  352.         else
  353.               infosize += info->bmiHeader.biClrUsed * 4;
  354.         break;
  355.     }
  356.  
  357.     size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;
  358.  
  359.     /* Write the file header, bitmap information, and bitmap pixel data... */
  360.     write_word(fp, BF_TYPE);        /* bfType */
  361.     write_dword(fp, size);          /* bfSize */
  362.     write_word(fp, 0);              /* bfReserved1 */
  363.     write_word(fp, 0);              /* bfReserved2 */
  364.     write_dword(fp, 18 + infosize); /* bfOffBits */
  365.  
  366.     write_dword(fp, info->bmiHeader.biSize);
  367.     write_long(fp, info->bmiHeader.biWidth);
  368.     write_long(fp, info->bmiHeader.biHeight);
  369.     write_word(fp, info->bmiHeader.biPlanes);
  370.     write_word(fp, info->bmiHeader.biBitCount);
  371.     write_dword(fp, info->bmiHeader.biCompression);
  372.     write_dword(fp, info->bmiHeader.biSizeImage);
  373.     write_long(fp, info->bmiHeader.biXPelsPerMeter);
  374.     write_long(fp, info->bmiHeader.biYPelsPerMeter);
  375.     write_dword(fp, info->bmiHeader.biClrUsed);
  376.     write_dword(fp, info->bmiHeader.biClrImportant);
  377.  
  378.     if (infosize > 40)
  379.     if (fwrite(info->bmiColors, infosize - 40, 1, fp) < 1)
  380.             {
  381.             /* Couldn't write the bitmap header - return... */
  382.             fclose(fp);
  383.             return (-1);
  384.             }
  385.  
  386.     if (fwrite(bits, 1, bitsize, fp) < bitsize)
  387.         {
  388.         /* Couldn't write the bitmap - return... */
  389.         fclose(fp);
  390.         return (-1);
  391.         }
  392.  
  393.     /* OK, everything went fine - return... */
  394.     fclose(fp);
  395.     return (0);
  396.     }
  397.  
  398.  
  399. /*
  400.  * 'read_word()' - Read a 16-bit unsigned integer.
  401.  */
  402.  
  403. static unsigned short     /* O - 16-bit unsigned integer */
  404. read_word(FILE *fp)       /* I - File to read from */
  405.     {
  406.     unsigned char b0, b1; /* Bytes from file */
  407.  
  408.     b0 = getc(fp);
  409.     b1 = getc(fp);
  410.  
  411.     return ((b1 << 8) | b0);
  412.     }
  413.  
  414.  
  415. /*
  416.  * 'read_dword()' - Read a 32-bit unsigned integer.
  417.  */
  418.  
  419. static unsigned int               /* O - 32-bit unsigned integer */
  420. read_dword(FILE *fp)              /* I - File to read from */
  421.     {
  422.     unsigned char b0, b1, b2, b3; /* Bytes from file */
  423.  
  424.     b0 = getc(fp);
  425.     b1 = getc(fp);
  426.     b2 = getc(fp);
  427.     b3 = getc(fp);
  428.  
  429.     return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
  430.     }
  431.  
  432.  
  433. /*
  434.  * 'read_long()' - Read a 32-bit signed integer.
  435.  */
  436.  
  437. static int                        /* O - 32-bit signed integer */
  438. read_long(FILE *fp)               /* I - File to read from */
  439.     {
  440.     unsigned char b0, b1, b2, b3; /* Bytes from file */
  441.  
  442.     b0 = getc(fp);
  443.     b1 = getc(fp);
  444.     b2 = getc(fp);
  445.     b3 = getc(fp);
  446.  
  447.     return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
  448.     }
  449.  
  450.  
  451. /*
  452.  * 'write_word()' - Write a 16-bit unsigned integer.
  453.  */
  454.  
  455. static int                     /* O - 0 on success, -1 on error */
  456. write_word(FILE           *fp, /* I - File to write to */
  457.            unsigned short w)   /* I - Integer to write */
  458.     {
  459.     putc(w, fp);
  460.     return (putc(w >> 8, fp));
  461.     }
  462.  
  463.  
  464. /*
  465.  * 'write_dword()' - Write a 32-bit unsigned integer.
  466.  */
  467.  
  468. static int                    /* O - 0 on success, -1 on error */
  469. write_dword(FILE         *fp, /* I - File to write to */
  470.             unsigned int dw)  /* I - Integer to write */
  471.     {
  472.     putc(dw, fp);
  473.     putc(dw >> 8, fp);
  474.     putc(dw >> 16, fp);
  475.     return (putc(dw >> 24, fp));
  476.     }
  477.  
  478.  
  479. /*
  480.  * 'write_long()' - Write a 32-bit signed integer.
  481.  */
  482.  
  483. static int           /* O - 0 on success, -1 on error */
  484. write_long(FILE *fp, /* I - File to write to */
  485.            int  l)   /* I - Integer to write */
  486.     {
  487.     putc(l, fp);
  488.     putc(l >> 8, fp);
  489.     putc(l >> 16, fp);
  490.     return (putc(l >> 24, fp));
  491.     }
  492. #endif /* WIN32 */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement