home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 199.lha / GimmeLib / picture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-28  |  8.7 KB  |  401 lines

  1. /*
  2.  *  FILE: picture.c
  3.  *  Support routines for reading IFF/ILBM files.
  4.  *
  5.  *  Public Domain, but keep our names in it as the original authors.
  6.  *  08-Dec-87    Rico Mariani        original code (modified by JST)
  7.  *  31-Aug-88    Jan Sven Trabandt   first release version
  8.  */
  9.  
  10.  
  11. #define I_AM_PICTURE
  12. #include "gimmelib/gimmefuncs.h"
  13. #include "gimmelib/picture.h"
  14. #include "gimmelib/postext.h"
  15. #include "gimmelib/minterm.h"
  16. #include <stdio.h>
  17.  
  18.  
  19. #define GET(iffile)         getc( iffile )
  20.  
  21. #define getId            getLong
  22. #define getLen            getLong
  23. #define getByte         GET
  24. #define skip(len, file)     fseek(file, (long)(len), 1)
  25.  
  26. #define getBMH(bmh, file)   fread(bmh, sizeof(BitMapHeader), 1, file)
  27.  
  28. /* requires an existent variable 'char *errmsg' and a label 'failure_return' */
  29. #define fail_and_return(msg)    {errmsg = msg; goto failure_return;}
  30.  
  31. /* forward declarations */
  32. static LONG getLong();
  33. static WORD getWord();
  34. static ULONG makeBM();
  35.  
  36. static char noMemMsg[] = "insufficient memory\n";
  37. static char badFileMsg[] = "corrupt or incomplete file\n";
  38.  
  39.  
  40. PICTURE *gimmePicture( filename, myflags )
  41.     UBYTE   *filename;
  42.     ULONG   myflags;
  43. {
  44.     LONG    len, id;
  45.     PICTURE *pic = NULL;
  46.     BYTE    *p;
  47.     void    *mh = NULL;
  48.     FILE    *file = NULL;
  49.     char    *errmsg = " ";
  50.     SHORT   i;
  51.  
  52.     if( !(file = fopen(filename, "r")) ) {
  53.     fail_and_return( "unable to open iff picture file for read\n" );
  54.     }
  55.     if( getId(file) != ID_FORM ) {
  56.     fail_and_return( "not IFF format\n" );
  57.     }
  58.     getLen( file );
  59.     if( getId(file) != ID_ILBM ) {
  60.     fail_and_return( "not ILBM format\n" );
  61.     }
  62.     for( ;; ) {
  63.     getChunk( &id, &len, file );
  64.     if( ferror(file) || feof(file) ) {
  65.         fail_and_return( badFileMsg );
  66.     }
  67.     switch( id ) {
  68.       case ID_BMHD:
  69.         pic = chainAllocMem( &mh, (ULONG)sizeof(PICTURE),
  70.                     MEMF_PUBLIC | MEMF_CLEAR );
  71.         if( !pic ) {
  72.            fail_and_return( noMemMsg );
  73.         }
  74.         getBMH( &pic->bmh, file );
  75.         if( len & 1 ) {
  76.         GET(file);
  77.         }
  78.         break;
  79.       case ID_CMAP:
  80.         if( getLut(pic, len, file) ) {
  81.         fail_and_return( "unable to get color table\n" );
  82.         }
  83.         break;
  84.       case ID_BODY:
  85.         if( !pic ) {
  86.         fail_and_return( "didn't find BMHD chunk\n" );
  87.         return( NULL );
  88.         }
  89.         switch( pic->bmh.masking ) {
  90.           case mskNone:
  91.           case mskLasso:
  92.           case mskHasTranCol:
  93.         break;
  94.           default:
  95.         printf("Error, unsupported masking type\n");
  96.         return( NULL );
  97.         } /* switch */
  98.  
  99.         pic->xsize = pic->bmh.w;
  100.         if( (pic->myflags = makeBM(pic, myflags)) == GBP_ERROR ) {
  101.         return( NULL );
  102.         }
  103.         switch( pic->bmh.compression ) {
  104.           case cmpNone:
  105.         if( getBody(pic->bm, pic->myflags, file) ) {
  106.             fail_and_return( "error in uncompressed body\n" );
  107.         }
  108.         break;
  109.           case cmpByteRun1:
  110.         if( getCmpBody(pic->bm, file) ) {
  111.             fail_and_return( "error in compressed body\n" );
  112.         }
  113.         break;
  114.           default:
  115.         fail_and_return( "unknown compression form\n" );
  116.         return( NULL );
  117.         } /* switch */
  118.         if( ferror(file) ) {
  119.         fail_and_return( badFileMsg );
  120.         }
  121.         pic->memhead = mh;
  122.         fclose( file );
  123.         return( pic );
  124.         break;
  125.       case ID_DEST:
  126.       case ID_SPRT:
  127.       case ID_CAMG:
  128.       case ID_CRNG:
  129.       case ID_CCRT:
  130.       default:        /* unimplemented chunk type */
  131.         skip( EVEN(len), file );
  132.         break;
  133.     } /* switch */
  134.     } /* for */
  135. failure_return: {}
  136.     if( Output() ) {
  137.     Write( Output(), errmsg, (ULONG)strlen(errmsg) );
  138.     }
  139.     if( mh ) {
  140.     chainFreeMem( mh );
  141.     }
  142.     if( file ) {
  143.     fclose( file );
  144.     }
  145.     return( NULL );
  146. } /* gimmePicture */
  147.  
  148.  
  149. static ULONG makeBM( pic, myflags )
  150.     register PICTURE    *pic;
  151.     ULONG        myflags;
  152. {
  153.     UBYTE *plane;
  154.  
  155.     if( !(pic->bm = AllocMem((ULONG)sizeof(struct BitMap), MEMF_PUBLIC)) ) {
  156.     return( GBP_ERROR );
  157.     }
  158.     InitBitMap( pic->bm, (long) pic->bmh.nPlanes, (long) pic->bmh.w,
  159.             (long) pic->bmh.h );
  160.     return( gimmeBitPlanes(pic->bm, myflags) );
  161. } /* makeBM */
  162.  
  163.  
  164. short getRidOfPicture( picture )
  165.     PICTURE   *picture;
  166. {
  167. #ifdef GIMME_WIMPY
  168.     if( picture ) {
  169.     return( -1 );
  170.     }
  171. #endif
  172.     if( picture->colormap.ColorTable ) {
  173.     FreeMem( picture->colormap.ColorTable,
  174.             (ULONG) picture->colormap.Count * sizeof(USHORT) );
  175.     }
  176.     if( picture->bm ) {
  177.     getRidOfBitPlanes( picture->bm, picture->myflags );
  178.     FreeMem( picture->bm, (ULONG)sizeof(struct BitMap) );
  179.     }
  180.     chainFreeMem( picture->memhead );
  181.     return( 0 );
  182. } /* getRidOfPicture */
  183.  
  184.  
  185. short positionPicture( rp, myflags, pic, minterm, x, y )
  186.     struct RastPort *rp;
  187.     ULONG        myflags;
  188.     PICTURE        *pic;
  189.     SHORT        minterm;
  190.     register SHORT  x, y;
  191. {
  192.     SHORT        left, top;
  193.     SHORT        width, height;
  194.     SHORT        temp;
  195.     struct BitMap   *bm;
  196.  
  197. #ifdef GIMME_WIMPY
  198.     if( !pic || !rp ) {
  199.     return( -1 );
  200.     }
  201. #endif
  202.     left = top = 0;
  203.     width = pic->bmh.w;
  204.     height = pic->bmh.h;
  205.     bm = rp->BitMap;
  206.     switch( myflags & GPT_XFLAGS ) {
  207.       case GPT_XCENTRE:
  208.     x -= width >> 1;
  209.     break;
  210.       case GPT_XRIGHT:
  211.     x -= width;
  212.     break;
  213.       case GPT_XLEFT:
  214.       default:
  215.     break;
  216.     } /* switch */
  217.     switch( myflags & GPT_YFLAGS ) {
  218.       case GPT_YBOTTOM:
  219.       case GPT_YBASELINE:
  220.     y -= height;
  221.     break;
  222.       case GPT_YCENTRE:
  223.       case GPT_YCENTREBASE:
  224.     y -= height >> 1;
  225.     break;
  226.       case GPT_YTOP:
  227.       default:
  228.     break;
  229.     } /* switch */
  230.     if( minterm != GIM_MINTERM_DEST ) {
  231.     if( x < 0 ) {
  232.         width += x;
  233.         left -= x;
  234.         x = 0;
  235.     } else if( (temp = x + width - (bm->BytesPerRow << 3)) > 0 ) {
  236.         width -= temp;
  237.     }
  238.     if( y < 0 ) {
  239.         height += y;
  240.         top -= y;
  241.         y = 0;
  242.     } else if( (temp = y + height - bm->Rows) > 0 ) {
  243.         height -= temp;
  244.     }
  245.     if( width > 0 && height > 0 ) {
  246.         BltBitMapRastPort( pic->bm, (long) left, (long) top, rp,
  247.                 (long) x, (long) y,
  248.                 (long) width, (long) height, (long) minterm );
  249.     }
  250.     }
  251.     return( 0 );
  252. } /* positionPicture */
  253.  
  254.  
  255. short usePictureColors( pic, screen )
  256.     register PICTURE *pic;
  257.     struct Screen    *screen;
  258. {
  259. #ifdef GIMME_WIMPY
  260.     if( !pic || !screen ) {
  261.     return( -1 );
  262.     }
  263. #endif
  264.     return( setColors(screen, pic->colormap.ColorTable,
  265.             (SHORT) pic->colormap.Count) );
  266. } /* usePictureColors */
  267.  
  268.  
  269. /* read an IFF Id */
  270. static LONG getLong( file )
  271.     FILE    *file;
  272. {
  273.     register UBYTE  p[4];
  274.  
  275.     p[0] = GET(file);
  276.     p[1] = GET(file);
  277.     p[2] = GET(file);
  278.     p[3] = GET(file);
  279.     return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
  280. } /* getLong */
  281.  
  282.  
  283. /* read an IFF chunk header */
  284. static getChunk( id, len, file )
  285.     LONG    *id, *len;
  286.     FILE    *file;
  287. {
  288.     *id = getId( file );
  289.     *len = getLen( file );
  290. } /* getChunk */
  291.  
  292.  
  293. /* get len bytes from the file and put them into memory */
  294. static memget( p, len, file )
  295.     UBYTE   *p;
  296.     LONG    len;
  297.     FILE    *file;
  298. {
  299.     for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
  300.     fread( p, (int) (len & 0x07fffL), 1, file );
  301.     } /* for */
  302. } /* memget */
  303.  
  304.  
  305. /* get a word */
  306. static WORD getWord( file )
  307.     FILE    *file;
  308. {
  309.     WORD    v;
  310.  
  311.     v = GET(file) << 8;
  312.     return( v | GET(file) );
  313. } /* getWord */
  314.  
  315.  
  316. static int getCmpBody( bm, file )
  317.     struct BitMap   *bm;
  318.     FILE        *file;
  319. {
  320.     register short  x;
  321.     short        y, pl;
  322.     UBYTE        *plane;
  323.     UBYTE        run_len, verb_len, run_byte;
  324.     BYTE        v;
  325.     register BYTE   mybyte;
  326.  
  327.     verb_len = run_len = 0;
  328.     /* note: the bit-planes should be clear already */
  329.     for( y = 0; y < bm->Rows; ++y ) {
  330.     for( pl = 0; pl < bm->Depth; ++pl ) {
  331.         plane = bm->Planes[pl] + y * bm->BytesPerRow;
  332.         for( x = 0; x < bm->BytesPerRow; ++x ) {
  333.         if( run_len ) {
  334.             --run_len;
  335.             mybyte = run_byte;
  336.         } else if( verb_len ) {
  337.             --verb_len;
  338.             mybyte = GET(file);
  339.         } else if( (v = GET(file)) >= 0 ) {
  340.             verb_len = v;
  341.             mybyte = GET(file);
  342.         } else {
  343.             run_len = -v;
  344.             mybyte = run_byte = GET(file);
  345.         }
  346.         plane[x] = mybyte;
  347.         } /* for */
  348.     } /* for */
  349.     } /* for */
  350.     return( 0 );
  351. } /* getCmpBody */
  352.  
  353.  
  354. static int getBody( bm, flags, file )
  355.     register struct BitMap *bm;
  356.     ULONG   flags;
  357.     FILE    *file;
  358. {
  359.     register short  i;
  360.  
  361.     if( flags & GBP_CONTIGUOUS ) {
  362.     memget( bm->Planes[0], (ULONG)(bm->Depth) * bm->Rows * bm->BytesPerRow,
  363.             file );
  364.     } else {
  365.     for( i = 0; i < bm->Depth; ++i ) {
  366.         memget( bm->Planes[i], (ULONG)(bm->Rows) * bm->BytesPerRow, file );
  367.     } /* for */
  368.     }
  369.     return( 0 );
  370. } /* getBody */
  371.  
  372.  
  373. static int getLut( pic, len, file )
  374.     PICTURE *pic;
  375.     LONG    len;
  376.     FILE    *file;
  377. {
  378.     SHORT   i, ncols;
  379.     USHORT  red, green, blue;
  380.     USHORT   *lut;
  381.  
  382.     pic->colormap.Flags = pic->colormap.Type = 0;
  383.     ncols = len / 3;
  384.     lut = (USHORT *) AllocMem( (ULONG) ncols * sizeof(USHORT), MEMF_PUBLIC );
  385.     if( !lut ) {
  386.     return( -1 );
  387.     }
  388.     for( i = 0; i < ncols; ++i ) {
  389.     red = GET(file) >> 4;
  390.     green = GET(file) >> 4;
  391.     blue = GET(file) >> 4;
  392.     lut[i] = (red << 8) | (green << 4) | blue;
  393.     } /* for */
  394.     if( len & 1 ) {
  395.     GET(file);
  396.     }
  397.     pic->colormap.Count = ncols;
  398.     pic->colormap.ColorTable = (APTR) lut;
  399.     return( 0 );
  400. } /* getLut */
  401.