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

  1. /*  
  2. Copyright 1990 by John Wiley & Sons, Inc.
  3.           All Rights Reserved.
  4. */
  5. /****************************************/
  6. /*       Image Processing Code          */
  7. /*      Area Processing Functions       */
  8. /*       written in Turbo C 2.0         */
  9. /*                 by                   */
  10. /*          Craig A. Lindley            */
  11. /*                                      */
  12. /*   Vers: 1.0  Last Update: 11/13/89   */
  13. /****************************************/
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <conio.h>
  18. #include <dos.h>
  19. #include <alloc.h>
  20. #include <process.h>
  21. #include <math.h>
  22. #include <graphics.h>
  23. #include "misc.h"
  24. #include "pcx.h"
  25. #include "vga.h"
  26. #include "imagesup.h"
  27. #include "arprocess.h"
  28.  
  29.  
  30. /*
  31. Integer Convolution Function
  32. */
  33.  
  34. CompletionCode Convolution(BYTE huge *InImage, unsigned Col, unsigned Row,
  35.                unsigned Width, unsigned Height,
  36.                short *Kernel, unsigned KernelCols,
  37.                unsigned KernelRows, unsigned Scale,
  38.                unsigned Absolute, BYTE huge * *OutImageBufPtr)
  39. {
  40.    register unsigned ColExtent, RowExtent;
  41.    register unsigned ImageCol, ImageRow, KernCol, KernRow;
  42.    unsigned ColOffset, RowOffset, TempCol, TempRow;
  43.    BYTE huge *OutputImageBuffer;
  44.    long Sum;
  45.    short *KernelPtr;
  46.  
  47.  
  48.    if (ParameterCheckOK(Col,Row,Col+Width,Row+Height,"Convolution"))
  49.    {
  50.       /* Image must be at least the same size as the kernel */
  51.       if (Width >= KernelCols && Height >= KernelRows)
  52.       {
  53.      /* allocate far memory buffer for output image */
  54.      OutputImageBuffer = (BYTE huge *)
  55.                  farcalloc(RASTERSIZE,(unsigned long)sizeof(BYTE));
  56.  
  57.      if (OutputImageBuffer == NULL)
  58.      {
  59.         restorecrtmode();
  60.         printf("Error Not enough memory for convolution output buffer\n");
  61.         return (ENoMemory);
  62.      }
  63.  
  64.      /* Store address of output image buffer */
  65.      *OutImageBufPtr = OutputImageBuffer;
  66.  
  67.      /*
  68.      Clearing the output buffer to white will show the
  69.      boarder areas not touched by the convolution. It also
  70.      provides a nice white frame for the output image.
  71.      */
  72.  
  73.      ClearImageArea(OutputImageBuffer,MINCOLNUM,MINROWNUM,
  74.             MAXCOLS,MAXROWS,WHITE);
  75.  
  76.      ColOffset = KernelCols/2;
  77.      RowOffset = KernelRows/2;
  78.      /* Compensate for edge effects */
  79.      Col += ColOffset;
  80.      Row += RowOffset;
  81.      Width  -= (KernelCols - 1);
  82.      Height -= (KernelRows - 1);
  83.  
  84.      /* Calculate new range of pixels to act upon */
  85.      ColExtent = Col + Width;
  86.      RowExtent = Row + Height;
  87.  
  88.      for (ImageRow = Row; ImageRow < RowExtent; ImageRow++)
  89.      {
  90.         TempRow = ImageRow - RowOffset;
  91.         for (ImageCol = Col; ImageCol < ColExtent; ImageCol++)
  92.         {
  93.            TempCol = ImageCol - ColOffset;
  94.            Sum = 0L;
  95.            KernelPtr = Kernel;
  96.            for (KernCol = 0; KernCol < KernelCols; KernCol++)
  97.           for (KernRow = 0; KernRow < KernelRows; KernRow++)
  98.              Sum += (GetPixelFromImage(InImage,
  99.                  TempCol+KernCol, TempRow+KernRow) *
  100.                  (*KernelPtr++));
  101.  
  102.            /* If absolute value is requested */
  103.            if (Absolute)
  104.           Sum = labs(Sum);
  105.  
  106.            /* Summation performed. Scale and range Sum*/
  107.            Sum >>= (long) Scale;
  108.  
  109.            Sum = (Sum < MINSAMPLEVAL) ? MINSAMPLEVAL:Sum;
  110.            Sum = (Sum > MAXSAMPLEVAL) ? MAXSAMPLEVAL:Sum;
  111.            PutPixelInImage(OutputImageBuffer,ImageCol,ImageRow,(BYTE)Sum);
  112.         }
  113.      }
  114.       }
  115.       else
  116.      return(EKernelSize);
  117.    }
  118.    return(NoError);
  119. }
  120.  
  121. /*
  122. Real Number Convolution Function. This convolution function is
  123. only used when the kernel entries are floating point numbers
  124. instead of integers. Because of the floating point operations
  125. envolved, this function is substantially slower than the already
  126. slow integer version above.
  127. */
  128.  
  129. CompletionCode RealConvolution(BYTE huge *InImage,
  130.                    unsigned Col, unsigned Row,
  131.                    unsigned Width, unsigned Height,
  132.                    double *Kernel, unsigned KernelCols,
  133.                    unsigned KernelRows, unsigned Scale,
  134.                    unsigned Absolute, BYTE huge * *OutImageBufPtr)
  135. {
  136.    register unsigned ColExtent, RowExtent;
  137.    register unsigned ImageCol, ImageRow, KernCol, KernRow;
  138.    unsigned ColOffset, RowOffset, TempCol, TempRow;
  139.    BYTE huge *OutputImageBuffer;
  140.    double Sum;
  141.    double *KernelPtr;
  142.  
  143.  
  144.    if (ParameterCheckOK(Col,Row,Col+Width,Row+Height,"Convolution"))
  145.    {
  146.       /* Image must be at least the same size as the kernel */
  147.       if (Width >= KernelCols && Height >= KernelRows)
  148.       {
  149.      /* allocate far memory buffer for output image */
  150.      OutputImageBuffer = (BYTE huge *)
  151.                  farcalloc(RASTERSIZE,(unsigned long)sizeof(BYTE));
  152.  
  153.      if (OutputImageBuffer == NULL)
  154.      {
  155.         restorecrtmode();
  156.         printf("Error Not enough memory for convolution output buffer\n");
  157.         return (ENoMemory);
  158.      }
  159.  
  160.      /* Store address of output image buffer */
  161.      *OutImageBufPtr = OutputImageBuffer;
  162.  
  163.      /*
  164.      Clearing the output buffer to white will show the
  165.      boarder areas not touched by the convolution. It also
  166.      provides a nice white frame for the output image.
  167.      */
  168.  
  169.      ClearImageArea(OutputImageBuffer,MINCOLNUM,MINROWNUM,
  170.             MAXCOLS,MAXROWS,WHITE);
  171.  
  172.      ColOffset = KernelCols/2;
  173.      RowOffset = KernelRows/2;
  174.      /* Compensate for edge effects */
  175.      Col += ColOffset;
  176.      Row += RowOffset;
  177.      Width  -= (KernelCols - 1);
  178.      Height -= (KernelRows - 1);
  179.  
  180.      /* Calculate new range of pixels to act upon */
  181.      ColExtent = Col + Width;
  182.      RowExtent = Row + Height;
  183.  
  184.      for (ImageRow = Row; ImageRow < RowExtent; ImageRow++)
  185.      {
  186.         TempRow = ImageRow - RowOffset;
  187.         for (ImageCol = Col; ImageCol < ColExtent; ImageCol++)
  188.         {
  189.            TempCol = ImageCol - ColOffset;
  190.            Sum = 0.0;
  191.            KernelPtr = Kernel;
  192.            for (KernCol = 0; KernCol < KernelCols; KernCol++)
  193.           for (KernRow = 0; KernRow < KernelRows; KernRow++)
  194.              Sum += (GetPixelFromImage(InImage,
  195.                  TempCol+KernCol, TempRow+KernRow) *
  196.                  (*KernelPtr++));
  197.  
  198.            /* If absolute value is requested */
  199.            if (Absolute)
  200.           Sum = fabs(Sum);
  201.  
  202.            /* Summation performed. Scale and range Sum */
  203.            Sum /= (double)(1<<Scale);
  204.  
  205.            Sum = (Sum < MINSAMPLEVAL) ? MINSAMPLEVAL:Sum;
  206.            Sum = (Sum > MAXSAMPLEVAL) ? MAXSAMPLEVAL:Sum;
  207.            PutPixelInImage(OutputImageBuffer,ImageCol,ImageRow,(BYTE)Sum);
  208.         }
  209.      }
  210.       }
  211.       else
  212.      return(EKernelSize);
  213.    }
  214.    return(NoError);
  215. }
  216.  
  217.  
  218.  
  219. /*
  220. Byte compare for use with the qsort library function call
  221. in the Median filter function.
  222. */
  223.  
  224. int ByteCompare(BYTE *Entry1, BYTE *Entry2)
  225. {
  226.    if (*Entry1 < *Entry2)
  227.       return(-1);
  228.    else if (*Entry1 > *Entry2)
  229.       return(1);
  230.    else
  231.       return(0);
  232. }
  233.  
  234.  
  235. CompletionCode MedianFilter(BYTE huge *InImage, unsigned Col, unsigned Row,
  236.                unsigned Width, unsigned Height,
  237.                unsigned NeighborhoodCols, unsigned NeighborhoodRows,
  238.                BYTE huge * *OutImageBufPtr)
  239. {
  240.    register unsigned ColExtent, RowExtent;
  241.    register unsigned ImageCol, ImageRow, NeighborCol, NeighborRow;
  242.    unsigned ColOffset, RowOffset, TempCol, TempRow, PixelIndex;
  243.    unsigned TotalPixels, MedianIndex;
  244.    BYTE huge *OutputImageBuffer;
  245.    BYTE *PixelValues;
  246.  
  247.  
  248.    if (ParameterCheckOK(Col,Row,Col+Width,Row+Height,"Median Filter"))
  249.    {
  250.       /* Image must be at least the same size as the neighborhood */
  251.       if (Width >= NeighborhoodCols && Height >= NeighborhoodRows)
  252.       {
  253.      /* allocate far memory buffer for output image */
  254.      OutputImageBuffer = (BYTE huge *)
  255.                  farcalloc(RASTERSIZE,(unsigned long)sizeof(BYTE));
  256.  
  257.      if (OutputImageBuffer == NULL)
  258.      {
  259.         restorecrtmode();
  260.         printf("Error Not enough memory for median filter output buffer\n");
  261.         return (ENoMemory);
  262.      }
  263.  
  264.      /* Store address of output image buffer */
  265.      *OutImageBufPtr = OutputImageBuffer;
  266.  
  267.      /*
  268.      Clearing the output buffer to white will show the
  269.      boarder areas not touched by the median filter. It also
  270.      provides a nice white frame for the output image.
  271.      */
  272.  
  273.      ClearImageArea(OutputImageBuffer,MINCOLNUM,MINROWNUM,
  274.             MAXCOLS,MAXROWS,WHITE);
  275.  
  276.      /* Calculate border pixel to miss */
  277.      ColOffset = NeighborhoodCols/2;
  278.      RowOffset = NeighborhoodRows/2;
  279.  
  280.      /* Compensate for edge effects */
  281.      Col += ColOffset;
  282.      Row += RowOffset;
  283.      Width  -= (NeighborhoodCols - 1);
  284.      Height -= (NeighborhoodRows - 1);
  285.  
  286.      /* Calculate new range of pixels to act upon */
  287.      ColExtent = Col + Width;
  288.      RowExtent = Row + Height;
  289.  
  290.      TotalPixels = (NeighborhoodCols*NeighborhoodRows);
  291.      MedianIndex = (NeighborhoodCols*NeighborhoodRows)/2;
  292.  
  293.      /* allocate memory for pixel buffer */
  294.      PixelValues = (BYTE *) calloc(TotalPixels,(unsigned)sizeof(BYTE));
  295.  
  296.      if (PixelValues == NULL)
  297.      {
  298.         restorecrtmode();
  299.         printf("Error Not enough memory for median filter pixel buffer\n");
  300.         return (ENoMemory);
  301.      }
  302.  
  303.      for (ImageRow = Row; ImageRow < RowExtent; ImageRow++)
  304.      {
  305.         TempRow = ImageRow - RowOffset;
  306.         for (ImageCol = Col; ImageCol < ColExtent; ImageCol++)
  307.         {
  308.            TempCol = ImageCol - ColOffset;
  309.            PixelIndex = 0;
  310.            for (NeighborCol = 0; NeighborCol < NeighborhoodCols; NeighborCol++)
  311.           for (NeighborRow = 0; NeighborRow < NeighborhoodRows; NeighborRow++)
  312.              PixelValues[PixelIndex++] =
  313.                GetPixelFromImage(InImage,TempCol+NeighborCol,
  314.                          TempRow+NeighborRow);
  315.  
  316.            /*
  317.            Quick sort the brightness values into ascending order
  318.            and then pick out the median or middle value as
  319.            that for the pixel.
  320.            */
  321.            qsort(PixelValues,TotalPixels,sizeof(BYTE),ByteCompare);
  322.            PutPixelInImage(OutputImageBuffer,ImageCol,ImageRow,
  323.                    PixelValues[MedianIndex]);
  324.         }
  325.      }
  326.       }
  327.       else
  328.      return(EKernelSize);
  329.    }
  330.    free(PixelValues);        /* give up the pixel value buffer */
  331.    return(NoError);
  332. }
  333.  
  334. /*
  335. Sobel Edge Detection Function
  336. */
  337.  
  338. CompletionCode SobelEdgeDet(BYTE huge *InImage,
  339.                 unsigned Col, unsigned Row,
  340.                 unsigned Width, unsigned Height,
  341.                 unsigned Threshold, unsigned Overlay,
  342.                 BYTE huge * *OutImageBufPtr)
  343. {
  344.    register unsigned ColExtent, RowExtent;
  345.    register unsigned ImageCol, ImageRow;
  346.    unsigned PtA, PtB, PtC, PtD, PtE, PtF, PtG, PtH, PtI;
  347.    unsigned LineAEIAveAbove, LineAEIAveBelow, LineAEIMaxDif;
  348.    unsigned LineBEHAveAbove, LineBEHAveBelow, LineBEHMaxDif;
  349.    unsigned LineCEGAveAbove, LineCEGAveBelow, LineCEGMaxDif;
  350.    unsigned LineDEFAveAbove, LineDEFAveBelow, LineDEFMaxDif;
  351.    unsigned MaxDif;
  352.    BYTE huge *OutputImageBuffer;
  353.  
  354.  
  355.    if (ParameterCheckOK(Col,Row,Col+Width,Row+Height,"Sobel Edge Detector"))
  356.    {
  357.       /* allocate far memory buffer for output image */
  358.       OutputImageBuffer = (BYTE huge *)
  359.               farcalloc(RASTERSIZE,(unsigned long)sizeof(BYTE));
  360.  
  361.       if (OutputImageBuffer == NULL)
  362.       {
  363.     restorecrtmode();
  364.     printf("Error Not enough memory for Sobel output buffer\n");
  365.     return (ENoMemory);
  366.       }
  367.  
  368.       /* Store address of output image buffer */
  369.       *OutImageBufPtr = OutputImageBuffer;
  370.  
  371.       /*
  372.       Clearing the output buffer
  373.       */
  374.  
  375.       ClearImageArea(OutputImageBuffer,MINCOLNUM,MINROWNUM,
  376.              MAXCOLS,MAXROWS,BLACK);
  377.  
  378.       /* Compensate for edge effects of 3x3 pixel neighborhood */
  379.       Col += 1;
  380.       Row += 1;
  381.       Width  -= 2;
  382.       Height -= 2;
  383.  
  384.       /* Calculate new range of pixels to act upon */
  385.       ColExtent = Col + Width;
  386.       RowExtent = Row + Height;
  387.  
  388.       for (ImageRow = Row; ImageRow < RowExtent; ImageRow++)
  389.      for (ImageCol = Col; ImageCol < ColExtent; ImageCol++)
  390.      {
  391.        /* Get each pixel in 3x3 neighborhood */
  392.        PtA = GetPixelFromImage(InImage,ImageCol-1,ImageRow-1);
  393.        PtB = GetPixelFromImage(InImage,ImageCol  ,ImageRow-1);
  394.        PtC = GetPixelFromImage(InImage,ImageCol+1,ImageRow-1);
  395.        PtD = GetPixelFromImage(InImage,ImageCol-1,ImageRow  );
  396.        PtE = GetPixelFromImage(InImage,ImageCol  ,ImageRow  );
  397.        PtF = GetPixelFromImage(InImage,ImageCol+1,ImageRow  );
  398.        PtG = GetPixelFromImage(InImage,ImageCol-1,ImageRow+1);
  399.        PtH = GetPixelFromImage(InImage,ImageCol  ,ImageRow+1);
  400.        PtI = GetPixelFromImage(InImage,ImageCol+1,ImageRow+1);
  401.  
  402.        /*
  403.        Calculate average above and below the line.
  404.        Take the absolute value of the difference.
  405.        */
  406.        LineAEIAveBelow = (PtD+PtG+PtH)/3;
  407.        LineAEIAveAbove = (PtB+PtC+PtF)/3;
  408.        LineAEIMaxDif = abs(LineAEIAveBelow-LineAEIAveAbove);
  409.  
  410.        LineBEHAveBelow = (PtA+PtD+PtG)/3;
  411.        LineBEHAveAbove = (PtC+PtF+PtI)/3;
  412.        LineBEHMaxDif = abs(LineBEHAveBelow-LineBEHAveAbove);
  413.  
  414.        LineCEGAveBelow = (PtF+PtH+PtI)/3;
  415.        LineCEGAveAbove = (PtA+PtB+PtD)/3;
  416.        LineCEGMaxDif = abs(LineCEGAveBelow-LineCEGAveAbove);
  417.  
  418.        LineDEFAveBelow = (PtG+PtH+PtI)/3;
  419.        LineDEFAveAbove = (PtA+PtB+PtC)/3;
  420.        LineDEFMaxDif = abs(LineDEFAveBelow-LineDEFAveAbove);
  421.        /*
  422.        Find the maximum value of the absolute differences
  423.        from the four possibilities.
  424.        */
  425.        MaxDif = MAX(LineAEIMaxDif,LineBEHMaxDif);
  426.        MaxDif = MAX(LineCEGMaxDif,MaxDif);
  427.        MaxDif = MAX(LineDEFMaxDif,MaxDif);
  428.        /*
  429.        If maximum difference is above the threshold, set
  430.        the pixel of interest (center pixel) to white. If
  431.        below the threshold optionally copy the input image
  432.        to the output image. This copying is controlled by
  433.        the parameter Overlay.
  434.        */
  435.        if (MaxDif >= Threshold)
  436.          PutPixelInImage(OutputImageBuffer,ImageCol,ImageRow,WHITE);
  437.        else if (Overlay)
  438.          PutPixelInImage(OutputImageBuffer,ImageCol,ImageRow,PtE);
  439.      }
  440.    }
  441.    return(NoError);
  442. }
  443.  
  444.