home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / desklib / examples / DeskLib / Examples / Widget5 / !Widget5 / c / Process < prev    next >
Encoding:
Text File  |  1995-05-12  |  21.7 KB  |  862 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *        File: Process.c                                               *
  4.  *                                                                      *
  5.  *     Purpose: Performs actual image processing functions              *
  6.  *                                                                      *
  7.  ************************************************************************/
  8.  
  9. #include "DeskLib:WimpSWIs.h"          /* Low-level WIMP commands         */
  10. #include "DeskLib:Window.h"            /* Window handling automation      */
  11. #include "DeskLib:Core.h"              /* usefull core functions          */
  12. #include "DeskLib:Error.h"             /* Error despatcher                */
  13. #include "DeskLib:Event.h"             /* Event despatcher                */
  14. #include "DeskLib:EventMsg.h"          /* Wimp Message event dispatcher   */
  15. #include "DeskLib:File.h"              /* Low level file handling         */
  16. #include "DeskLib:Msgs.h"              /* Message translation code        */
  17. #include "DeskLib:Resource.h"          /* Handles finding resource files  */
  18. #include "DeskLib:Sound.h"             /* Beep!                           */
  19. #include "DeskLib:Icon.h"              /* Icon handling automation        */
  20. #include "DeskLib:Screen.h"            /* Caching screen info             */
  21. #include "DeskLib:Sprite.h"            /* Sprite handling routines        */
  22. #include "DeskLib:File.h"              /* OS file IO                      */
  23. #include "DeskLib:KeyCodes.h"          /* Codes for wimp returned keys    */
  24. #include "DeskLib:Hourglass.h"         /* control hourglass               */
  25.  
  26. #include "SpriteWin.h"
  27. #include "Filter.h"
  28. #include "ProcessWin.h"
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32.  
  33. void clip_pixel(int *pixel);
  34. void clip_coord(wimp_point *coord, wimp_point *imagesize);
  35. void bubblesort_subloop(int *outerloop, int *innerloop, int *pixel, int (*median)[10]);
  36.  
  37. #define getsource(coord) (sourceimagedata[coord.x + (coord.y * sourcelinelength)])
  38. #define getsource2(coord) (source2imagedata[coord.x + (coord.y * source2linelength)])
  39. #define putdest(coord,value) (destimagedata[coord.x + (coord.y * destlinelength)] = value)
  40. #define getdest(coord) (destimagedata[coord.x + (coord.y * destlinelength)])
  41.  
  42. /******************************************************************************
  43.  *                            extern routines                                 *
  44.  ******************************************************************************/
  45.  
  46. void Process_Copy(int sourceimage, int destimage, wimp_point *size)
  47. {
  48.  /*
  49.   * copies 'sourceimage' to 'destimage'
  50.   */
  51.   wimp_point pixel;
  52.  
  53.   spritewin_block *block;
  54.   char *sourceimagedata;
  55.   int sourcelinelength;
  56.   char *destimagedata;
  57.   int destlinelength;
  58.  
  59.  /*
  60.   * set up variables for fast sprite access
  61.   */
  62.   block = SpriteWin_GetImageBlock(sourceimage);
  63.   sourceimagedata = (char *) block->spritearea + block->image;
  64.   sourcelinelength = block->linebytes;
  65.  
  66.   block = SpriteWin_GetImageBlock(destimage);
  67.   destimagedata = (char *) block->spritearea + block->image;
  68.   destlinelength = block->linebytes;
  69.  
  70.   Hourglass_On();
  71.  
  72.   for(pixel.y = 0; pixel.y < size->y; pixel.y++){
  73.  
  74.      Hourglass_Percentage( (pixel.y * 100) / size->y);
  75.  
  76.      for(pixel.x = 0; pixel.x < size->x; pixel.x++){
  77.  
  78.          putdest(pixel, getsource(pixel));
  79.      }
  80.   }
  81.  
  82.   Hourglass_Off();
  83.  
  84. }
  85.  
  86. /******************************************************************************/
  87.  
  88. void Process_Add(int sourceimage, int destimage, wimp_point *size)
  89. {
  90.  /*
  91.   * adds 'sourceimage' to 'destimage'
  92.   */
  93.   wimp_point pixel;
  94.   int value;
  95.  
  96.   spritewin_block *block;
  97.   char *sourceimagedata;
  98.   int sourcelinelength;
  99.   char *destimagedata;
  100.   int destlinelength;
  101.  
  102.  /*
  103.   * set up variables for fast sprite access
  104.   */
  105.   block = SpriteWin_GetImageBlock(sourceimage);
  106.   sourceimagedata = (char *) block->spritearea + block->image;
  107.   sourcelinelength = block->linebytes;
  108.  
  109.   block = SpriteWin_GetImageBlock(destimage);
  110.   destimagedata = (char *) block->spritearea + block->image;
  111.   destlinelength = block->linebytes;
  112.  
  113.   Hourglass_On();
  114.  
  115.   for(pixel.y = 0; pixel.y < size->y; pixel.y++){
  116.  
  117.      Hourglass_Percentage( (pixel.y * 100) / size->y);
  118.  
  119.      for(pixel.x = 0; pixel.x < size->x; pixel.x++){
  120.  
  121.          value =  getsource(pixel);
  122.          value += getdest(pixel);
  123.  
  124.          clip_pixel(&value);
  125.  
  126.          putdest(pixel, value);
  127.      }
  128.   }
  129.  
  130.   Hourglass_Off();
  131.  
  132. }
  133.  
  134. /******************************************************************************/
  135.  
  136. void Process_Average(int sourceimage, int destimage, wimp_point *size)
  137. {
  138.  /*
  139.   * adds 'sourceimage' to 'destimage' and divides by 2
  140.   */
  141.   wimp_point pixel;
  142.   int value;
  143.  
  144.   spritewin_block *block;
  145.   char *sourceimagedata;
  146.   int sourcelinelength;
  147.   char *destimagedata;
  148.   int destlinelength;
  149.  
  150.  /*
  151.   * set up variables for fast sprite access
  152.   */
  153.   block = SpriteWin_GetImageBlock(sourceimage);
  154.   sourceimagedata = (char *) block->spritearea + block->image;
  155.   sourcelinelength = block->linebytes;
  156.  
  157.   block = SpriteWin_GetImageBlock(destimage);
  158.   destimagedata = (char *) block->spritearea + block->image;
  159.   destlinelength = block->linebytes;
  160.  
  161.   Hourglass_On();
  162.  
  163.   for(pixel.y = 0; pixel.y < size->y; pixel.y++){
  164.  
  165.      for(pixel.x = 0; pixel.x < size->x; pixel.x++){
  166.  
  167.          Hourglass_Percentage( (pixel.y * 100) / size->y);
  168.  
  169.          value =  getsource(pixel);
  170.          value += getdest(pixel);
  171.          value =  value >> 1;
  172.  
  173.          clip_pixel(&value);
  174.  
  175.          putdest(pixel, value);
  176.      }
  177.   }
  178.  
  179.   Hourglass_Off();
  180.  
  181. }
  182.  
  183. /******************************************************************************/
  184.  
  185. void Process_Convolve(int sourceimage, int destimage, wimp_point *size,
  186.                       wimp_point *anchor, int (*filter)[3][3], BOOL overwrite)
  187. {
  188.  /*
  189.   * convolves 'sourceimage' to 'destimage' using 'filter'
  190.   * if overwrite is FALSE then the destination image is added to rather than overwritten
  191.   */
  192.  
  193. /* maps 0,0 centred matrix to 1,1 centred array */
  194. #define matrix(x, y) (*filter)[x + 1][y + 1]
  195.  
  196.   int scalefactor;
  197.   wimp_point coord;
  198.   wimp_point coord2;
  199.   wimp_point coord3;
  200.   int pixel;
  201.  
  202.   spritewin_block *block;
  203.   char *sourceimagedata;
  204.   int sourcelinelength;
  205.   char *destimagedata;
  206.   int destlinelength;
  207.  
  208.  /*
  209.   * set up variables for fast sprite access
  210.   */
  211.   block = SpriteWin_GetImageBlock(sourceimage);
  212.   sourceimagedata = (char *) block->spritearea + block->image;
  213.   sourcelinelength = block->linebytes;
  214.  
  215.   block = SpriteWin_GetImageBlock(destimage);
  216.   destimagedata = (char *) block->spritearea + block->image;
  217.   destlinelength = block->linebytes;
  218.  
  219.   Hourglass_On();
  220.  
  221.  /*
  222.   * calculate scalefactor for filter matrix
  223.   */
  224.   scalefactor = 0;
  225.   for(coord.y = -1; coord.y <= 1; coord.y++){
  226.  
  227.       for(coord.x = -1; coord.x <= 1; coord.x++){
  228.  
  229.           scalefactor += matrix(coord.x, coord.y);
  230.  
  231.       }
  232.  
  233.   }
  234.   if(scalefactor == 0)
  235.      scalefactor = 1;
  236.  
  237.  
  238.  /*
  239.   * convolve image
  240.   */
  241.   for(coord.y = 0; coord.y < size->y; coord.y++){
  242.  
  243.       Hourglass_Percentage( (coord.y * 100) / size->y);
  244.  
  245.       for(coord.x = 0; coord.x < size->x; coord.x++){
  246.  
  247.          /*
  248.           * perform convolution
  249.           */
  250.  
  251.          /*
  252.           * set initial state of final pixel to 0 if overwrite of final image if not
  253.           */
  254.           if(overwrite)
  255.              pixel = 0;
  256.           else
  257.              pixel = getdest(coord);
  258.  
  259.  
  260.           for(coord2.y = -1; coord2.y <= 1; coord2.y++){
  261.  
  262.               for(coord2.x = -1; coord2.x <= 1; coord2.x++){
  263.  
  264.                   coord3.x = coord.x + coord2.x;
  265.                   coord3.y = coord.y + coord2.y;
  266.                   clip_coord(&coord3, size); /* make sure coord is not off image */
  267.                   pixel += matrix(coord2.x, coord2.y) * getsource(coord3);
  268.  
  269.               }
  270.  
  271.           }
  272.  
  273.           pixel = pixel / scalefactor;
  274.  
  275.           clip_pixel(&pixel);
  276.  
  277.           putdest(coord, pixel);
  278.         
  279.       }
  280.   }
  281.  
  282.   Hourglass_Off();
  283.  
  284. }
  285.  
  286. /******************************************************************************/
  287.  
  288. void Process_Median(int sourceimage, int destimage, wimp_point *size)
  289. {
  290.  /*
  291.   * 3x3 median filters 'sourceimage' to 'destimage'
  292.   */
  293.   wimp_point coord;
  294.   int pixelno;
  295.   int outerloop, innerloop;
  296.   int median[10];
  297.   wimp_point coord2;
  298.   wimp_point coord3;
  299.   int pixel;
  300.  
  301.   spritewin_block *block;
  302.   char *sourceimagedata;
  303.   int sourcelinelength;
  304.   char *destimagedata;
  305.   int destlinelength;
  306.  
  307.  /*
  308.   * set up variables for fast sprite access
  309.   */
  310.   block = SpriteWin_GetImageBlock(sourceimage);
  311.   sourceimagedata = (char *) block->spritearea + block->image;
  312.   sourcelinelength = block->linebytes;
  313.  
  314.   block = SpriteWin_GetImageBlock(destimage);
  315.   destimagedata = (char *) block->spritearea + block->image;
  316.   destlinelength = block->linebytes;
  317.                                                                                         
  318.   Hourglass_On();
  319.  
  320.  /*
  321.   * filter image
  322.   */
  323.   for(coord.y = 0; coord.y < size->y; coord.y++){
  324.  
  325.       Hourglass_Percentage( (coord.y * 100) / size->y);
  326.       
  327.       for(coord.x = 0; coord.x < size->x; coord.x++){
  328.  
  329.          /*
  330.           * perform median filtering
  331.           */
  332.  
  333.         /*
  334.          * fill array 'median' with the 9 pixels contained by the 3x3
  335.          * matrix around the current pixel in the source image.
  336.          * the array entries are median[1] to median[9]
  337.          */
  338.  
  339.          pixelno = 1;
  340.  
  341.          for(coord2.y = -1; coord2.y <= 1; coord2.y++){
  342.  
  343.              for(coord2.x = -1; coord2.x <= 1; coord2.x++){
  344.  
  345.                  coord3.x = coord.x + coord2.x;
  346.                  coord3.y = coord.y + coord2.y;
  347.                  clip_coord(&coord3, size); /* make sure coord is not off image */
  348.                  median[pixelno++] = getsource(coord3);
  349.  
  350.              }
  351.  
  352.          }
  353.  
  354.         /*
  355.          * sort array median into numerical order so that the median (middle)
  356.          * value can be found
  357.          */
  358.  
  359.          for(outerloop = 2; outerloop <= 9; outerloop++){
  360.  
  361.              pixel = median[outerloop];
  362.  
  363.              bubblesort_subloop(&outerloop, &innerloop, &pixel, &median);
  364.  
  365.              median[innerloop + 1] = pixel;
  366.  
  367.          }
  368.  
  369.         /*
  370.          * place median value in destination image
  371.          */
  372.          putdest(coord, median[5]);
  373.       
  374.      }
  375.  
  376.   }
  377.  
  378.   Hourglass_Off();
  379.  
  380. }
  381.  
  382. void bubblesort_subloop(int *outerloop, int *innerloop, int *pixel, int (*median)[10])
  383. {
  384.  /*
  385.   * subloop for bubblesort used in median filter
  386.   * removes need for gotos (algorithm was originally in FORTRAN!)
  387.   */
  388.  
  389.   for(*innerloop = *outerloop - 1; *innerloop >= 1; *innerloop = *innerloop - 1){
  390.  
  391.       if( (*median)[*innerloop] < *pixel )
  392.          return;
  393.  
  394.       (*median)[*innerloop + 1] = (*median)[*innerloop];
  395.  
  396.   }
  397.  
  398.   *innerloop = 0;
  399.  
  400. }
  401.  
  402. /******************************************************************************/
  403.  
  404. void Process_GreyHistorgram(int sourceimage, wimp_point *size, int (*greyhist)[256])
  405. {
  406.  /*
  407.   * calculates grey level histogram for 'sourceimage' and places it in the array
  408.   * 'greyhist'
  409.   */
  410.   wimp_point coord;
  411.   int greylevel;
  412.  
  413.   Hourglass_On();
  414.  
  415.  /*
  416.   * initialise 'greyhist' array to zero
  417.   */
  418.   for(greylevel = 0; greylevel < 256; greylevel++){
  419.  
  420.       (*greyhist)[greylevel] = 0;
  421.  
  422.   }
  423.  
  424.  /*
  425.   * calculate histogram
  426.   */
  427.   for(coord.y = 0; coord.y < size->y; coord.y++){
  428.  
  429.       for(coord.x = 0; coord.x < size->x; coord.x++){
  430.  
  431.           greylevel = SpriteWin_GetPixel(&coord, sourceimage);
  432.  
  433.           (*greyhist)[greylevel]++;
  434.  
  435.       }
  436.  
  437.   }
  438.  
  439.   Hourglass_Off();
  440.  
  441. }
  442.  
  443. /******************************************************************************/
  444.  
  445. void Process_CumulativeHistorgram(int (*greyhist)[256], int (*cuhist)[256])
  446. {
  447.  /*
  448.   * takes grey level histogram for 'greyhist' and calculates the cumulative
  449.   * histogram and places it in 'cuhist'
  450.   * NOTE: 'greyhist' and 'cuhist' can be the same array
  451.   */
  452.   int greylevel;
  453.   int sum;
  454.  
  455.   Hourglass_On();
  456.  
  457.   sum = 0;
  458.  
  459.   for(greylevel = 0; greylevel < 256; greylevel++){
  460.  
  461.       sum += (*greyhist)[greylevel];
  462.  
  463.       (*cuhist)[greylevel] = sum;
  464.  
  465.   }
  466.  
  467.   Hourglass_Off();
  468.  
  469. }
  470.  
  471. /******************************************************************************/
  472.  
  473. void Process_HistogramEq(int sourceimage, wimp_point *size, char (*greymap)[])
  474. {
  475.  /*
  476.   * calculates grey level histogram for 'sourceimage' and uses it to do calculate
  477.   * the greymap for histogram equalization
  478.   */
  479.   int histogram[256];
  480.   int cumulative[256];
  481.   int totalpixels;
  482.   int greylevel;
  483.   float numerator;
  484.  
  485.   Hourglass_On();
  486.  
  487.  /*
  488.   * calculate grey level histogram
  489.   */
  490.   Process_GreyHistorgram(sourceimage, size, &histogram);
  491.       
  492.  /*
  493.   * calculate cumulative grey level histogram
  494.   */
  495.   Process_CumulativeHistorgram(&histogram, &cumulative);
  496.  
  497.  /*
  498.   * calculate lookup table for histogram equalization
  499.   * equation is:              nogreys - 1
  500.   *              newgrey[n] = -----------  * cumulative[n]
  501.   *                           totalpixels
  502.   */
  503.   totalpixels = size->x * size->y;
  504.   numerator = (float)(256.0 - 1.0) / (float)totalpixels;
  505.  
  506.   for(greylevel = 0; greylevel < 256; greylevel++){
  507.  
  508.       (*greymap)[greylevel] = (char) (numerator * cumulative[greylevel]);
  509.  
  510.   }
  511.  
  512.   Hourglass_Off();
  513.  
  514. }
  515.  
  516. /******************************************************************************/
  517.  
  518. void Process_Scale(int sourceimage, int destimage,
  519.                    wimp_point *sourcesize, wimp_point *destsize)
  520. {
  521.  /*
  522.   * scales 'sourceimage' to size of 'destimage' using biliner interpolation and
  523.   * resampling
  524.   */
  525.  
  526.   /*
  527.    * Using the grey levels of the 4 nearest neighbours, the new grey level is
  528.    * a*x + b*y + c*x*y + d = greylevel
  529.    * where a, b, c and d are calculated by solving the 4 simultanious equations.
  530.    * By making the top left NN be always 0,0 when calculating, the same solution
  531.    * to the equation can be used every time, ie.
  532.    * where the NN are at   1     2
  533.    *                      0,0   1,0
  534.    *                      1,0   1,1
  535.    *                       3     4
  536.    * a = g2 - g1     b = g3 - g1    c = g4 - g2 + g1 - g3    d = g1
  537.    */
  538.   int a, b, c, d, xi, yi;
  539.   int scalefactorx, scalefactory;
  540.   int g1, g2, g3, g4;
  541.   wimp_point sourcepixel;
  542.   wimp_point destpixel;
  543.   wimp_point NNtopleft;
  544.   int newgrey;
  545.  
  546.   spritewin_block *block;
  547.   char *sourceimagedata;
  548.   int sourcelinelength;
  549.   char *destimagedata;
  550.   int destlinelength;
  551.  
  552.  /*
  553.   * set up variables for fast sprite access
  554.   */
  555.   block = SpriteWin_GetImageBlock(sourceimage);
  556.   sourceimagedata = (char *) block->spritearea + block->image;
  557.   sourcelinelength = block->linebytes;
  558.  
  559.   block = SpriteWin_GetImageBlock(destimage);
  560.   destimagedata = (char *) block->spritearea + block->image;
  561.   destlinelength = block->linebytes;
  562.  
  563.   Hourglass_On();
  564.  
  565.  /*
  566.   * calculate scalefactor that maps coordinate in destination image plane to
  567.   * those in the source image plane
  568.   */
  569.   scalefactorx = (sourcesize->x << 10) / destsize->x;
  570.   scalefactory = (sourcesize->y << 10) / destsize->y;
  571.  
  572.   for(destpixel.y = 0; destpixel.y < destsize->y; destpixel.y++){
  573.  
  574.      for(destpixel.x = 0; destpixel.x < destsize->x; destpixel.x++){
  575.  
  576.          Hourglass_Percentage( (destpixel.y * 100) / destsize->y);
  577.  
  578.         /*
  579.          * calculate coord of destination image point in source frame of reference
  580.          */
  581.          xi = destpixel.x * scalefactorx;
  582.          yi = destpixel.y * scalefactory;
  583.  
  584.         /*
  585.          * calculate coord of top left nearest neighbour in source image
  586.          */
  587.          NNtopleft.x = xi >> 10;
  588.          NNtopleft.y = yi >> 10;
  589.  
  590.         /*
  591.          * get grey scale values of nearest neighbours
  592.          */
  593.          sourcepixel = NNtopleft;
  594.          g1 = getsource(sourcepixel);
  595.          sourcepixel.x++;
  596.          clip_coord(&sourcepixel, sourcesize); /* make sure coord is not off image */
  597.          g2 = getsource(sourcepixel);
  598.          sourcepixel.x = NNtopleft.x;
  599.          sourcepixel.y = NNtopleft.y + 1;
  600.          g3 = getsource(sourcepixel);
  601.          sourcepixel.x++;
  602.          clip_coord(&sourcepixel, sourcesize); /* make sure coord is not off image */
  603.          g4 = getsource(sourcepixel);
  604.  
  605.         /*
  606.          * calculate constants
  607.          */
  608.          a = (g2 - g1);
  609.          b = (g3 - g1);
  610.          c = (g4 - g2 + g1 - g3);
  611.          d = g1 << 10;
  612.  
  613.         /*
  614.          * calculate coords of point in nearest neighbour frame of reference
  615.          */
  616.          xi = xi - (NNtopleft.x << 10);
  617.          yi = yi - (NNtopleft.y << 10);
  618.  
  619.         /*
  620.          * calculate new grey level for destination image
  621.          */
  622.          newgrey = (a*xi + b*yi + c* ((xi*yi) >> 10) + d) >> 10;
  623.  
  624.          clip_pixel(&newgrey);
  625.  
  626.          putdest(destpixel, newgrey);
  627.      }
  628.   }
  629.  
  630.   Hourglass_Off();
  631.  
  632. }
  633.  
  634. /******************************************************************************/
  635.  
  636. void Process_Mix(int source1, int source2, int destimage, int image1percent,
  637.                  wimp_point *size)
  638. {
  639.  /*
  640.   * mixes source1 and source2 according to the percentage in image1percent and
  641.   * puts the result in destimage.
  642.   * NOTE: destimage can be the same as source2
  643.   */
  644.   wimp_point pixel;
  645.   int value;
  646.   int image2percent;
  647.  
  648.   spritewin_block *block;
  649.   char *sourceimagedata;
  650.   int sourcelinelength;
  651.   char *source2imagedata;
  652.   int source2linelength;
  653.   char *destimagedata;
  654.   int destlinelength;
  655.  
  656.  /*
  657.   * set up variables for fast sprite access
  658.   */
  659.   block = SpriteWin_GetImageBlock(source1);
  660.   sourceimagedata = (char *) block->spritearea + block->image;
  661.   sourcelinelength = block->linebytes;
  662.  
  663.   block = SpriteWin_GetImageBlock(source2);
  664.   source2imagedata = (char *) block->spritearea + block->image;
  665.   source2linelength = block->linebytes;
  666.  
  667.   block = SpriteWin_GetImageBlock(destimage);
  668.   destimagedata = (char *) block->spritearea + block->image;
  669.   destlinelength = block->linebytes;
  670.  
  671.   image2percent = 100 - image1percent;
  672.  
  673.   Hourglass_On();
  674.  
  675.   for(pixel.y = 0; pixel.y < size->y; pixel.y++){
  676.  
  677.      Hourglass_Percentage( (pixel.y * 100) / size->y);
  678.  
  679.      for(pixel.x = 0; pixel.x < size->x; pixel.x++){
  680.  
  681.          value =  ((getsource(pixel) << 2) * image1percent) / 100;
  682.          value += ((getsource2(pixel) << 2) * image2percent) / 100;
  683.  
  684.          value = value >> 2;
  685.  
  686.          /*clip_pixel(&value);*/
  687.  
  688.          putdest(pixel, value);
  689.      }
  690.   }
  691.  
  692.   Hourglass_Off();
  693.  
  694. }
  695.  
  696. /******************************************************************************/
  697.  
  698. void Process_GreyMap(int sourceimage, int destimage, wimp_point *size, char (*greymap)[])
  699. {
  700.  /*
  701.   * map the greylevels in the 'sourceimage' to the new values set out using the bargraph
  702.   * from the window in 'barmap' and put the new image in 'destimage'
  703.   */
  704.   wimp_point pixel;
  705.  
  706.   spritewin_block *block;
  707.   char *sourceimagedata;
  708.   int sourcelinelength;
  709.   char *destimagedata;
  710.   int destlinelength;
  711.  
  712.  /*
  713.   * set up variables for fast sprite access
  714.   */
  715.   block = SpriteWin_GetImageBlock(sourceimage);
  716.   sourceimagedata = (char *) block->spritearea + block->image;
  717.   sourcelinelength = block->linebytes;
  718.  
  719.   block = SpriteWin_GetImageBlock(destimage);
  720.   destimagedata = (char *) block->spritearea + block->image;
  721.   destlinelength = block->linebytes;
  722.  
  723.   Hourglass_On();
  724.  
  725.  /*
  726.   * create new image using greylevel lookup table
  727.   */
  728.  
  729.   for(pixel.y = 0; pixel.y < size->y; pixel.y++){
  730.  
  731.      Hourglass_Percentage( (pixel.y * 100) / size->y);
  732.  
  733.      for(pixel.x = 0; pixel.x < size->x; pixel.x++){
  734.  
  735.          putdest(pixel, (*greymap)[getsource(pixel)]);
  736.      }
  737.   }
  738.  
  739.   Hourglass_Off();
  740.  
  741. }
  742.  
  743. /******************************************************************************/
  744.  
  745. void Process_SLCE(int sourceimage, wimp_point *size, char (*greymap)[])
  746. {
  747.  /*
  748.   * calculates grey level histogram for 'sourceimage' Saturating Linear Contrast 
  749.   * Enhancement
  750.   */
  751.   int histogram[256];
  752.   int greylevel;
  753.   int sum;
  754.   double mean;
  755.   double sumsquares;
  756.   double sd;
  757.   double grad, yinter;
  758.   int dhigh, dlow;
  759.  
  760.   Hourglass_On();
  761.  
  762.  /*
  763.   * calculate grey level histogram
  764.   */
  765.   Process_GreyHistorgram(sourceimage, size, &histogram);
  766.  
  767.  /*
  768.   * calculate mean of the grey level histogram
  769.   */
  770.   for(greylevel = 0; greylevel < 256; greylevel++)
  771.       sum += histogram[greylevel] * greylevel;
  772.  
  773.   mean = (double) sum / (double) (size->x * size->y);
  774.  
  775.  /*
  776.   * calculate standard deviation of the grey level histogram
  777.   */
  778.   for(greylevel = 0; greylevel < 256; greylevel++)
  779.       sumsquares += ((mean - (double) greylevel) * (mean - (double) greylevel)) *
  780.                     (double) histogram[greylevel];
  781.  
  782.   sd = sqrt( sumsquares / (double) (size->x * size->y) );
  783.  
  784.  
  785.  /*
  786.   * calculate lookup table for SLCE
  787.   */
  788.   dhigh = (int) ((3.0 * sd) + mean + 0.5);
  789.   dlow = (int) (mean - (3 * sd) + 0.5);
  790.  
  791.   if(dlow < 0)
  792.      dlow = 0;
  793.  
  794.   if(dhigh > 255)
  795.      dhigh = 255;
  796.  
  797.  /*
  798.   * below low point all are 0
  799.   */
  800.   for(greylevel = 0; greylevel < dlow; greylevel++)
  801.       (*greymap)[greylevel] = 0;
  802.  
  803.  /*
  804.   * between dlow and dhigh the levels are a linear line
  805.   * gradient 'grad' and yintercept 'yinter'
  806.   */
  807.   grad = 255.0 / ( ((double) dhigh) - ((double) dlow) );
  808.   yinter = - ( grad * ((double) dlow) );
  809.   for(greylevel = dlow; greylevel <= dhigh; greylevel++)
  810.       (*greymap)[greylevel] = (int) ( ( grad * ((double) greylevel) ) + yinter + 0.5);
  811.  
  812.  /*
  813.   * above dhigh the levels are all 255
  814.   */
  815.   for(greylevel = dhigh; greylevel < 256; greylevel++)
  816.       (*greymap)[greylevel] = 255;
  817.  
  818.   Hourglass_Off();
  819.  
  820. }
  821.  
  822. /******************************************************************************
  823.  *                             misc routines                                  *
  824.  ******************************************************************************/
  825.  
  826. void clip_pixel(int *pixel)
  827. {
  828.  /*
  829.   * clip the pixel value to the allowed range
  830.   */
  831.  
  832.   if(*pixel > 255)
  833.      *pixel = 255;
  834.  
  835.   if(*pixel < 0)
  836.      *pixel = 0;
  837.      
  838. }
  839.  
  840. /******************************************************************************/
  841.  
  842. void clip_coord(wimp_point *coord, wimp_point *imagesize)
  843. {
  844.  /*
  845.   * clips coordinate so that it is in the image.
  846.   * Therefore, outside values will use those on the edge of the images
  847.   */
  848.  
  849.   if(coord->x < 0)
  850.      coord->x = 0;
  851.  
  852.   if(coord->x >= imagesize->x)
  853.      coord->x = imagesize->x - 1;
  854.  
  855.   if(coord->y < 0)
  856.      coord->y = 0;
  857.  
  858.   if(coord->y >= imagesize->y)
  859.      coord->y = imagesize->y - 1;
  860.              
  861. }
  862.