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

  1. /* ppmrotate.c - read a portable pixmap and rotate it by some angle
  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 <math.h>
  15. #define M_PI    3.14159265358979323846
  16. #include "ppm.h"
  17.  
  18. #define SCALE 4096
  19. #define HALFSCALE 2048
  20.  
  21. main( argc, argv )
  22. int argc;
  23. char *argv[];
  24.     {
  25.     FILE *ifd;
  26.     pixel **pixels, **temp1pixels, **temp2pixels, *newpixelrow;
  27.     register pixel *pP, *npP;
  28.     pixel bgpixel, prevpixel, p;
  29.     int argn, rows, cols, newrows, tempcols, newcols, yshearjunk, x2shearjunk, row, col, new;
  30.     pixval maxval;
  31.     float fangle, xshearfac, yshearfac, new0;
  32.     int intnew0;
  33.     register long fracnew0, omfracnew0;
  34.     char *usage = "<angle> [ppmfile]";
  35.  
  36.     pm_progname = argv[0];
  37.  
  38.     argn = 1;
  39.  
  40.     if ( argn == argc )
  41.     pm_usage( usage );
  42.     if ( sscanf( argv[argn], "%g", &fangle ) != 1 )
  43.     pm_usage( usage );
  44.     argn++;
  45.     if ( fangle < -90.0 || fangle > 90.0 )
  46.     pm_error( "angle must be between -90 and 90", 0,0,0,0,0 );
  47.     fangle = fangle * M_PI / 180.0;    /* convert to radians */
  48.  
  49.     xshearfac = tan( fangle / 2.0 );
  50.     if ( xshearfac < 0.0 )
  51.     xshearfac = -xshearfac;
  52.     yshearfac = sin( fangle );
  53.     if ( yshearfac < 0.0 )
  54.     yshearfac = -yshearfac;
  55.  
  56.     if ( argn != argc )
  57.     {
  58.     ifd = pm_openr( argv[argn] );
  59.     argn++;
  60.     }
  61.     else
  62.     ifd = stdin;
  63.  
  64.     if ( argn != argc )
  65.     pm_usage( usage );
  66.  
  67.     ppm_pbmmaxval = 255;    /* use larger value for better results */
  68.     pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
  69.  
  70.     pm_close( ifd );
  71.  
  72.     tempcols = rows * xshearfac + cols + 0.999999;
  73.     yshearjunk = ( tempcols - cols ) * yshearfac;
  74.     newrows = tempcols * yshearfac + rows + 0.999999;
  75.     x2shearjunk = ( newrows - rows - yshearjunk ) * xshearfac;
  76.     newrows -= 2 * yshearjunk;
  77.     newcols = newrows * xshearfac + tempcols + 0.999999 - 2 * x2shearjunk;
  78.  
  79.     bgpixel = ppm_backgroundpixel( pixels, cols, rows );
  80.  
  81.     /* First shear X into temp1pixels. */
  82.     temp1pixels = ppm_allocarray( tempcols, rows );
  83.     for ( row = 0; row < rows; row++ )
  84.     {
  85.     for ( col = 0, npP = temp1pixels[row]; col < tempcols; col++, npP++ )
  86.         *npP = bgpixel;
  87.  
  88.     if ( fangle > 0 )
  89.         new0 = row * xshearfac;
  90.     else
  91.         new0 = ( rows - row ) * xshearfac;
  92.     intnew0 = (int) new0;
  93.     fracnew0 = ( new0 - intnew0 ) * SCALE;
  94.     omfracnew0 = SCALE - fracnew0;
  95.  
  96.     prevpixel = bgpixel;
  97.  
  98.     for ( col = 0, npP = &(temp1pixels[row][intnew0]), pP = pixels[row]; col < cols; col++, npP++, pP++ )
  99.         {
  100.         PPM_ASSIGN( *npP,
  101.         ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(*pP) + HALFSCALE ) / SCALE,
  102.         ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(*pP) + HALFSCALE ) / SCALE,
  103.         ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(*pP) + HALFSCALE ) / SCALE );
  104.         prevpixel = *pP;
  105.         }
  106.     if ( fracnew0 > 0 && intnew0 + cols < tempcols )
  107.         {
  108.         PPM_ASSIGN( *npP,
  109.         ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
  110.         ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
  111.         ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
  112.         }
  113.  
  114.     }
  115.     ppm_freearray( pixels, rows );
  116.  
  117.     /* Now inverse shear Y from temp1 into temp2. */
  118.     temp2pixels = ppm_allocarray( tempcols, newrows );
  119.     for ( col = 0; col < tempcols; col++ )
  120.     {
  121.     for ( row = 0; row < newrows; row++ )
  122.         temp2pixels[row][col] = bgpixel;
  123.  
  124.     if ( fangle > 0 )
  125.         new0 = ( tempcols - col ) * yshearfac;
  126.     else
  127.         new0 = col * yshearfac;
  128.     intnew0 = (int) new0;
  129.     fracnew0 = ( new0 - intnew0 ) * SCALE;
  130.     omfracnew0 = SCALE - fracnew0;
  131.     intnew0 -= yshearjunk;
  132.  
  133.     prevpixel = bgpixel;
  134.  
  135.     for ( row = 0; row < rows; row++ )
  136.         {
  137.         new = intnew0 + row;
  138.         if ( new >= 0 && new < newrows )
  139.         {
  140.         npP = &(temp2pixels[new][col]);
  141.         p = temp1pixels[row][col];
  142.         PPM_ASSIGN( *npP,
  143.             ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(p) + HALFSCALE ) / SCALE,
  144.             ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(p) + HALFSCALE ) / SCALE,
  145.             ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(p) + HALFSCALE ) / SCALE );
  146.         prevpixel = p;
  147.         }
  148.         }
  149.     if ( fracnew0 > 0 && intnew0 + rows < newrows )
  150.         {
  151.         npP = &(temp2pixels[intnew0 + rows][col]);
  152.         PPM_ASSIGN( *npP,
  153.         ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
  154.         ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
  155.         ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
  156.         }
  157.     }
  158.     ppm_freearray( temp1pixels, rows );
  159.  
  160.     /* Finally, shear X from temp2 into newpixelrow. */
  161.     ppm_writeppminit( stdout, newcols, newrows, maxval );
  162.     newpixelrow = ppm_allocrow( newcols );
  163.     for ( row = 0; row < newrows; row++ )
  164.     {
  165.     for ( col = 0, npP = newpixelrow; col < newcols; col++, npP++ )
  166.         *npP = bgpixel;
  167.  
  168.     if ( fangle > 0 )
  169.         new0 = row * xshearfac;
  170.     else
  171.         new0 = ( newrows - row ) * xshearfac;
  172.     intnew0 = (int) new0;
  173.     fracnew0 = ( new0 - intnew0 ) * SCALE;
  174.     omfracnew0 = SCALE - fracnew0;
  175.     intnew0 -= x2shearjunk;
  176.  
  177.     prevpixel = bgpixel;
  178.  
  179.     for ( col = 0, pP = temp2pixels[row]; col < tempcols; col++, pP++ )
  180.         {
  181.         new = intnew0 + col;
  182.         if ( new >= 0 && new < newcols )
  183.         {
  184.         npP = &(newpixelrow[new]);
  185.         PPM_ASSIGN( *npP,
  186.             ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(*pP) + HALFSCALE ) / SCALE,
  187.             ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(*pP) + HALFSCALE ) / SCALE,
  188.             ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(*pP) + HALFSCALE ) / SCALE );
  189.         prevpixel = *pP;
  190.         }
  191.         }
  192.     if ( fracnew0 > 0 && intnew0 + tempcols < newcols )
  193.         {
  194.         npP = &(newpixelrow[intnew0 + tempcols]);
  195.         PPM_ASSIGN( *npP,
  196.         ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE,
  197.         ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE,
  198.         ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE );
  199.         }
  200.     ppm_writeppmrow( stdout, newpixelrow, newcols, maxval );
  201.     }
  202.  
  203.     exit( 0 );
  204.     }
  205.