home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0040 - 0049 / ibm0040-0049 / ibm0040.tar / ibm0040 / IMGPROC.ZIP / C12.ZIP / GEPROCES.C next >
Encoding:
C/C++ Source or Header  |  1990-04-06  |  12.1 KB  |  366 lines

  1. /*  
  2. Copyright 1990 by John Wiley & Sons, Inc.
  3.           All Rights Reserved.
  4. */
  5. /****************************************/
  6. /*       Image Processing Code          */
  7. /*   Geometric Processing Functions     */
  8. /*       written in Turbo C 2.0         */
  9. /*                by                    */
  10. /*         Craig A. Lindley             */
  11. /*                                      */
  12. /*   Vers: 1.0  Last Update: 11/16/89   */
  13. /****************************************/
  14.  
  15. #include <stdio.h>
  16. #include <conio.h>
  17. #include <dos.h>
  18. #include <alloc.h>
  19. #include <process.h>
  20. #include <math.h>
  21. #include <graphics.h>
  22. #include "misc.h"
  23. #include "pcx.h"
  24. #include "vga.h"
  25. #include "imagesup.h"
  26.  
  27.  
  28. void ScaleImage(BYTE huge *InImage, unsigned SCol, unsigned SRow,
  29.         unsigned SWidth, unsigned SHeight,
  30.         double ScaleH, double ScaleV,
  31.         BYTE huge *OutImage,
  32.         unsigned DCol, unsigned DRow,
  33.         unsigned Interpolate)
  34. {
  35.    unsigned DestWidth, DestHeight;
  36.    unsigned PtA, PtB, PtC, PtD, PixelValue;
  37.    register unsigned SPixelColNum, SPixelRowNum, DestCol, DestRow;
  38.    double SPixelColAddr, SPixelRowAddr;
  39.    double ColDelta, RowDelta;
  40.    double ContribFromAandB, ContribFromCandD;
  41.  
  42.    DestWidth =  ScaleH * SWidth + 0.5;
  43.    DestHeight = ScaleV * SHeight+ 0.5;
  44.  
  45.    if (ParameterCheckOK(SCol,SRow,SCol+SWidth,SRow+SHeight,"ScaleImage") &&
  46.        ParameterCheckOK(DCol,DRow,DCol+DestWidth,DRow+DestHeight,"ScaleImage"))
  47.    {
  48.       /* Calculations from destination perspective */
  49.       for (DestRow = 0; DestRow < DestHeight; DestRow++)
  50.       {
  51.      SPixelRowAddr = DestRow/ScaleV;
  52.      SPixelRowNum  = (unsigned) SPixelRowAddr;
  53.      RowDelta      = SPixelRowAddr - SPixelRowNum;
  54.      SPixelRowNum += SRow;
  55.  
  56.      for (DestCol = 0; DestCol < DestWidth; DestCol++)
  57.      {
  58.         SPixelColAddr = DestCol/ScaleH;
  59.         SPixelColNum  = (unsigned) SPixelColAddr;
  60.         ColDelta      = SPixelColAddr - SPixelColNum;
  61.         SPixelColNum += SCol;
  62.  
  63.         if (Interpolate)
  64.         {
  65.            /*
  66.            SPixelColNum and SPixelRowNum now contain the pixel
  67.            coordinates of the upper left pixel of the targetted
  68.            pixel's (point X) neighborhood. This is point A below:
  69.                A       B
  70.                    X
  71.                C       D
  72.            We must retrieve the brightness level of each of the
  73.            four pixels to calculate the value of the pixel put into
  74.            the destination image.
  75.  
  76.            Get point A brightness as it will always lie within the
  77.            input image area. Check to make sure the other points are
  78.            within also. If so use their values for the calculations.
  79.            If not, set them all equal to point A's value. This induces
  80.            an error but only at the edges on an image.
  81.            */
  82.  
  83.            PtA = GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum);
  84.            if (((SPixelColNum+1) < MAXCOLS) && ((SPixelRowNum+1) < MAXROWS))
  85.            {
  86.           PtB = GetPixelFromImage(InImage,SPixelColNum+1,SPixelRowNum);
  87.           PtC = GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum+1);
  88.           PtD = GetPixelFromImage(InImage,SPixelColNum+1,SPixelRowNum+1);
  89.            }
  90.            else
  91.            {
  92.           /* All points have equal brightness */
  93.           PtB=PtC=PtD=PtA;
  94.            }
  95.            /*
  96.            Interpolate to find brightness contribution of each pixel
  97.            in neighborhood. Done in both the horizontal and vertical
  98.            directions.
  99.            */
  100.            ContribFromAandB = ColDelta*((double)PtB - PtA) + PtA;
  101.            ContribFromCandD = ColDelta*((double)PtD - PtC) + PtC;
  102.            PixelValue = 0.5 + ContribFromAandB +
  103.             (ContribFromCandD - ContribFromAandB)*RowDelta;
  104.         }
  105.         else
  106.            PixelValue=GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum);
  107.  
  108.         /* Put the pixel into the destination buffer */
  109.         PutPixelInImage(OutImage,DestCol+DCol,DestRow+DRow,PixelValue);
  110.      }
  111.       }
  112.    }
  113. }
  114.  
  115.  
  116. void SizeImage(BYTE huge *InImage, unsigned SCol, unsigned SRow,
  117.         unsigned SWidth, unsigned SHeight,
  118.         BYTE huge *OutImage,
  119.         unsigned DCol, unsigned DRow,
  120.         unsigned DWidth, unsigned DHeight,
  121.         unsigned Interpolate)
  122. {
  123.    double HScale, VScale;
  124.  
  125.    /* Check for parameters out of range */
  126.    if (ParameterCheckOK(SCol,SRow,SCol+SWidth,SRow+SHeight,"SizeImage") &&
  127.        ParameterCheckOK(DCol,DRow,DCol+DWidth,DRow+DHeight,"SizeImage"))
  128.    {
  129.       /*
  130.       Calculate horizontal and vertical scale factors required
  131.       to fit specified portion of input image into specified portion
  132.       of output image.
  133.       */
  134.       HScale = (double)DWidth/(double)SWidth;
  135.       VScale = (double)DHeight/(double)SHeight;
  136.  
  137.       /* Call ScaleImage to do the actual work */
  138.       ScaleImage(InImage,SCol,SRow,SWidth,SHeight,HScale,VScale,
  139.          OutImage,DCol,DRow,Interpolate);
  140.    }
  141. }
  142.  
  143. void RotateImage(BYTE huge *InImage, unsigned Col, unsigned Row,
  144.          unsigned Width, unsigned Height, double Angle,
  145.          BYTE huge *OutImage, unsigned Interpolate)
  146. {
  147.    register unsigned ImageCol, ImageRow;
  148.    unsigned CenterCol, CenterRow, SPixelColNum, SPixelRowNum;
  149.    unsigned ColExtent, RowExtent, PixelValue;
  150.    unsigned PtA, PtB, PtC, PtD;
  151.    double   DPixelRelativeColNum, DPixelRelativeRowNum;
  152.    double   CosAngle, SinAngle, SPixelColAddr, SPixelRowAddr;
  153.    double   ColDelta, RowDelta;
  154.    double   ContribFromAandB, ContribFromCandD;
  155.  
  156.    if (ParameterCheckOK(Col,Row,Col+Width,Row+Height,"RotateImage"))
  157.    {
  158.       /* Angle must be in 0..359.9 */
  159.       while (Angle >= 360.0)
  160.      Angle -= 360.0;
  161.  
  162.       /* Convert angle from degrees to radians */
  163.       Angle *= ((double) 3.14159/(double) 180.0);
  164.  
  165.       /* Calculate angle values for rotation */
  166.       CosAngle = cos(Angle);
  167.       SinAngle = sin(Angle);
  168.  
  169.       /* Center of rotation */
  170.       CenterCol = Col + Width/2;
  171.       CenterRow = Row + Height/2;
  172.  
  173.       ColExtent = Col + Width;
  174.       RowExtent = Row + Height;
  175.  
  176.       /*
  177.       All calculations are performed from the destination image
  178.       perspective. Absolute pixel values must be converted into
  179.       inches of display distance to keep the aspect value
  180.       correct when image is rotated. After rotation, the calculated
  181.       display distance is converted back to real pixel values.
  182.       */
  183.  
  184.       for (ImageRow = Row; ImageRow < RowExtent; ImageRow++)
  185.       {
  186.      DPixelRelativeRowNum = (double)ImageRow - CenterRow;
  187.      /* Convert row value to display distance from image center */
  188.      DPixelRelativeRowNum *= LRINCHESPERPIXELVERT;
  189.  
  190.      for (ImageCol = Col; ImageCol < ColExtent; ImageCol++)
  191.      {
  192.         DPixelRelativeColNum = (double)ImageCol - CenterCol;
  193.         /* Convert col value to display distance from image center */
  194.         DPixelRelativeColNum *= LRINCHESPERPIXELHORIZ;
  195.         /*
  196.         Calculate source pixel address from destination
  197.         pixels position.
  198.         */
  199.         SPixelColAddr = DPixelRelativeColNum*CosAngle-
  200.                 DPixelRelativeRowNum*SinAngle;
  201.         SPixelRowAddr = DPixelRelativeColNum*SinAngle+
  202.                 DPixelRelativeRowNum*CosAngle;
  203.  
  204.         /*
  205.         Convert from coordinates relative to image
  206.         center back into absolute coordinates.
  207.         */
  208.         /* Convert display distance to pixel location */
  209.         SPixelColAddr *= LRPIXELSPERINCHHORIZ;
  210.         SPixelColAddr += CenterCol;
  211.         SPixelRowAddr *= LRPIXELSPERINCHVERT;
  212.         SPixelRowAddr += CenterRow;
  213.  
  214.         SPixelColNum = (unsigned) SPixelColAddr;
  215.         SPixelRowNum = (unsigned) SPixelRowAddr;
  216.         ColDelta = SPixelColAddr - SPixelColNum;
  217.         RowDelta = SPixelRowAddr - SPixelRowNum;
  218.  
  219.         if (Interpolate)
  220.         {
  221.            /*
  222.            SPixelColNum and SPixelRowNum now contain the pixel
  223.            coordinates of the upper left pixel of the targetted
  224.            pixel's (point X) neighborhood. This is point A below:
  225.                A       B
  226.                    X
  227.                C       D
  228.            We must retrieve the brightness level of each of the
  229.            four pixels to calculate the value of the pixel put into
  230.            the destination image.
  231.  
  232.            Get point A brightness as it will always lie within the
  233.            input image area. Check to make sure the other points are
  234.            within also. If so use their values for the calculations.
  235.            If not, set them all equal to point A's value. This induces
  236.            an error but only at the edges on an image.
  237.            */
  238.  
  239.            PtA = GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum);
  240.            if (((SPixelColNum+1) < MAXCOLS) && ((SPixelRowNum+1) < MAXROWS))
  241.            {
  242.           PtB = GetPixelFromImage(InImage,SPixelColNum+1,SPixelRowNum);
  243.           PtC = GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum+1);
  244.           PtD = GetPixelFromImage(InImage,SPixelColNum+1,SPixelRowNum+1);
  245.            }
  246.            else
  247.            {
  248.           /* All points have equal brightness */
  249.           PtB=PtC=PtD=PtA;
  250.            }
  251.            /*
  252.            Interpolate to find brightness contribution of each pixel
  253.            in neighborhood. Done in both the horizontal and vertical
  254.            directions.
  255.            */
  256.            ContribFromAandB = ColDelta*((double)PtB - PtA) + PtA;
  257.            ContribFromCandD = ColDelta*((double)PtD - PtC) + PtC;
  258.            PixelValue = 0.5 + ContribFromAandB +
  259.             (ContribFromCandD - ContribFromAandB)*RowDelta;
  260.         }
  261.         else
  262.            PixelValue=GetPixelFromImage(InImage,SPixelColNum,SPixelRowNum);
  263.  
  264.         /* Put the pixel into the destination buffer */
  265.         PutPixelInImage(OutImage,ImageCol,ImageRow,PixelValue);
  266.      }
  267.       }
  268.    }
  269. }
  270.  
  271.  
  272. /*
  273. Caution: images must not overlap
  274. */
  275. void TranslateImage(BYTE huge *InImage,
  276.             unsigned SCol, unsigned SRow,
  277.             unsigned SWidth, unsigned SHeight,
  278.             BYTE huge *OutImage,
  279.             unsigned DCol, unsigned DRow,
  280.             unsigned EraseFlag)
  281. {
  282.    register unsigned SImageCol, SImageRow, DestCol;
  283.    unsigned SColExtent, SRowExtent;
  284.  
  285.    /* Check for parameters out of range */
  286.    if (ParameterCheckOK(SCol,SRow,SCol+SWidth,SRow+SHeight,"TranslateImage") &&
  287.        ParameterCheckOK(DCol,DRow,DCol+SWidth,DRow+SHeight,"TranslateImage"))
  288.    {
  289.       SColExtent = SCol+SWidth;
  290.       SRowExtent = SRow+SHeight;
  291.  
  292.       for (SImageRow = SRow; SImageRow < SRowExtent; SImageRow++)
  293.       {
  294.      /* Reset the destination Column count every row */
  295.      DestCol = DCol;
  296.      for (SImageCol = SCol; SImageCol < SColExtent; SImageCol++)
  297.      {
  298.         /* Transfer byte of the image data between buffers */
  299.         PutPixelInImage(OutImage,DestCol++,DRow,
  300.                 GetPixelFromImage(InImage,SImageCol,SImageRow));
  301.      }
  302.      /* Bump to next row in the destination image */
  303.      DRow++;
  304.       }
  305.       /* If erasure specified, blot out original image */
  306.       if (EraseFlag)
  307.      ClearImageArea(InImage,SCol,SRow,SWidth,SHeight,BLACK);
  308.    }
  309. }
  310.  
  311. void MirrorImage(BYTE huge *InImage,
  312.          unsigned SCol, unsigned SRow,
  313.          unsigned SWidth, unsigned SHeight,
  314.          enum MirrorType WhichMirror,
  315.          BYTE huge *OutImage,
  316.          unsigned DCol, unsigned DRow)
  317. {
  318.    register unsigned SImageCol, SImageRow, DestCol;
  319.    unsigned SColExtent, SRowExtent;
  320.  
  321.    /* Check for parameters out of range */
  322.    if (ParameterCheckOK(SCol,SRow,SCol+SWidth,SRow+SHeight,"MirrorImage") &&
  323.        ParameterCheckOK(DCol,DRow,DCol+SWidth,DRow+SHeight,"MirrorImage"))
  324.    {
  325.       SColExtent = SCol+SWidth;
  326.       SRowExtent = SRow+SHeight;
  327.  
  328.       switch(WhichMirror)
  329.       {
  330.      case HorizMirror:
  331.         for (SImageRow = SRow; SImageRow < SRowExtent; SImageRow++)
  332.         {
  333.            /* Reset the destination Column count every row */
  334.            DestCol = DCol + SWidth;
  335.            for (SImageCol = SCol; SImageCol < SColExtent; SImageCol++)
  336.            {
  337.           /* Transfer byte of the image data between buffers */
  338.           PutPixelInImage(OutImage,--DestCol,DRow,
  339.                 GetPixelFromImage(InImage,SImageCol,SImageRow));
  340.            }
  341.            /* Bump to next row in the destination image */
  342.            DRow++;
  343.         }
  344.         break;
  345.      case VertMirror:
  346.         DRow += (SHeight-1);
  347.         for (SImageRow = SRow; SImageRow < SRowExtent; SImageRow++)
  348.         {
  349.            /* Reset the destination Column count every row */
  350.            DestCol = DCol;
  351.            for (SImageCol = SCol; SImageCol < SColExtent; SImageCol++)
  352.            {
  353.           /* Transfer byte of the image data between buffers */
  354.           PutPixelInImage(OutImage,DestCol++,DRow,
  355.                 GetPixelFromImage(InImage,SImageCol,SImageRow));
  356.            }
  357.            /* Bump to next row in the destination image */
  358.            DRow--;
  359.         }
  360.         break;
  361.       }
  362.    }
  363. }
  364.  
  365.  
  366.