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

  1. /* libpnm3.c - pnm utility library part 3
  2. **
  3. ** Copyright (C) 1989, 1991 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. #include "ppm.h"
  16. #include "libppm.h"
  17.  
  18. #include "pgm.h"
  19. #include "libpgm.h"
  20.  
  21. #include "pbm.h"
  22. #include "libpbm.h"
  23.  
  24. #if __STDC__
  25. xel
  26. pnm_backgroundxel( xel** xels, int cols, int rows, xelval maxval, int format )
  27. #else /*__STDC__*/
  28. xel
  29. pnm_backgroundxel( xels, cols, rows, maxval, format )
  30.     xel** xels;
  31.     int cols, rows, format;
  32.     xelval maxval;
  33. #endif /*__STDC__*/
  34.     {
  35.     xel bgxel, ul, ur, ll, lr;
  36.  
  37.     /* Guess a good background value. */
  38.     ul = xels[0][0];
  39.     ur = xels[0][cols-1];
  40.     ll = xels[rows-1][0];
  41.     lr = xels[rows-1][cols-1];
  42.  
  43.     /* First check for three corners equal. */
  44.     if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, ll ) )
  45.     bgxel = ul;
  46.     else if ( PNM_EQUAL( ul, ur ) && PNM_EQUAL( ur, lr ) )
  47.     bgxel = ul;
  48.     else if ( PNM_EQUAL( ul, ll ) && PNM_EQUAL( ll, lr ) )
  49.     bgxel = ul;
  50.     else if ( PNM_EQUAL( ur, ll ) && PNM_EQUAL( ll, lr ) )
  51.     bgxel = ur;
  52.     /* Nope, check for two corners equal. */
  53.     else if ( PNM_EQUAL( ul, ur ) || PNM_EQUAL( ul, ll ) ||
  54.           PNM_EQUAL( ul, lr ) )
  55.     bgxel = ul;
  56.     else if ( PNM_EQUAL( ur, ll ) || PNM_EQUAL( ur, lr ) )
  57.     bgxel = ur;
  58.     else if ( PNM_EQUAL( ll, lr ) )
  59.     bgxel = ll;
  60.     else
  61.     {
  62.     /* Nope, we have to average the four corners.  This breaks the
  63.     ** rules of pnm, but oh well.  Let's try to do it portably. */
  64.     switch ( PNM_FORMAT_TYPE(format) )
  65.         {
  66.         case PPM_TYPE:
  67.         PPM_ASSIGN( bgxel,
  68.         PPM_GETR(ul) + PPM_GETR(ur) + PPM_GETR(ll) + PPM_GETR(lr) / 4,
  69.         PPM_GETG(ul) + PPM_GETG(ur) + PPM_GETG(ll) + PPM_GETG(lr) / 4,
  70.         PPM_GETB(ul) + PPM_GETB(ur) + PPM_GETB(ll) + PPM_GETB(lr) / 4 );
  71.         break;
  72.  
  73.         case PGM_TYPE:
  74.         {
  75.         gray gul, gur, gll, glr;
  76.         gul = (gray) PNM_GET1( ul );
  77.         gur = (gray) PNM_GET1( ur );
  78.         gll = (gray) PNM_GET1( ll );
  79.         glr = (gray) PNM_GET1( lr );
  80.         PNM_ASSIGN1( bgxel, ( ( gul + gur + gll + glr ) / 4 ) );
  81.         break;
  82.         }
  83.  
  84.         case PBM_TYPE:
  85.         pm_error(
  86.         "pnm_backgroundxel: four bits no two of which equal each other??" );
  87.  
  88.         default:
  89.         pm_error( "can't happen" );
  90.         }
  91.     }
  92.  
  93.     return bgxel;
  94.     }
  95.  
  96. #if __STDC__
  97. xel
  98. pnm_backgroundxelrow( xel* xelrow, int cols, xelval maxval, int format )
  99. #else /*__STDC__*/
  100. xel
  101. pnm_backgroundxelrow( xelrow, cols, maxval, format )
  102.     xel* xelrow;
  103.     int cols, format;
  104.     xelval maxval;
  105. #endif /*__STDC__*/
  106.     {
  107.     xel bgxel, l, r;
  108.  
  109.     /* Guess a good background value. */
  110.     l = xelrow[0];
  111.     r = xelrow[cols-1];
  112.  
  113.     /* First check for both corners equal. */
  114.     if ( PNM_EQUAL( l, r ) )
  115.     bgxel = l;
  116.     else
  117.     {
  118.     /* Nope, we have to average the two corners.  This breaks the
  119.     ** rules of pnm, but oh well.  Let's try to do it portably. */
  120.     switch ( PNM_FORMAT_TYPE(format) )
  121.         {
  122.         case PPM_TYPE:
  123.         PPM_ASSIGN( bgxel, PPM_GETR(l) + PPM_GETR(r) / 2,
  124.         PPM_GETG(l) + PPM_GETG(r) / 2, PPM_GETB(l) + PPM_GETB(r) / 2 );
  125.         break;
  126.  
  127.         case PGM_TYPE:
  128.         {
  129.         gray gl, gr;
  130.         gl = (gray) PNM_GET1( l );
  131.         gr = (gray) PNM_GET1( r );
  132.         PNM_ASSIGN1( bgxel, ( ( gl + gr ) / 2 ) );
  133.         break;
  134.         }
  135.  
  136.         case PBM_TYPE:
  137.         {
  138.         int col, blacks;
  139.  
  140.         /* One black, one white.  Gotta count. */
  141.         for ( col = 0, blacks = 0; col < cols; ++col )
  142.         {
  143.         if ( PNM_GET1( xelrow[col] ) == 0 )
  144.             ++blacks;
  145.         }
  146.         if ( blacks >= cols / 2 )
  147.         PNM_ASSIGN1( bgxel, 0 );
  148.         else
  149.         PNM_ASSIGN1( bgxel, pnm_pbmmaxval );
  150.         break;
  151.         }
  152.  
  153.         default:
  154.         pm_error( "can't happen" );
  155.         }
  156.     }
  157.  
  158.     return bgxel;
  159.     }
  160.  
  161. #if __STDC__
  162. xel
  163. pnm_whitexel( xelval maxval, int format )
  164. #else /*__STDC__*/
  165. xel
  166. pnm_whitexel( maxval, format )
  167.     xelval maxval;
  168.     int format;
  169. #endif /*__STDC__*/
  170.     {
  171.     xel x;
  172.  
  173.     switch ( PNM_FORMAT_TYPE(format) )
  174.     {
  175.     case PPM_TYPE:
  176.     PPM_ASSIGN( x, maxval, maxval, maxval );
  177.     break;
  178.  
  179.     case PGM_TYPE:
  180.     PNM_ASSIGN1( x, maxval );
  181.     break;
  182.  
  183.     case PBM_TYPE:
  184.     PNM_ASSIGN1( x, pnm_pbmmaxval );
  185.     break;
  186.  
  187.     default:
  188.     pm_error( "can't happen" );
  189.     }
  190.  
  191.     return x;
  192.     }
  193.  
  194. #if __STDC__
  195. xel
  196. pnm_blackxel( xelval maxval, int format )
  197. #else /*__STDC__*/
  198. xel
  199. pnm_blackxel( maxval, format )
  200.     xelval maxval;
  201.     int format;
  202. #endif /*__STDC__*/
  203.     {
  204.     xel x;
  205.  
  206.     switch ( PNM_FORMAT_TYPE(format) )
  207.     {
  208.     case PPM_TYPE:
  209.     PPM_ASSIGN( x, 0, 0, 0 );
  210.     break;
  211.  
  212.     case PGM_TYPE:
  213.     PNM_ASSIGN1( x, (xelval) 0 );
  214.     break;
  215.  
  216.     case PBM_TYPE:
  217.     PNM_ASSIGN1( x, (xelval) 0 );
  218.     break;
  219.  
  220.     default:
  221.     pm_error( "can't happen" );
  222.     }
  223.  
  224.     return x;
  225.     }
  226.  
  227. #if __STDC__
  228. void
  229. pnm_invertxel( xel* xP, xelval maxval, int format )
  230. #else /*__STDC__*/
  231. void
  232. pnm_invertxel( xP, maxval, format )
  233.     xel* xP;
  234.     xelval maxval;
  235.     int format;
  236. #endif /*__STDC__*/
  237.     {
  238.     switch ( PNM_FORMAT_TYPE(format) )
  239.     {
  240.     case PPM_TYPE:
  241.     PPM_ASSIGN(
  242.         *xP, maxval - PPM_GETR( *xP ),
  243.         maxval - PPM_GETG( *xP ), maxval - PPM_GETB( *xP ) );
  244.     break;
  245.  
  246.     case PGM_TYPE:
  247.     PNM_ASSIGN1( *xP, (gray) maxval - (gray) PNM_GET1( *xP ) );
  248.     break;
  249.  
  250.     case PBM_TYPE:
  251.     PNM_ASSIGN1( *xP, ( PNM_GET1( *xP ) == 0 ) ? pnm_pbmmaxval : 0 );
  252.     break;
  253.  
  254.     default:
  255.     pm_error( "can't happen" );
  256.     }
  257.     }
  258.  
  259. #if __STDC__
  260. void
  261. pnm_promoteformat( xel** xels, int cols, int rows, xelval maxval, int format, xelval newmaxval, int newformat )
  262. #else /*__STDC__*/
  263. void
  264. pnm_promoteformat( xels, cols, rows, maxval, format, newmaxval, newformat )
  265.     xel** xels;
  266.     xelval maxval, newmaxval;
  267.     int cols, rows, format, newformat;
  268. #endif /*__STDC__*/
  269.     {
  270.     int row;
  271.  
  272.     for ( row = 0; row < rows; ++row )
  273.     pnm_promoteformatrow(
  274.         xels[row], cols, maxval, format, newmaxval, newformat );
  275.     }
  276.  
  277. #if __STDC__
  278. void
  279. pnm_promoteformatrow( xel* xelrow, int cols, xelval maxval, int format, xelval newmaxval, int newformat )
  280. #else /*__STDC__*/
  281. void
  282. pnm_promoteformatrow( xelrow, cols, maxval, format, newmaxval, newformat )
  283.     xel* xelrow;
  284.     xelval maxval, newmaxval;
  285.     int cols, format, newformat;
  286. #endif /*__STDC__*/
  287.     {
  288.     register int col;
  289.     register xel* xP;
  290.  
  291.     if ( ( PNM_FORMAT_TYPE(format) == PPM_TYPE &&
  292.        ( PNM_FORMAT_TYPE(newformat) == PGM_TYPE ||
  293.          PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) ) ||
  294.      ( PNM_FORMAT_TYPE(format) == PGM_TYPE &&
  295.        PNM_FORMAT_TYPE(newformat) == PBM_TYPE ) )
  296.     pm_error( "pnm_promoteformatrow: can't promote downwards!" );
  297.  
  298.     /* Are we promoting to the same type? */
  299.     if ( PNM_FORMAT_TYPE(format) == PNM_FORMAT_TYPE(newformat) )
  300.     {
  301.     if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
  302.         return;
  303.     if ( newmaxval < maxval )
  304.         pm_error(
  305.        "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" );
  306.     if ( newmaxval == maxval )
  307.         return;
  308.     /* Increase maxval. */
  309.     switch ( PNM_FORMAT_TYPE(format) )
  310.         {
  311.         case PGM_TYPE:
  312.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  313.         PNM_ASSIGN1(
  314.             *xP, (int) PNM_GET1(*xP) * newmaxval / maxval );
  315.         break;
  316.  
  317.         case PPM_TYPE:
  318.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  319.         PPM_DEPTH( *xP, *xP, maxval, newmaxval );
  320.         break;
  321.  
  322.         default:
  323.         pm_error( "shouldn't happen" );
  324.         }
  325.     return;
  326.     }
  327.  
  328.     /* We must be promoting to a higher type. */
  329.     switch ( PNM_FORMAT_TYPE(format) )
  330.     {
  331.     case PBM_TYPE:
  332.     switch ( PNM_FORMAT_TYPE(newformat) )
  333.         {
  334.         case PGM_TYPE:
  335.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  336.         if ( PNM_GET1(*xP) == 0 )
  337.             PNM_ASSIGN1( *xP, 0 );
  338.         else
  339.             PNM_ASSIGN1( *xP, newmaxval );
  340.         break;
  341.  
  342.         case PPM_TYPE:
  343.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  344.         if ( PNM_GET1(*xP) == 0 )
  345.             PPM_ASSIGN( *xP, 0, 0, 0 );
  346.         else
  347.             PPM_ASSIGN( *xP, newmaxval, newmaxval, newmaxval );
  348.         break;
  349.  
  350.         default:
  351.         pm_error( "can't happen" );
  352.         }
  353.     break;
  354.  
  355.     case PGM_TYPE:
  356.     switch ( PNM_FORMAT_TYPE(newformat) )
  357.         {
  358.         case PPM_TYPE:
  359.         if ( newmaxval < maxval )
  360.         pm_error(
  361.        "pnm_promoteformatrow: can't decrease maxval - try using pnmdepth" );
  362.         if ( newmaxval == maxval )
  363.         {
  364.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  365.             PPM_ASSIGN(
  366.             *xP, PNM_GET1(*xP), PNM_GET1(*xP), PNM_GET1(*xP) );
  367.         }
  368.         else
  369.         { /* Increase maxval. */
  370.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  371.             PPM_ASSIGN(
  372.             *xP, (int) PNM_GET1(*xP) * newmaxval / maxval,
  373.             (int) PNM_GET1(*xP) * newmaxval / maxval,
  374.             (int) PNM_GET1(*xP) * newmaxval / maxval );
  375.         }
  376.         break;
  377.  
  378.         default:
  379.         pm_error( "can't happen" );
  380.         }
  381.     break;
  382.  
  383.     default:
  384.     pm_error( "can't happen" );
  385.     }
  386.     }
  387.