Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //
  2. //      bmp.cpp - source file / freeware
  3. //
  4. //      David Henry - tfc_duke@hotmail.com
  5. //
  6.  
  7.  
  8. #include        "bmp.h"
  9. #include    <stdio.h>
  10.  
  11. #include    <libc/stubs.h>
  12.  
  13. extern "C"{
  14. long filelength(int fhandle);
  15. }
  16.  
  17. // --------------------------------------------------
  18. // LoadFileBMP() - load a Windows/OS2 BITMAP image
  19. //                                 [.bmp].
  20. //
  21. // parameters :
  22. //    - filename [in]  : image source file
  23. //    - pixels   [out] : 32 bits rgb image data
  24. //    - width    [out] : image width in pixels
  25. //    - height   [out] : image height in pixels
  26. //    - flipvert [in]  : flip vertically
  27. //
  28. // return value :
  29. //    - -1 : no image data
  30. //    -  0 : failure
  31. //    -  1 : success
  32. //
  33. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  34. // accepted image formats :
  35. //     # RGB 1-4-8-24-32 bits   WINDOWS - OS/2
  36. //     # RLE 4-8 bits                   WINDOWS
  37. // --------------------------------------------------
  38.  
  39. int LoadFileBMP( const char *filename, unsigned char **pixels, int *width, int *height, bool flipvert )
  40. {
  41.         FILE            *file;                  // file stream
  42.         BITMAPFILEHEADER        *bmfh;                  // bitmap file header
  43.         BITMAPINFOHEADER        *bmih;                  // bitmap info header (windows)
  44.         BITMAPCOREHEADER        *bmch;                  // bitmap core header (os/2)
  45.         RGBTRIPLE                       *os2_palette;   // pointer to the color palette os/2
  46.         RGBQUAD                         *win_palette;   // pointer to the color palette windows
  47.         char                            *buffer;                // buffer storing the entire file
  48.         unsigned char           *ptr;                   // pointer to pixels data
  49.         int                                     bitCount;               // number of bits per pixel
  50.         int                                     compression;    // compression type (rgb/rle)
  51.         int                                     row, col, i;    // temporary variables
  52.         int                                     w, h;                   // width, height
  53.  
  54.  
  55.  
  56.         /////////////////////////////////////////////////////
  57.         // read the entire file in the buffer
  58.  
  59.         file = fopen(filename,"rb");
  60.  
  61.         if( !file)
  62.                 return 0;
  63.  
  64.         long flen = filelength(fileno(file));
  65.  
  66.         buffer = new char[ flen + 1 ];
  67.         int rd = fread(buffer, flen, 1, file);
  68.         char *pBuff = buffer;
  69.  
  70.         fclose(file);
  71.  
  72.         /////////////////////////////////////////////////////
  73.        
  74.  
  75.         // read the header
  76.         bmfh = (BITMAPFILEHEADER *)pBuff;
  77.         pBuff += sizeof( BITMAPFILEHEADER );
  78.  
  79.         // verify that it's a BITMAP file
  80.         if( bmfh->bfType != BITMAP_ID )
  81.         {
  82.                 delete [] buffer;
  83.                 return 0;
  84.         }
  85.  
  86.  
  87.         bmch = (BITMAPCOREHEADER *)pBuff;
  88.         bmih = (BITMAPINFOHEADER *)pBuff;
  89.  
  90.  
  91.         if( (bmih->biCompression < 0) || (bmih->biCompression > 3) )
  92.         {
  93.                 // OS/2 style
  94.                 pBuff += sizeof( BITMAPCOREHEADER );
  95.  
  96.                 bitCount        = bmch->bcBitCount;
  97.                 compression     = BI_OS2;
  98.  
  99.                 w = bmch->bcWidth;
  100.                 h = bmch->bcHeight;
  101.         }
  102.         else
  103.         {
  104.                 // WINDOWS style
  105.                 pBuff += sizeof( BITMAPINFOHEADER );
  106.  
  107.                 bitCount        = bmih->biBitCount;
  108.                 compression     = bmih->biCompression;
  109.  
  110.                 w = bmih->biWidth;
  111.                 h = bmih->biHeight;
  112.         }
  113.  
  114.  
  115.         if( width )
  116.                 *width  = w;
  117.  
  118.         if( height )
  119.                 *height = h;
  120.  
  121.  
  122.         if( !pixels )
  123.         {
  124.                 delete [] buffer;
  125.                 return (-1);
  126.         }
  127.  
  128.  
  129.         /////////////////////////////////////////////////////
  130.         // read the palette
  131.  
  132.         if( bitCount <= 8 )
  133.         {
  134.                 // 24 and 32 bits images are not paletted
  135.  
  136.                 // ajust the palette pointer to the memory in the buffer
  137.                 os2_palette = (RGBTRIPLE *)pBuff;
  138.                 win_palette = (RGBQUAD *)pBuff;
  139.  
  140.                 //      [number of colors in the palette] * [size of one pixel]
  141.                 pBuff += (1 << bitCount) * (bitCount >> 3) * sizeof( unsigned char );
  142.         }
  143.  
  144.         /////////////////////////////////////////////////////
  145.  
  146.  
  147.         // allocate memory to store pixel data
  148.         *pixels = new unsigned char[ w * h * 3 ];
  149.         ptr             = &(*pixels)[0];
  150.  
  151.  
  152.         // move the pixel data pointer to the begening of bitmap data
  153.         pBuff = buffer + (bmfh->bfOffBits * sizeof( char ));
  154.  
  155.  
  156.         /////////////////////////////////////////////////////
  157.         // read pixel data following the image compression
  158.         // type and the number of bits per pixels
  159.         /////////////////////////////////////////////////////
  160.  
  161.         switch( compression )
  162.         {
  163.                 case BI_OS2:
  164.                 case BI_RGB:
  165.                 {
  166.                         for( row = h - 1; row >= 0; row-- )
  167.                         {
  168.                                 if( flipvert )
  169.                                         ptr = &(*pixels)[ row * w * 3 ];
  170.  
  171.                                 switch( bitCount )
  172.                                 {
  173.                                         case 1:
  174.                                         {
  175. // RGB 1 BITS
  176.                                                 for( col = 0; col < (int)(w / 8); col++ )
  177.                                                 {
  178.                                                         // read the current pixel
  179.                                                         unsigned char color = *((unsigned char *)(pBuff++));
  180.  
  181.                                                         for( i = 7; i >= 0; i--, ptr += 3 )
  182.                                                         {
  183.                                                                 // convert indexed pixel (1 bit) into rgb (32 bits) pixel
  184.                                                                 int clrIdx = ((color & (1<<i)) > 0);
  185.  
  186.                                                                 if( compression == BI_OS2 )
  187.                                                                 {
  188.                                                                         ptr[2] = os2_palette[ clrIdx ].rgbtRed;
  189.                                                                         ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
  190.                                                                         ptr[0] = os2_palette[ clrIdx ].rgbtBlue;                                                                       
  191.                                                                 }
  192.                                                                 else
  193.                                                                 {
  194.                                                                         ptr[2] = win_palette[ clrIdx ].rgbRed;
  195.                                                                         ptr[1] = win_palette[ clrIdx ].rgbGreen;
  196.                                                                         ptr[0] = win_palette[ clrIdx ].rgbBlue;
  197.                                                                 }
  198.                                                         }
  199.                                                 }
  200.  
  201.                                                 break;
  202.                                         }
  203.  
  204.                                         case 4:
  205.                                         {
  206. // RGB 4 BITS
  207.                                                 for( col = 0; col < (int)(w / 2); col++, ptr += 6 )
  208.                                                 {
  209.                                                         // read the current pixel
  210.                                                         unsigned char color = *((unsigned char *)(pBuff++));
  211.  
  212.                                                         // convert indexed pixel (4 bits) into rgb (32 bits) pixel
  213.                                                         int clrIdx;
  214.  
  215.                                                         if( compression == BI_OS2 )
  216.                                                         {
  217.                                                                 clrIdx = (color >> 4);
  218.                                                                 ptr[2] = os2_palette[ clrIdx ].rgbtRed;
  219.                                                                 ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
  220.                                                                 ptr[0] = os2_palette[ clrIdx ].rgbtBlue;
  221.  
  222.                                                                 clrIdx = (color & 0x0F);
  223.                                                                 ptr[6] = os2_palette[ clrIdx ].rgbtRed;
  224.                                                                 ptr[5] = os2_palette[ clrIdx ].rgbtGreen;
  225.                                                                 ptr[4] = os2_palette[ clrIdx ].rgbtBlue;
  226.  
  227.                                                         }
  228.                                                         else
  229.                                                         {
  230.                                                                 clrIdx = (color >> 4);
  231.                                                                 ptr[2] = win_palette[ clrIdx ].rgbRed;
  232.                                                                 ptr[1] = win_palette[ clrIdx ].rgbGreen;
  233.                                                                 ptr[0] = win_palette[ clrIdx ].rgbBlue;
  234.  
  235.                                                                 clrIdx = (color & 0x0F);
  236.                                                                 ptr[6] = win_palette[ clrIdx ].rgbRed;
  237.                                                                 ptr[5] = win_palette[ clrIdx ].rgbGreen;
  238.                                                                 ptr[4] = win_palette[ clrIdx ].rgbBlue;
  239.                                                         }
  240.                                                 }
  241.  
  242.                                                 break;
  243.                                         }
  244.  
  245.                                         case 8:
  246.                                         {
  247. // RGB 8 BITS
  248.                                                 for( col = 0; col < w; col++, ptr += 3 )
  249.                                                 {
  250.                                                         // read the current pixel
  251.                                                         unsigned char color = *((unsigned char *)(pBuff++));
  252.  
  253.                                                         // convert indexed pixel (8 bits) into rgb (32 bits) pixel
  254.                                                         if( compression == BI_OS2 )
  255.                                                         {
  256.                                                                 ptr[2] = os2_palette[ color ].rgbtRed;
  257.                                                                 ptr[1] = os2_palette[ color ].rgbtGreen;
  258.                                                                 ptr[0] = os2_palette[ color ].rgbtBlue;
  259.                                                         }
  260.                                                         else
  261.                                                         {
  262.                                                                 ptr[2] = win_palette[ color ].rgbRed;
  263.                                                                 ptr[1] = win_palette[ color ].rgbGreen;
  264.                                                                 ptr[0] = win_palette[ color ].rgbBlue;
  265.                                                         }
  266.                                                 }
  267.  
  268.                                                 break;
  269.                                         }
  270.  
  271.                                         case 24:
  272.                                         {
  273. // RGB 24 BITS
  274.                                                 for( col = 0; col < w; col++, ptr += 3 )
  275.                                                 {
  276.                                                         // convert bgr pixel (24 bits) into rgb (32 bits) pixel
  277.                                                         RGBTRIPLE *pix = (RGBTRIPLE *)pBuff;
  278.                                                         pBuff += sizeof( RGBTRIPLE );
  279.  
  280.                                                         ptr[2] = pix->rgbtRed;
  281.                                                         ptr[1] = pix->rgbtGreen;
  282.                                                         ptr[0] = pix->rgbtBlue;
  283.                                                 }
  284.  
  285.                                                 break;
  286.                                         }
  287.  
  288.                                         case 32:
  289.                                         {
  290. // RGB 32 BITS
  291.                                                 for( col = 0; col < w; col++, ptr += 3 )
  292.                                                 {
  293.                                                         // // convert bgr pixel (32 bits) into rgb (32 bits) pixel
  294.                                                         RGBQUAD *pix = (RGBQUAD *)pBuff;
  295.                                                         pBuff += sizeof( RGBQUAD );
  296.  
  297.                                                         ptr[2] = pix->rgbRed;
  298.                                                         ptr[1] = pix->rgbGreen;
  299.                                                         ptr[0] = pix->rgbBlue;
  300.  
  301.                                                 }
  302.  
  303.                                                 break;
  304.                                         }
  305.                                 }
  306.                         }
  307.  
  308.                         break;
  309.                 }
  310.  
  311.                 case BI_RLE8:
  312.                 {
  313. // RLE 8 BITS
  314.                         for( row = h - 1; row >= 0; row-- )
  315.                         {
  316.                                 if( flipvert )
  317.                                         ptr = &(*pixels)[ row * w * 3 ];
  318.  
  319.                                 for( col = 0; col < w; /* nothing */ )
  320.                                 {
  321.                                         // get one packet (2 bytes)
  322.                                         unsigned char byte1 = *((unsigned char *)(pBuff++));
  323.                                         unsigned char byte2 = *((unsigned char *)(pBuff++));
  324.  
  325.  
  326.                                         if( byte1 == RLE_COMMAND )
  327.                                         {
  328.                                                 // absolute encoding
  329.                                                 for( i = 0; i < byte2; i++, ptr += 3, col++ )
  330.                                                 {
  331.                                                         // read the current pixel
  332.                                                         unsigned char color = *((unsigned char *)(pBuff++));
  333.  
  334.                                                         // convert indexed pixel (8 bits) into rgb (32 bits) pixel
  335.                                                         ptr[2] = win_palette[ color ].rgbRed;
  336.                                                         ptr[1] = win_palette[ color ].rgbGreen;
  337.                                                         ptr[0] = win_palette[ color ].rgbBlue;
  338.                                                 }
  339.  
  340.                                                 if( (byte2 % 2) == 1 )
  341.                                                         pBuff++;
  342.                                         }
  343.                                         else
  344.                                         {
  345.                                                 // read next pixels
  346.                                                 for( i = 0; i < byte1; i++, ptr += 3, col++ )
  347.                                                 {
  348.                                                         // convert indexed pixel (8 bits) into rgb (32 bits) pixel
  349.                                                         ptr[2] = win_palette[ byte2 ].rgbRed;
  350.                                                         ptr[1] = win_palette[ byte2 ].rgbGreen;
  351.                                                         ptr[0] = win_palette[ byte2 ].rgbBlue;
  352.                                                 }        
  353.                                         }
  354.                                 }
  355.                         }
  356.  
  357.                         break;
  358.                 }
  359.  
  360.                 case BI_RLE4:
  361.                 {
  362. // RLE 4 BITS
  363.                         unsigned char color;
  364.                         int     bytesRead = 0;          // number of bytes read
  365.  
  366.                         for( row = h - 1; row >= 0; row-- )
  367.                         {
  368.                                 if( flipvert )
  369.                                         ptr = &(*pixels)[ row * w * 3 ];
  370.  
  371.                                 for( col = 0; col < w; /* nothing */ )
  372.                                 {
  373.                                         // get one packet (2 bytes)
  374.                                         unsigned char byte1 = *((unsigned char *)(pBuff++));
  375.                                         unsigned char byte2 = *((unsigned char *)(pBuff++));
  376.  
  377.                                         bytesRead += 2;
  378.  
  379.  
  380.                                         if( byte1 == RLE_COMMAND )
  381.                                         {
  382.                                                 // absolute encoding
  383.                                                 unsigned char databyte;
  384.  
  385.                                                 for( i = 0; i < byte2; i++, ptr += 3, col++ )
  386.                                                 {
  387.                                                         if( (i % 2) == 0 )
  388.                                                         {
  389.                                                                 // read the current pixel
  390.                                                                 databyte = *((unsigned char *)(pBuff++));
  391.                                                                 bytesRead++;
  392.  
  393.                                                                 color = (databyte >> 4);        // 4 first bits
  394.                                                         }
  395.                                                         else
  396.                                                         {
  397.                                                                 color = (databyte & 0x0F);      // 4 last bits
  398.                                                         }
  399.  
  400.                                                         // convert indexed pixel (4 bits) into rgb (32 bits) pixel
  401.                                                         ptr[2] = win_palette[ color ].rgbRed;
  402.                                                         ptr[1] = win_palette[ color ].rgbGreen;
  403.                                                         ptr[0] = win_palette[ color ].rgbBlue;
  404.                                                 }
  405.          
  406.                                                 while( (bytesRead % 2) != 0 )
  407.                                                 {
  408.                                                         pBuff++;
  409.                                                         bytesRead++;
  410.                                                 }
  411.                                         }
  412.                                         else
  413.                                         {
  414.                                                 // read next pixels
  415.                                                 for( i = 0; i < byte1; i++, ptr += 3, col++ )
  416.                                                 {
  417.                                                         if( (i % 2) == 0 )
  418.                                                                 color = (byte2 >> 4);   // 4 first bits
  419.                                                         else
  420.                                                                 color = (byte2 & 0x0F); // 4 last bits
  421.  
  422.                                                         // convert indexed pixel (4 bits) into rgb (32 bits) pixel
  423.                                                         ptr[2] = win_palette[ color ].rgbRed;
  424.                                                         ptr[1] = win_palette[ color ].rgbGreen;
  425.                                                         ptr[0] = win_palette[ color ].rgbBlue;
  426.                                                 }        
  427.                                         }
  428.                                 }
  429.                         }
  430.  
  431.                         break;
  432.                 }
  433.         }
  434.  
  435.  
  436.         // free buffer memory
  437.         delete [] buffer;
  438.  
  439.  
  440.         // return success
  441.         return 1;
  442. }
  443.