home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 309.lha / PBM_PLUS / ppm / ilbmtoppm.c < prev    next >
C/C++ Source or Header  |  1980-12-04  |  9KB  |  354 lines

  1. /* ilbmtoppm.c - read an Amiga IFF ILBM file and produce a portable pixmap
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include "ppm.h"
  15. #include "ilbm.h"
  16.  
  17. main( argc, argv )
  18. int argc;
  19. char *argv[];
  20.     {
  21.     FILE *ifd;
  22.     pixel *pixelrow, *colormap = 0;
  23.     int argn, rows, cols = 0, row, col, colors, i, j, r, g, b, byte, bytes;
  24.     pixval maxval;
  25.     char iffid[5];
  26.     unsigned char *body = 0, *bp, *ubp, *rawrow, *runbuf;
  27.     long formsize, bytesread, chunksize, viewportmodes = 0;
  28.     int nPlanes, masking, compression, xAsp, yAsp, ham, hammask, allPlanes;
  29.     unsigned char get_byte();
  30.     short get_big_short();
  31.     long get_big_long();
  32.  
  33.     pm_progname = argv[0];
  34.  
  35.     argn = 1;
  36.  
  37.     if ( argn < argc )
  38.     {
  39.     ifd = pm_openr( argv[argn] );
  40.     argn++;
  41.     }
  42.     else
  43.     ifd = stdin;
  44.  
  45.     if ( argn != argc )
  46.     pm_usage( "[ilbmfile]" );
  47.  
  48.     /* Read in the ILBM file. */
  49.     iffid[4] = '\0';
  50.     getfourchars( ifd, iffid );
  51.     if ( strcmp( iffid, "FORM" ) != 0 )
  52.     pm_error( "input is not a FORM type IFF file", 0,0,0,0,0 );
  53.     formsize = get_big_long( ifd );
  54.     getfourchars( ifd, iffid );
  55.     if ( strcmp( iffid, "ILBM" ) != 0 )
  56.     pm_error( "input is not an ILBM type FORM IFF file", 0,0,0,0,0 );
  57.     bytesread = 12;
  58.  
  59.     /* Main loop, parsing the IFF FORM. */
  60.     while ( bytesread < formsize )
  61.     {
  62.     getfourchars( ifd, iffid );
  63.     chunksize = get_big_long( ifd );
  64.     bytesread += 8;
  65.  
  66.     if ( body != 0 )
  67.         {
  68.         fprintf(
  69.         stderr, "%s: \"%s\" chunk found after BODY chunk -- skipping\n",
  70.         argv[0], iffid );
  71.         for ( i = 0; i < chunksize; i++ )
  72.         (void) get_byte( ifd );
  73.         }
  74.     else if ( strcmp( iffid, "BMHD" ) == 0 )
  75.         {
  76.         cols = get_big_short( ifd );
  77.         rows = get_big_short( ifd );
  78.         (void) get_big_short( ifd );    /* x */
  79.         (void) get_big_short( ifd );    /* y */
  80.         nPlanes = get_byte( ifd );
  81.         masking = get_byte( ifd );
  82.         compression = get_byte( ifd );
  83.         (void) get_byte( ifd );    /* pad1 */
  84.         (void) get_big_short( ifd );    /* transparentColor */
  85.         xAsp = get_byte( ifd );
  86.         yAsp = get_byte( ifd );
  87.         (void) get_big_short( ifd );    /* pageWidth */
  88.         (void) get_big_short( ifd );    /* pageHeight */
  89.         }
  90.     else if ( strcmp( iffid, "CMAP" ) == 0 )
  91.         {
  92.         colors = chunksize / 3;
  93.         if ( colors > 0 )
  94.         {
  95.         colormap = ppm_allocrow( colors );
  96.         for ( i = 0; i < colors; i++ )
  97.             {
  98.             r = get_byte( ifd );
  99.             g = get_byte( ifd );
  100.             b = get_byte( ifd );
  101.             PPM_ASSIGN( colormap[i], r, g, b );
  102.             }
  103.         if ( colors * 3 != chunksize )
  104.             (void) get_byte( ifd );
  105.         }
  106.         }
  107.     else if ( strcmp( iffid, "CAMG" ) == 0 )
  108.         {
  109.         viewportmodes = get_big_long( ifd );
  110.         }
  111.     else if ( strcmp( iffid, "BODY" ) == 0 )
  112.         {
  113.         body = (unsigned char *) malloc( chunksize );
  114.         if ( body == 0 )
  115.         pm_error( "out of memory", 0,0,0,0,0 );
  116.         if ( fread( body, 1, chunksize, ifd ) != chunksize )
  117.         pm_error( "premature EOF reading BODY chunk", 0,0,0,0,0 );
  118.         }
  119.     else if ( strcmp( iffid, "GRAB" ) == 0 ||
  120.               strcmp( iffid, "DEST" ) == 0 ||
  121.               strcmp( iffid, "SPRT" ) == 0 ||
  122.               strcmp( iffid, "CRNG" ) == 0 ||
  123.               strcmp( iffid, "CCRT" ) == 0 ||
  124.               strcmp( iffid, "DPPV" ) == 0 )
  125.         {
  126.         for ( i = 0; i < chunksize; i++ )
  127.         (void) get_byte( ifd );
  128.         }
  129.     else
  130.         {
  131.         fprintf(
  132.         stderr, "%s: unknown chunk type \"%s\" -- skipping\n",
  133.         argv[0], iffid );
  134.         for ( i = 0; i < chunksize; i++ )
  135.         (void) get_byte( ifd );
  136.         }
  137.  
  138.     bytesread += chunksize;
  139.     }
  140.  
  141.     pm_close( ifd );
  142.  
  143.     /* Done reading.  Now interpret what we got. */
  144.     if ( cols == 0 )
  145.     pm_error( "no BMHD chunk found", 0,0,0,0,0 );
  146.     if ( body == 0 )
  147.     pm_error( "no BODY chunk found", 0,0,0,0,0 );
  148.     if ( xAsp != yAsp )
  149.     fprintf(
  150.         stderr,
  151.         "(Warning: non-square pixels; to fix do a 'ppmscale -%cscale %g'.)\n",
  152.         xAsp > yAsp ? 'x' : 'y',
  153.         xAsp > yAsp ? (float) xAsp / yAsp : (float) yAsp / xAsp );
  154.     if ( viewportmodes & vmHAM )
  155.     {
  156.     ham = 1;
  157.     hammask = ( 1 << ( nPlanes - 2 ) ) - 1;
  158.     maxval = ( 1 << ( nPlanes - 2 ) ) - 1;
  159.     if ( colormap != 0 )
  160.         for ( i = 0; i < colors; i++ )
  161.         {
  162.         r = PPM_GETR( colormap[i] ) >> ( 10 - nPlanes );
  163.         g = PPM_GETG( colormap[i] ) >> ( 10 - nPlanes );
  164.         b = PPM_GETB( colormap[i] ) >> ( 10 - nPlanes );
  165.         PPM_ASSIGN( colormap[i], r, g, b );
  166.         }
  167.     }
  168.     else
  169.     {
  170.     ham = 0;
  171.     if ( colormap != 0 )
  172.         maxval = 255;        /* colormap contains bytes */
  173.     else
  174.         maxval = ( 1 << nPlanes ) - 1;
  175.     }
  176.     if ( viewportmodes & vmEXTRA_HALFBRITE )
  177.     {
  178.     pixel *tempcolormap;
  179.     
  180.     tempcolormap = ppm_allocrow( colors * 2 );
  181.     for ( i = 0; i < colors; i++ )
  182.         {
  183.         tempcolormap[i] = colormap[i];
  184.         PPM_ASSIGN(
  185.         tempcolormap[colors + i], PPM_GETR(colormap[i]) / 2,
  186.         PPM_GETG(colormap[i]) / 2, PPM_GETB(colormap[i]) / 2 );
  187.         }
  188.     ppm_freerow( colormap );
  189.     colormap = tempcolormap;
  190.     colors *= 2;
  191.     }
  192.     if ( colormap == 0 )
  193.     fprintf(
  194.         stderr, "(No colormap -- interpreting values as grayscale.)\n" );
  195.     allPlanes = nPlanes + ( masking == mskHasMask ? 1 : 0 );
  196.  
  197.     ppm_writeppminit( stdout, cols, rows, maxval );
  198.     pixelrow = ppm_allocrow( cols );
  199.     rawrow = (unsigned char *) malloc( cols );
  200.     if ( rawrow == 0 )
  201.     pm_error( "out of memory", 0,0,0,0,0 );
  202.     runbuf = (unsigned char *) malloc( RowBytes( cols ) );
  203.     if ( runbuf == 0 )
  204.     pm_error( "out of memory", 0,0,0,0,0 );
  205.  
  206.     bp = body;
  207.     for ( row = 0; row < rows; row++ )
  208.     {
  209.     /* Extract rawrow from the image. */
  210.     for ( col = 0; col < cols; col++ )
  211.         rawrow[col] = 0;
  212.     for ( i = 0; i < allPlanes; i++ )
  213.         {
  214.         switch ( compression )
  215.         {
  216.         case cmpNone:
  217.         ubp = bp;
  218.         bp += RowBytes( cols );
  219.         break;
  220.  
  221.         case cmpByteRun1:
  222.         ubp = runbuf;
  223.         bytes = RowBytes( cols );
  224.         do
  225.             {
  226.             byte = *bp++;
  227.             if ( byte <= 127 )
  228.             for ( j = byte, bytes -= j + 1; j >= 0; j-- )
  229.                 *ubp++ = *bp++;
  230.             else if ( byte != 128 )
  231.             for ( j = 256 - byte, bytes -= j + 1, byte = *bp++;
  232.                   j >= 0; j-- )
  233.                 *ubp++ = byte;
  234.             }
  235.         while ( bytes > 0 );
  236.         if ( bytes < 0 )
  237.             pm_error( "error doing ByteRun decompression", 0,0,0,0,0 );
  238.         ubp = runbuf;
  239.         break;
  240.  
  241.         default:
  242.         pm_error( "unknown compression type", 0,0,0,0,0 );
  243.         }
  244.  
  245.         if ( i >= nPlanes )
  246.         continue;    /* ignore mask plane */
  247.  
  248.         for ( col = 0; col < cols; col++ )
  249.         if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  250.             rawrow[col] |= 1 << i;
  251.         }
  252.  
  253.     /* Interpret rawrow into pixels. */
  254.     r = g = b = 0;
  255.     for ( col = 0; col < cols; col++ )
  256.         if ( ham )
  257.         { /* HAM mode. */
  258.         switch ( ( rawrow[col] >> nPlanes - 2 ) & 0x3 )
  259.             {
  260.             case 0:
  261.             if ( colormap != 0 && colors >= maxval )
  262.             pixelrow[col] = colormap[rawrow[col] & hammask];
  263.             else
  264.             PPM_ASSIGN(
  265.                 pixelrow[col], rawrow[col] & hammask,
  266.                 rawrow[col] & hammask, rawrow[col] & hammask );
  267.             r = PPM_GETR( pixelrow[col] );
  268.             g = PPM_GETG( pixelrow[col] );
  269.             b = PPM_GETB( pixelrow[col] );
  270.             break;
  271.  
  272.             case 1:
  273.             b = rawrow[col] & hammask;
  274.             PPM_ASSIGN( pixelrow[col], r, g, b );
  275.             break;
  276.  
  277.             case 2:
  278.             r = rawrow[col] & hammask;
  279.             PPM_ASSIGN( pixelrow[col], r, g, b );
  280.             break;
  281.  
  282.             case 3:
  283.             g = rawrow[col] & hammask;
  284.             PPM_ASSIGN( pixelrow[col], r, g, b );
  285.             break;
  286.  
  287.             default:
  288.             pm_error( "impossible HAM code", 0,0,0,0,0 );
  289.             }
  290.         }
  291.         else if ( colormap != 0 )
  292.         /* Non-HAM colormapped. */
  293.         pixelrow[col] = colormap[rawrow[col]];
  294.         else
  295.         /* Non-HAM direct -- weird. */
  296.         PPM_ASSIGN(
  297.             pixelrow[col], rawrow[col], rawrow[col], rawrow[col] );
  298.  
  299.     /* And write out the row. */
  300.     ppm_writeppmrow( stdout, pixelrow, cols, maxval );
  301.     }
  302.  
  303.     exit( 0 );
  304.     }
  305.  
  306. unsigned char
  307. get_byte( f )
  308. FILE *f;
  309.     {
  310.     int i;
  311.  
  312.     i = getc( f );
  313.     if ( i == EOF )
  314.     pm_error( "premature EOF", 0,0,0,0,0 );
  315.  
  316.     return (unsigned char) i;
  317.     }
  318.  
  319. getfourchars( f, fourchars )
  320. FILE *f;
  321. char fourchars[4];
  322.     {
  323.     fourchars[0] = get_byte( f );
  324.     fourchars[1] = get_byte( f );
  325.     fourchars[2] = get_byte( f );
  326.     fourchars[3] = get_byte( f );
  327.     }
  328.  
  329. short
  330. get_big_short( f )
  331. FILE *f;
  332.     {
  333.     short s;
  334.  
  335.     s = get_byte( f ) << 8;
  336.     s |= get_byte( f );
  337.  
  338.     return s;
  339.     }
  340.  
  341. long
  342. get_big_long( f )
  343. FILE *f;
  344.     {
  345.     long l;
  346.  
  347.     l = get_byte( f ) << 24;
  348.     l |= get_byte( f ) << 16;
  349.     l |= get_byte( f ) << 8;
  350.     l |= get_byte( f );
  351.  
  352.     return l;
  353.     }
  354.