home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / pnm / pnmcrop.c < prev    next >
C/C++ Source or Header  |  1993-10-06  |  4KB  |  172 lines

  1. /* pnmcrop.c - crop a portable anymap
  2. **
  3. ** Copyright (C) 1988 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 "pnm.h"
  14.  
  15. #define LEFT 1
  16. #define RIGHT 2
  17. #define TOP 4
  18. #define BOTTOM 8
  19.  
  20. int
  21. main( argc, argv )
  22.     int argc;
  23.     char* argv[];
  24.     {
  25.     FILE* ifp;
  26.     xel** xels;
  27.     register xel* xP;
  28.     xel background;
  29.     xelval maxval;
  30.     int argn, format, backdefault, backblack;
  31.     int rows, cols, row, col, newrows, newcols;
  32.     int top, bottom, left, right;
  33.     int which;
  34.     char *usage = "[-white|-black] [-left] [-right] [-top] [-bottom] [pnmfile]";
  35.  
  36.     pnm_init( &argc, argv );
  37.  
  38.     argn = 1;
  39.     backdefault = 1;
  40.     which = 0;
  41.  
  42.     /* Check for flags. */
  43.     if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  44.     {
  45.     if ( pm_keymatch( argv[argn], "-white", 2 ) )
  46.         {
  47.         backdefault = 0;
  48.         backblack = 0;
  49.         }
  50.     else if ( pm_keymatch( argv[argn], "-black", 2 ) )
  51.         {
  52.         backdefault = 0;
  53.         backblack = 1;
  54.         }
  55.     else if ( pm_keymatch( argv[argn], "-left", 2 ) )
  56.         {
  57.         which |= LEFT;
  58.         }
  59.     else if ( pm_keymatch( argv[argn], "-right", 2 ) )
  60.         {
  61.         which |= RIGHT;
  62.         }
  63.     else if ( pm_keymatch( argv[argn], "-top", 2 ) )
  64.         {
  65.         which |= TOP;
  66.         }
  67.     else if ( pm_keymatch( argv[argn], "-bottom", 2 ) )
  68.         {
  69.         which |= BOTTOM;
  70.         }
  71.     else
  72.         pm_usage( usage );
  73.     ++argn;
  74.     }
  75.  
  76.     if ( argn != argc )
  77.     {
  78.     ifp = pm_openr( argv[argn] );
  79.     ++argn;
  80.     }
  81.     else
  82.     ifp = stdin;
  83.  
  84.     if ( argn != argc )
  85.     pm_usage( usage );
  86.  
  87.     xels = pnm_readpnm( ifp, &cols, &rows, &maxval, &format );
  88.     pm_close( ifp );
  89.  
  90.     if (!which)
  91.         which = LEFT|RIGHT|TOP|BOTTOM;
  92.  
  93.     if ( backdefault )
  94.     background = pnm_backgroundxel( xels, cols, rows, maxval, format );
  95.     else
  96.     if ( backblack )
  97.         background = pnm_blackxel( maxval, format );
  98.     else
  99.         background = pnm_whitexel( maxval, format );
  100.  
  101.     /* Find first non-background line. */
  102.     if (which & TOP) {
  103.        for ( top = 0; top < rows; top++ )
  104.      for ( col = 0, xP = xels[top]; col < cols; col++, xP++ )
  105.          if ( ! PNM_EQUAL( *xP, background ) )
  106.          goto gottop;
  107.     } else top = 0;
  108. gottop:
  109.  
  110.     /* Find last non-background line. */
  111.     if (which & BOTTOM) {
  112.        for ( bottom = rows - 1; bottom >= top; bottom-- )
  113.      for ( col = 0, xP = xels[bottom]; col < cols; col++, xP++ )
  114.          if ( ! PNM_EQUAL( *xP, background ) )
  115.          goto gotbottom;
  116.     } else bottom = rows - 1;
  117. gotbottom:
  118.  
  119.     /* Find first non-background column.  To avoid massive paging on
  120.     ** large anymaps, we use a different loop than the above two cases. */
  121.     if (which & LEFT) {
  122.        left = cols - 1;
  123.        for ( row = top; row <= bottom; row++ )
  124.        {
  125.        int thisleft;
  126.  
  127.        for ( thisleft = 0; thisleft < left; thisleft++ )
  128.            if ( ! PNM_EQUAL( xels[row][thisleft], background ) )
  129.            {
  130.            left = thisleft;
  131.            break;
  132.            }
  133.        }
  134.     } else left = 0;
  135.  
  136.     /* Find last non-background column.  Again, use row-major loop. */
  137.     if (which & RIGHT) {
  138.        right = left + 1;
  139.        for ( row = top; row <= bottom; row++ )
  140.        {
  141.        int thisright;
  142.  
  143.        for ( thisright = cols - 1; thisright > right; thisright-- )
  144.            if ( ! PNM_EQUAL( xels[row][thisright], background ) )
  145.            {
  146.            right = thisright;
  147.            break;
  148.            }
  149.        }
  150.     } else right = cols - 1;
  151.  
  152. #define ending(n) (((n) > 1) ? "s" : "")
  153.     if ( top > 0 )
  154.     pm_message( "cropping %d row%s off the top", top, ending(top), 0,0,0 );
  155.     if ( bottom < rows - 1 )
  156.     pm_message( "cropping %d row%s off the bottom", rows-1-bottom, ending(rows-1-bottom), 0,0,0 );
  157.     if ( left > 0 )
  158.     pm_message( "cropping %d col%s off the left", left, ending(left), 0,0,0 );
  159.     if ( right < cols - 1 )
  160.     pm_message( "cropping %d col%s off the right", cols-1-right, ending(cols-1-right), 0,0,0 );
  161.  
  162.     /* Now write out the new anymap. */
  163.     newcols = right - left + 1;
  164.     newrows = bottom - top + 1;
  165.     pnm_writepnminit( stdout, newcols, newrows, maxval, format, 0 );
  166.     for ( row = top; row <= bottom; row++ )
  167.     pnm_writepnmrow( stdout, &(xels[row][left]), newcols, maxval, format, 0 );
  168.     pm_close( stdout );
  169.  
  170.     exit( 0 );
  171.     }
  172.