home *** CD-ROM | disk | FTP | other *** search
/ MACD 9 / MACD9.iso / Skanery / BetaScan / ScannerDev / MakeILBM.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-02  |  11.4 KB  |  451 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /* Write image as ilbm                                                  */
  4. /*                                                                      */
  5. /*                                                                      */
  6. /*                                                                      */
  7. /*                                                                      */
  8. /************************************************************************/
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include <exec/types.h>
  15. #include <datatypes/pictureclass.h>
  16.  
  17. #include "MakeILBM.h"
  18. #include "packer.h"
  19.  
  20. #define ID_XBMI MAKE_ID('X','B','M','I')
  21. #define ILBM_BUFLEN 1500000
  22.  
  23. struct ImageBuf
  24. {
  25.   UBYTE* buf;
  26.   ULONG  actualLen;
  27.   FILE*  fh;
  28. };
  29.  
  30. struct ILBMFile
  31. {
  32.   char* fileName;
  33.   int   formLenOffset;
  34.   int   bodyLenOffset;
  35.   UBYTE flags;
  36.   
  37.   UBYTE depth;
  38.   UWORD width;
  39.   UWORD height;
  40.   UWORD xdpi;
  41.   UWORD ydpi;
  42.  
  43.   ULONG scanLineWidth;
  44.   ULONG bufLen;
  45.   struct ImageBuf buf[3];
  46. };
  47.  
  48. #define ILBMFLAGS_COMPRESS  (0x01 << 0)
  49. #define ILBMFLAGS_TEMPFILE  (0x01 << 1)
  50.  
  51. struct xbmi
  52. {
  53.   WORD xbmi_type;   /* ILBM_PAL, ILBM_RGB, ... (se below) */
  54.   WORD xbmi_xdpi;
  55.   WORD xbmi_ydpi;
  56. };
  57.  
  58.  
  59. #define ILBM_PAL        0       /* BODY data = indexes into the palette (CMAP)
  60.                                  * numcolors = 1<<depth;
  61.                                  */
  62.  
  63. #define ILBM_GREY       1       /* BODY =  grayscale values
  64.                                  * Bits per sample = number of bitplanes.
  65.                                  * Samples per pixel = 1.
  66.                                  * black = 0, white = (1<<depth)-1;
  67.                                  */
  68.  
  69. #define ILBM_RGB        2       /* BODY data = red, green, and blue values.
  70.                                  * Bits per sample = depth/3.
  71.                                  * Samples per pixel = 3.
  72.                                  */
  73.  
  74. #define ILBM_RGBA       3       /* BODY data = red, green, blue, and alpha
  75.                                  * channel values.
  76.                                  * Bits per sample = depth/4.
  77.                                  * Samples per pixel = 4.
  78.                                  */
  79.  
  80. #define ILBM_CMYK       4       /* BODY data = cyan, magenta, yellow, and black
  81.                                  * values.
  82.                                  * Bits per sample = depth/4.
  83.                                  * Samples per pixel = 4.
  84.                                  */
  85.  
  86. #define ILBM_CMYKA      5       /* BODY data = cyan, magenta, yellow, black,
  87.                                  * and alpha channel values.
  88.                                  * Bits per sample = depth/5.
  89.                                  * Samples per pixel = 5.
  90.                                  */
  91.  
  92. #define ILBM_BW         6       /* BODY data = black and white bits.
  93.                                  * Bits per sample = 1.
  94.                                  * Samples per pixel = 1.
  95.                                  * white = 0, black = 1.
  96.                                  */
  97.  
  98. static char* tempfile[3] = {"temp.red","temp.green","temp.blue"};
  99.  
  100. static void makePlane(UBYTE* source,UBYTE* dest,int bit,int length)
  101. {
  102.   int   bitNum,byteNum;
  103.   UBYTE b,sourceMask;
  104.  
  105.   sourceMask = 0x01 << bit;
  106.   
  107.   for( byteNum = 0 ; byteNum < length ; byteNum++ )
  108.   {
  109.     UBYTE destMask;
  110.     
  111.     destMask = 0x80;
  112.     b = 0;
  113.     for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  114.     {
  115.       if( (*source) & sourceMask )
  116.         b |= destMask;
  117.  
  118.       destMask >>= 1;
  119.       source++;
  120.     }
  121.     *(dest++) = b;
  122.   }
  123.  
  124. static void makeILBM(struct ILBMFile* ilbmfh)
  125. {
  126.   struct BitMapHeader BMHD;
  127.   struct xbmi         XBMI;
  128.   FILE*  fh;
  129.   int    c;
  130.   
  131.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  132.   {
  133.     for( c = 0 ; c < 3 ; c++ )
  134.     {
  135.       ilbmfh->buf[c].fh = fopen(tempfile[c],"r");
  136.       setvbuf(ilbmfh->buf[c].fh,ilbmfh->buf[c].buf,_IOFBF,ilbmfh->bufLen);
  137.     }
  138.   }
  139.   
  140.   BMHD.bmh_Width = ilbmfh->width;
  141.   BMHD.bmh_Height = ilbmfh->height;
  142.   BMHD.bmh_Left = 0;
  143.   BMHD.bmh_Top = 0;
  144.   BMHD.bmh_Depth = ilbmfh->depth;
  145.   BMHD.bmh_Masking = 0;
  146.   BMHD.bmh_Pad = 0;
  147.   BMHD.bmh_Transparent = 0;
  148.   BMHD.bmh_XAspect = 1;
  149.   BMHD.bmh_YAspect = 1;
  150.   BMHD.bmh_PageWidth = ilbmfh->width;
  151.   BMHD.bmh_PageHeight = ilbmfh->height;
  152.   
  153.   switch( ilbmfh->depth )
  154.   {
  155.     case 1:
  156.       XBMI.xbmi_type = ILBM_BW;
  157.       break;
  158.     case 8:
  159.       XBMI.xbmi_type = ILBM_GREY;
  160.       break;
  161.     case 24:
  162.       XBMI.xbmi_type = ILBM_RGB;
  163.       break;
  164.   }        
  165.   XBMI.xbmi_xdpi = ilbmfh->xdpi;
  166.   XBMI.xbmi_ydpi = ilbmfh->ydpi;
  167.  
  168.   if( fh = fopen(ilbmfh->fileName,"w") )
  169.   {
  170.     int scanLine,color,bitNum;
  171.     ULONG lineLen,bodyLen,formLen;
  172.     ULONG temp,psize;
  173.     UBYTE *line;
  174.     UBYTE *pline = NULL;
  175.     UBYTE *scanbuf = NULL;
  176.  
  177.     lineLen = ((ilbmfh->width+7)/8+1) & 0xFFFFFFFE;
  178.     line = malloc(lineLen);
  179.     if( (ilbmfh->flags & ILBMFLAGS_COMPRESS) && (pline = malloc(lineLen*2)) )
  180.       BMHD.bmh_Compression = 1;
  181.     else
  182.       BMHD.bmh_Compression = 0;
  183.       
  184.     temp = ID_FORM;
  185.     fwrite(&temp,4,1,fh);
  186.     ilbmfh->formLenOffset = ftell(fh);
  187.     temp = 0;
  188.     fwrite(&temp,4,1,fh);
  189.  
  190.     temp = ID_ILBM;
  191.     fwrite(&temp,4,1,fh);
  192.  
  193.     temp = ID_BMHD;
  194.     fwrite(&temp,4,1,fh);
  195.     temp = sizeof(struct BitMapHeader);
  196.     fwrite(&temp,4,1,fh);
  197.     fwrite(&BMHD,sizeof(struct BitMapHeader),1,fh);
  198.     
  199.     temp = ID_XBMI;
  200.     fwrite(&temp,4,1,fh);
  201.     temp = sizeof(struct xbmi);
  202.     
  203.     fwrite(&temp,4,1,fh);
  204.     fwrite(&XBMI,sizeof(struct xbmi),1,fh);
  205.  
  206.     if( ilbmfh->depth == 1 )
  207.     {
  208.       UBYTE b;
  209.       
  210.       temp = ID_CMAP;
  211.       fwrite(&temp,4,1,fh);
  212.       temp = 3*2;;
  213.       fwrite(&temp,4,1,fh);
  214.  
  215.       b = 0xFF;
  216.       fwrite(&b,1,1,fh);
  217.       fwrite(&b,1,1,fh);
  218.       fwrite(&b,1,1,fh);
  219.  
  220.       b = 0;
  221.       fwrite(&b,1,1,fh);
  222.       fwrite(&b,1,1,fh);
  223.       fwrite(&b,1,1,fh);
  224.     }
  225.     else if( ilbmfh->depth == 8 )
  226.     {
  227.       UBYTE b;
  228.       int   i;
  229.       
  230.       temp = ID_CMAP;
  231.       fwrite(&temp,4,1,fh);
  232.       temp = 3*256;;
  233.       fwrite(&temp,4,1,fh);
  234.       for( i = 0 ;  i < 256 ; i++ )
  235.       {
  236.         b = (UBYTE)i;
  237.         fwrite(&b,1,1,fh);
  238.         fwrite(&b,1,1,fh);
  239.         fwrite(&b,1,1,fh);
  240.       }
  241.     }
  242.     
  243.     temp = ID_BODY;
  244.     fwrite(&temp,4,1,fh);
  245.     ilbmfh->bodyLenOffset = ftell(fh);
  246.     temp = 0;
  247.     fwrite(&temp,4,1,fh);
  248.  
  249.     if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  250.       scanbuf = malloc(ilbmfh->scanLineWidth);
  251.     
  252.     switch( ilbmfh->depth )
  253.     {
  254.       case 1:
  255.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  256.         {
  257.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  258.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  259.           else
  260.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  261.  
  262.           if( pline == NULL )
  263.             fwrite(scanbuf,lineLen,1,fh);
  264.           else
  265.           {
  266.             psize = PackRow(scanbuf,pline,lineLen);
  267.             fwrite(pline,psize,1,fh);
  268.           }
  269.         }
  270.         break;
  271.       case 8:
  272.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  273.         {
  274.           if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  275.             fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[0].fh);
  276.           else
  277.             scanbuf = ilbmfh->buf[0].buf + scanLine*ilbmfh->scanLineWidth;
  278.           for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  279.           {
  280.             makePlane(scanbuf,line,bitNum,lineLen);
  281.             if( pline == NULL )
  282.               fwrite(line,lineLen,1,fh);
  283.             else
  284.             {
  285.               psize = PackRow(line,pline,lineLen);
  286.               fwrite(pline,psize,1,fh);
  287.             }
  288.           }
  289.         }
  290.         break;
  291.       case 24:
  292.         for( scanLine = 0 ; scanLine < ilbmfh->height ; scanLine++ )
  293.         {
  294.           for( color = 0 ; color < 3 ; color++ )
  295.           {
  296.             if( ilbmfh->buf[color].buf )
  297.             {
  298.               if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  299.                 fread(scanbuf,ilbmfh->scanLineWidth,1,ilbmfh->buf[color].fh);
  300.               else
  301.                 scanbuf = ilbmfh->buf[color].buf + scanLine*ilbmfh->scanLineWidth;
  302.               for( bitNum = 0 ; bitNum < 8 ; bitNum++ )
  303.               {
  304.                 makePlane(scanbuf,line,bitNum,lineLen);
  305.                 if( pline == NULL )
  306.                   fwrite(line,lineLen,1,fh);
  307.                 else
  308.                 {
  309.                   psize = PackRow(line,pline,lineLen);
  310.                   fwrite(pline,psize,1,fh);
  311.                 }
  312.               }
  313.             }
  314.           }
  315.         }
  316.         break;
  317.     }        
  318.     free(line);
  319.     if( pline )
  320.       free(pline);
  321.     if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  322.       free(scanbuf);
  323.  
  324.     for( color = 0 ; color < 3 ; color++ )
  325.     {
  326.       if( ilbmfh->buf[color].fh )
  327.         fclose(ilbmfh->buf[color].fh);
  328.       if( ilbmfh->buf[color].buf )
  329.         free(ilbmfh->buf[color].buf);
  330.     }
  331.  
  332.     // Write FORM and BODY length
  333.     formLen = ftell(fh) - ilbmfh->formLenOffset - 4;
  334.     bodyLen = ftell(fh) - ilbmfh->bodyLenOffset - 4;
  335.  
  336.     fseek(fh,ilbmfh->formLenOffset,SEEK_SET);
  337.     fwrite(&formLen,4,1,fh);
  338.  
  339.     fseek(fh,ilbmfh->bodyLenOffset,SEEK_SET);
  340.     fwrite(&bodyLen,4,1,fh);
  341.     
  342.     fclose(fh);
  343.   }
  344. }
  345.  
  346.  
  347. struct ILBMFile *openILBM(char* name,int width,int height,int depth,int xdpi,int ydpi,short compr)
  348. {
  349.   struct ILBMFile* fh;
  350.   
  351.   if( fh = calloc(1,sizeof(struct ILBMFile)) )
  352.   {
  353.     fh->fileName = name;
  354.     if( compr )
  355.       fh->flags = ILBMFLAGS_COMPRESS;
  356.     else
  357.       fh->flags = 0;
  358.     fh->depth = depth;
  359.     fh->width = width;
  360.     fh->height = height;
  361.     fh->xdpi = xdpi;
  362.     fh->ydpi = ydpi;
  363.  
  364.     switch( depth )
  365.     {
  366.       case 1:
  367.         fh->scanLineWidth = (width+7)/8;
  368.         fh->bufLen = fh->scanLineWidth*height;
  369.         if( fh->bufLen > ILBM_BUFLEN )
  370.           fh->bufLen = ILBM_BUFLEN;
  371.         fh->buf[0].buf = malloc(fh->bufLen);
  372.         break;
  373.       case 8:
  374.         fh->scanLineWidth = width;
  375.         fh->bufLen = fh->scanLineWidth*height;
  376.         if( fh->bufLen > ILBM_BUFLEN )
  377.           fh->bufLen = ILBM_BUFLEN;
  378.         fh->buf[0].buf = malloc(fh->bufLen);
  379.         break;
  380.       case 24:
  381.         {
  382.           int c;
  383.           
  384.         fh->scanLineWidth = width;
  385.         fh->bufLen = fh->scanLineWidth*height;
  386.           if( 3*fh->bufLen > ILBM_BUFLEN )
  387.             fh->bufLen = ILBM_BUFLEN/3;
  388.             
  389.           for( c = 0 ; c < 3 ; c++ )
  390.             fh->buf[c].buf = malloc(fh->bufLen);
  391.         }
  392.         break;
  393.       default:
  394.         free(fh);
  395.         return NULL;
  396.     }
  397.   }
  398.         
  399.   return fh;
  400. }
  401.  
  402. void closeILBM(struct ILBMFile* ilbmfh,short error)
  403. {
  404.   int    c;
  405.   
  406.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  407.   {
  408.     for( c = 0 ; c < 3 ; c++ )
  409.     {
  410.       if( ilbmfh->buf[c].fh )
  411.       {
  412.         fwrite(ilbmfh->buf[c].buf,ilbmfh->buf[c].actualLen,1,ilbmfh->buf[c].fh);
  413.         fclose(ilbmfh->buf[c].fh);
  414.         ilbmfh->buf[c].fh = NULL;
  415.       }
  416.     }
  417.   }
  418.  
  419.   if( !error )
  420.     makeILBM(ilbmfh);
  421.  
  422.   if( ilbmfh->flags & ILBMFLAGS_TEMPFILE )
  423.   {
  424.     for( c = 0 ; c < 3 ; c++ )
  425.       remove(tempfile[c]);
  426.   }
  427.  
  428.   free(ilbmfh);
  429. }
  430.  
  431. void writeILBM(struct ILBMFile* fh,UBYTE* buf,int cPlane)
  432. {
  433.   if( fh->buf[cPlane].actualLen + fh->scanLineWidth > fh->bufLen )
  434.   {
  435.     if( fh->buf[cPlane].fh == NULL )
  436.     {
  437.       if( fh->buf[cPlane].fh = fopen(tempfile[cPlane],"w") )
  438.         fh->flags |= ILBMFLAGS_TEMPFILE;
  439.       else
  440.         return;
  441.     }
  442.           
  443.     fwrite(fh->buf[cPlane].buf,fh->buf[cPlane].actualLen,1,fh->buf[cPlane].fh);
  444.     fh->buf[cPlane].actualLen = 0;
  445.   }
  446.  
  447.   memcpy(fh->buf[cPlane].buf+fh->buf[cPlane].actualLen,buf,fh->scanLineWidth);
  448.   fh->buf[cPlane].actualLen += fh->scanLineWidth;
  449. }
  450.