home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / contrib / bmp2vbm / bmp2vbm.cpp next >
C/C++ Source or Header  |  1998-07-03  |  9KB  |  368 lines

  1. #include <stdio.h>
  2.  
  3. #define BI_RGB  0
  4. #define BI_RLE8 1
  5. #define BI_RLE4 2
  6.  
  7. #define WIN 40
  8. #define OS2 64
  9.  
  10.   int bmp2vbm(FILE* fileIn, FILE* fileOut, char* vbmName);
  11.   static unsigned int rdInt16(FILE *fileIn);
  12.   static unsigned int rdInt32(FILE *fileIn);
  13.   static int rdBMP1(FILE* fileIn, unsigned char* rev,
  14.             unsigned int w, unsigned int h);
  15.   static int rdBMP4(FILE* fileIn, unsigned char* rev,
  16.             unsigned int w, unsigned int h, unsigned int comp);
  17.   static int rdBMP8(FILE* fileIn, unsigned char* rev,
  18.             unsigned int w, unsigned int h, unsigned comp);
  19.   static int rdBMP24(FILE* fileIn, unsigned char* rev,
  20.              unsigned int w, unsigned int h);
  21.   static unsigned int rdInt16(FILE *fileIn);
  22.   static unsigned int rdInt32(FILE *fileIn);
  23.  
  24. // ==========================>>> main <<<==========================
  25.   int main(int argc, char** argv)
  26.   {
  27.     // simple driver for bmp2vbm
  28.  
  29.     FILE* fin;
  30.     FILE* fout;
  31.  
  32.     if (argc != 4)
  33.       {
  34.     fprintf(stderr,"Usage: b2v in.bmp out.vbm iconname\n");
  35.         return 0;
  36.       }
  37.     if (!(fin = fopen(argv[1],"rb")))
  38.       {
  39.     fprintf(stderr,"Input .bmp file %s not found.\n",argv[1]);
  40.         return 0;
  41.       }
  42.     if (!(fout = fopen(argv[2],"w")))
  43.       {
  44.     fprintf(stderr,"Can't create output .vbm file %s.\n",argv[2]);
  45.     fclose(fin);
  46.         return 0;
  47.       }
  48.  
  49.  
  50.     int res = bmp2vbm(fin, fout, argv[3]);
  51.     if (!res)
  52.     fprintf(stderr,"Conversion failed\n");
  53.     fclose(fin);
  54.     fclose(fout);
  55.  
  56.     return 0;
  57.   }
  58.  
  59. // ==========================>>> bmp2vbm <<<==========================
  60.   int bmp2vbm(FILE* fileIn, FILE* fileOut, char* vbmName)
  61.   {
  62.     // Convert MSDOS, OS/2 bmp file to a V .vbm file
  63.  
  64.     int          i, c, c1, rv;
  65.     unsigned int bfSize, bfOffBits, Size, Width, Height, Planes;
  66.     unsigned int BitCount, Compression, SizeImage, XPelsPerMeter;
  67.     unsigned int YPelsPerMeter, ClrUsed, ClrImportant;
  68.     int bPad;
  69.  
  70.     // First two bytes must be "BM"
  71.  
  72.     c = getc(fileIn);  c1 = getc(fileIn);
  73.     if (c !='B' || c1 != 'M')        // anything not BM fails
  74.     return 0;
  75.  
  76.     bfSize = rdInt32(fileIn);
  77.     rdInt16(fileIn);                 // reserved: ignore
  78.     rdInt16(fileIn);
  79.     bfOffBits = rdInt32(fileIn);
  80.  
  81.     Size = rdInt32(fileIn);
  82.  
  83.     if (Size == WIN || Size == OS2)  // read header info
  84.       {
  85.     Width         = rdInt32(fileIn);
  86.     Height        = rdInt32(fileIn);
  87.     Planes        = rdInt16(fileIn);
  88.     BitCount      = rdInt16(fileIn);
  89.     Compression   = rdInt32(fileIn);
  90.     SizeImage     = rdInt32(fileIn);
  91.     XPelsPerMeter = rdInt32(fileIn);
  92.     YPelsPerMeter = rdInt32(fileIn);
  93.     ClrUsed       = rdInt32(fileIn);
  94.     ClrImportant  = rdInt32(fileIn);
  95.       }
  96.     else
  97.     return 0;            // old format, we won't handle!
  98.  
  99.     // Check to see if things are as they should be
  100.  
  101.     if (ferror(fileIn) || feof(fileIn))    // something is amis
  102.     return 0;            // so fail
  103.  
  104.     if ((BitCount!=1 && BitCount!=4 && BitCount!=8 && BitCount!=24) || 
  105.       Planes!=1 || Compression > BI_RLE4)
  106.     return 0;
  107.  
  108.     if (((BitCount==1 || BitCount==24) && Compression != BI_RGB) ||
  109.     Compression != BI_RGB)    // only uncompressed for now
  110. //         (BitCount==4 && Compression==BI_RLE8) ||
  111. //         (BitCount==8 && Compression==BI_RLE4))
  112.     return 0;
  113.  
  114.     // Skip to color map
  115.     c = Size - 40;    // 40 bytes read from Size to ClrImportant
  116.     for (i=0; i<c; i++)
  117.     getc(fileIn);
  118.     
  119.     bPad = bfOffBits - (Size + 14);    // padding after color map
  120.  
  121.     // Now, write the header
  122.  
  123.     if (BitCount != 24)        // colormap for 1 or 4 or 8
  124.       {
  125.     int i, cmaplen;
  126.     cmaplen = (ClrUsed) ? ClrUsed : 1 << BitCount;
  127.  
  128.         fprintf(fileOut,"//vbm8\n");
  129.     fprintf(fileOut,"#define %s_height %d\n", vbmName,Height);
  130.     fprintf(fileOut,"#define %s_width %d\n", vbmName,Width);
  131.     fprintf(fileOut,"unsigned char %s_bits[] = {\n%d,\n",vbmName,cmaplen-1);
  132.  
  133.     int r,g,b;
  134.       int valsOut = 0;
  135.     for (i=0; i<cmaplen; i++)
  136.       {
  137.         b = getc(fileIn);
  138.         g = getc(fileIn);
  139.         r = getc(fileIn);
  140.         (void) getc(fileIn);    // skip pad byte
  141.         bPad -= 4;            // we just read 4 bytes
  142.         fprintf(fileOut,"%d,%d,%d,",r,g,b);
  143.         valsOut += 3;
  144.         if (valsOut >= 20)
  145.           {
  146.         valsOut = 0;
  147.          fprintf(fileOut,"\n");
  148.           }
  149.       }
  150.     fprintf(fileOut,"// begin bitmap\n");
  151.       }
  152.     else                // 24 bit bmp
  153.       {
  154.     fprintf(fileOut,"//vbm24\n");
  155.     fprintf(fileOut,"#define %s_height %d\n", vbmName,Height);
  156.     fprintf(fileOut,"#define %s_width %d\n", vbmName,Width);
  157.     fprintf(fileOut,"unsigned char %s[] = {\n",vbmName);
  158.       }
  159.  
  160.     if (ferror(fileIn) || feof(fileIn))    // something is amiss
  161.     return 0;            // so fail
  162.  
  163.     // Now, skip over any unused bytes between the color map (if there
  164.     // was one, and the start of the bitmap data.
  165.     
  166.     while (bPad > 0)
  167.       {
  168.     (void) getc(fileIn);
  169.     bPad--;
  170.       }
  171.  
  172.     // Now, read rest of file and write out an 8 or 24 bit v icon def
  173.  
  174.     long limit = (BitCount == 24) ? Width*Height*3 : Width*Height;
  175.  
  176.     unsigned char* rev = new unsigned char[limit];
  177.  
  178.     if (BitCount == 1)
  179.     rv = rdBMP1(fileIn,rev,Width,Height);
  180.     else if (BitCount == 4)
  181.     rv = rdBMP4(fileIn,rev,Width,Height,Compression);
  182.     else if (BitCount == 8)
  183.     rv = rdBMP8(fileIn,rev,Width,Height, Compression);
  184.     else
  185.     rv = rdBMP24(fileIn,rev,Width,Height);
  186.  
  187.     int valsOut = 0;
  188.  
  189.     // have to reverse the bitmap's row order
  190.  
  191.     long rowLen = (BitCount == 24) ? Width*3 : Width;
  192.  
  193.     for (long ix = limit - rowLen ; ix >= 0 ; ix -= rowLen)
  194.       {
  195.     // output one row
  196.     for (long ri = 0 ; ri < rowLen ; ++ri)
  197.       {
  198.         fprintf(fileOut,"%d,",rev[ix+ri]);
  199.         if (++valsOut >= 20)
  200.           {
  201.         valsOut = 0; fprintf(fileOut,"\n");
  202.           }
  203.       }
  204.       }
  205.  
  206.     fprintf(fileOut,"0};\n");
  207.     if (!rv)
  208.     return 0;
  209.  
  210.     return 1;
  211.  
  212.   }  
  213.  
  214. //=========================>> rdBMP1 <<=============================
  215.   static int rdBMP1(FILE* fileIn, unsigned char* rev,
  216.     unsigned int w, unsigned int h)
  217.   {
  218.     int i,j,c,bitnum,padw;
  219.  
  220.     c = 0;
  221.     padw = ((w + 31)/32) * 32;  /* 'w', padded to be a multiple of 32 */
  222.  
  223.     for (i=h-1; i>=0; i--)
  224.       {
  225.     for (j=bitnum=0; j<padw; j++,bitnum++)
  226.       {
  227.         if ((bitnum&7) == 0)
  228.           { /* read the next byte */
  229.         c = getc(fileIn);
  230.         bitnum = 0;
  231.           }
  232.       
  233.         if (j<w)
  234.           {
  235.         *rev++ = (c & 0x80) ? 1 : 0;
  236.         c <<= 1;
  237.           }
  238.       }
  239.  
  240.     if (ferror(fileIn) || feof(fileIn))    // something is amiss
  241.         return 0;            // so fail
  242.       }
  243.  
  244.     if (ferror(fileIn) || feof(fileIn))    // something is amiss
  245.     return 0;            // so fail
  246. }  
  247.  
  248. //=========================>> rdBMP4 <<=============================
  249.   static int rdBMP4(FILE* fileIn, unsigned char*rev,
  250.             unsigned int w, unsigned int h, unsigned int comp)
  251.   {
  252.     int   i,j,c,c1,x,y,nybnum,padw,rv;
  253.  
  254.     rv = 1;
  255.     c = c1 = 0;
  256.  
  257.     if (comp == BI_RGB)            // read uncompressed data
  258.       {
  259.     padw = ((w + 7)/8) * 8;     // 'w' padded to a multiple of 8pix (32 bits)
  260.  
  261.     for (i=h-1; i>=0; i--)
  262.       {
  263.         for (j=nybnum=0; j<padw; j++,nybnum++)
  264.           {
  265.         if ((nybnum & 1) == 0)    // read next byte
  266.           { /* read next byte */
  267.             c = getc(fileIn);
  268.             nybnum = 0;
  269.           }
  270.  
  271.         if (j<w)
  272.           {
  273.             *rev++ = (c & 0xf0) >> 4;
  274.             c <<= 4;
  275.           }
  276.         if (ferror(fileIn) || feof(fileIn))    // something is amiss
  277.             return 0;            // so fail
  278.           }
  279.       }
  280.       }
  281.     else
  282.     return 0;
  283.   
  284.     if (ferror(fileIn) || feof(fileIn))    // something is amiss
  285.     return 0;            // so fail
  286.     return rv;
  287.   }  
  288.  
  289. //=========================>> rdBMP8 <<=============================
  290.   static int rdBMP8(FILE* fileIn, unsigned char* rev,
  291.             unsigned int w, unsigned int h, unsigned int comp)
  292.   {
  293.     int   i,j,c,c1,padw,x,y,rv;
  294.  
  295.     rv = 1;
  296.  
  297.     if (comp == BI_RGB)        // read uncompressed data
  298.       {
  299.     padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
  300.  
  301.     for (i=h-1; i>=0; i--) 
  302.       {
  303.         for (j=0; j<padw; j++) 
  304.           {
  305.         c = getc(fileIn);
  306.         if (c==EOF) 
  307.             rv = 1;
  308.         if (j<w)
  309.           {
  310.             *rev++ = c;
  311.           }
  312.         if (ferror(fileIn) || feof(fileIn))    // something is amiss
  313.             return 0;            // so fail
  314.           }
  315.       }
  316.       }
  317.     else 
  318.     return 0;
  319.  
  320.     if (ferror(fileIn) || feof(fileIn))    // something is amiss
  321.     return 0;            // so fail
  322.     return rv;
  323.   }  
  324.  
  325. //=========================>> rdBMP24 <<=============================
  326.   static int rdBMP24(FILE* fileIn, unsigned char* rev,
  327.              unsigned int w, unsigned int h)
  328.   {
  329.     int   i,j,padb,rv;
  330.     unsigned int r,g,b;
  331.  
  332.     padb = (4 - ((w*3) % 4)) & 0x03;  // # of pad bytes to read at EOscanline
  333.  
  334.     for (i=h-1; i>=0; i--)
  335.       {
  336.     for (j=0; j<w; j++) 
  337.       {
  338.         b = getc(fileIn);   // blue
  339.         g = getc(fileIn);   // green
  340.         r = getc(fileIn);   // red
  341.         *rev++ = r; *rev++ = g; *rev++ = b;
  342.       }
  343.  
  344.     for (j=0; j<padb; j++) 
  345.         getc(fileIn);
  346.       }
  347.     return 1;
  348.   }  
  349.  
  350. //=============================>>> rdInt16 <<<=============================
  351.   static unsigned int rdInt16(FILE *fileIn)
  352.   {
  353.     int c, c1;
  354.     c = getc(fileIn);  c1 = getc(fileIn);
  355.     return ((unsigned int) c) + (((unsigned int) c1) << 8);
  356.   }
  357.  
  358. //=============================>>> rdInt32 <<<=============================
  359.   static unsigned int rdInt32(FILE *fileIn)
  360.   {
  361.     int c, c1, c2, c3;
  362.     c = getc(fileIn);  c1 = getc(fileIn);  c2 = getc(fileIn);  c3 = getc(fileIn);
  363.     return ((unsigned int) c) +
  364.          (((unsigned int) c1) << 8) + 
  365.      (((unsigned int) c2) << 16) +
  366.      (((unsigned int) c3) << 24);
  367.   }
  368.