home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / graphics / utility / mgif40.lzh / MGIF40 / SOURCES / PROCESS.C < prev    next >
C/C++ Source or Header  |  1993-08-25  |  39KB  |  2,250 lines

  1. #undef DBL_LOOP            /* def for for(x..., for(y... loops */
  2. #undef INL_SORT            /* def to inline piksrt() in median() */
  3.  
  4. /*
  5.  *    process.c - all the image processing functions.
  6.  */
  7.  
  8. /* Last changed by Bill 91/6/9 */
  9. static char *sccsid = "@(#) process.c 1.4 rosenkra(13) 92/11/09 Klockars\0\0";
  10.  
  11. /* #include <stdio.h>    Included via proto.h */
  12. /* #include "mgif.h"    Included via proto.h */
  13.  
  14. #ifndef __LATTICE__
  15. #include "proto.h"    /* Lattice C should have this precompiled */
  16. #endif
  17.  
  18. /* NEW, used to be constants */
  19. extern long MAXRAW, MAXIMG;
  20.  
  21. /*
  22.  *    local functions
  23.  */
  24.  
  25. /*
  26. int        larger ();        /* frame processes... *
  27. int        zoom ();
  28. int        smaller ();
  29. int        cut ();
  30. int        rotate ();
  31. int        mirror ();
  32. int        convolve ();        /* area processes... *
  33. int        blur ();
  34. int        median ();
  35. int        piksrt ();
  36. int        logscale ();        /* point processes... *
  37. int        Log2x10 ();
  38. int        contrast ();
  39. int        brighten ();
  40. int        invert ();
  41. int        threshold ();
  42. int        histeq ();
  43. int        redistribute ();
  44. int        copyrast ();        /* others... *
  45. */
  46.  
  47. /*
  48.  *    external functions
  49.  */
  50.  
  51. /*
  52. extern int    do_hist ();
  53. extern int    copyrast ();
  54. */
  55.  
  56. /*------------------------------*/
  57. /*    larger            */
  58. /*------------------------------*/
  59.  
  60. #define L_BOTH        0
  61. #define L_HOR        1
  62. #define L_VERT        2
  63.  
  64. int larger (pras, w, h, opt, ptrans)
  65. uchar_t           *pras;
  66. int        w;
  67. int        h;
  68. int        opt;        /* checked by caller! */
  69. uchar_t           *ptrans;
  70. {
  71.  
  72. /*
  73.  *    enlarge an image (so far 320x200 -> 640x400). return 1 if
  74.  *    successful, else 0.
  75.  */
  76.  
  77.     register uchar_t       *pr;
  78.     register uchar_t       *pt;
  79.     register long        x;
  80.     register long        y;
  81.     long            x2;
  82.     long            y2;
  83.     register long        wold;
  84.     long            hold;
  85.     register long        w2;
  86.     long            h2;
  87.  
  88.  
  89.     /*
  90.      *   fail if enlarged image will be too big for buffer
  91.      */
  92. #if 0
  93.     if ((w > 320) || (h > 200))
  94.         return (0);
  95. #endif
  96.     switch (opt)
  97.     {
  98.     case L_BOTH:
  99.         if (4L * (long) w * (long) h > MAXIMG)
  100.             return (0);
  101.         break;
  102.     case L_HOR:
  103.         if (2L * (long) w * (long) h > MAXIMG)
  104.             return (0);
  105.         break;
  106.     case L_VERT:
  107.         if (2L * (long) w * (long) h > MAXIMG)
  108.             return (0);
  109.         break;
  110.     }
  111.  
  112.  
  113.  
  114.     /*
  115.      *   here we always do the transform in situ (in ptrans)...
  116.      */
  117.     if (pras == ptrans)
  118.     {
  119.         /*
  120.          *   do in place...
  121.          */
  122.         pr = pras;
  123.         pt = pras;
  124.     }
  125.     else
  126.     {
  127.         /*
  128.          *   copy to new image
  129.          */
  130.         pr = pras;
  131.         pt = ptrans;
  132.  
  133.         /*
  134.          *   first copy orig image to transform image
  135.          */
  136.         copyrast (pr, w, h, pt);
  137.         pr = ptrans;
  138.     }
  139.  
  140.  
  141.     wold = w;
  142.     hold = h;
  143.     switch (opt)
  144.     {
  145.     case L_BOTH:
  146.         /*
  147.          *   set new sizes
  148.          */
  149.         w2 = wold*2L;
  150.         h2 = hold*2L;
  151.  
  152.  
  153.         /*
  154.          *   shift existing data:
  155.          *
  156.          *      0123456789
  157.          *    0|**********|            *=existing pixels
  158.          *    1|**********|            +=new pixels
  159.          *    .
  160.          *    .
  161.          *         |
  162.          *         v
  163.          *                1111111111
  164.          *      01234567890123456789
  165.          *    0|                    |
  166.          *    1| + + + + + + + + + +|
  167.          *    2|                    |
  168.          *    3| + + + + + + + + + +|
  169.          *    .
  170.          *    .
  171.          */
  172.         for (y = hold-1; y >= 0; y--)
  173.         {
  174.             for (x = wold-1; x >= 0; x--)
  175.             {
  176.                 x2 = (2*x)+1;
  177.                 y2 = (2*y)+1;
  178.                 pt[y2*w2 + x2] = pt[y*wold + x];
  179.             }
  180.         }
  181.  
  182.  
  183.         /*
  184.          *   now make intermediate points within row (average):
  185.          *
  186.          *                1111111111
  187.          *      01234567890123456789
  188.          *    0|                    |        *=existing pixels
  189.          *    1|+*+*+*+*+*+*+*+*+*+*|        +=new pixels
  190.          *    2|                    |
  191.          *    3|+*+*+*+*+*+*+*+*+*+*|
  192.          *    .
  193.          *    .
  194.          */
  195.         for (y = 1; y < h2; y += 2)
  196.         {
  197.             /* first point is duplicate of second */
  198.             pt[y*w2 + 0] = pt[y*w2 + 1];
  199.  
  200.             /* others are average */
  201.             for (x = 2; x < w2; x += 2)
  202.             {
  203.                 pt[y*w2 + x] = (uchar_t) (
  204.                      ((uint_t) pt[y*w2 + (x-1)]
  205.                     + (uint_t) pt[y*w2 + (x+1)]) / 2);
  206.             }
  207.         }
  208.  
  209.  
  210.         /*
  211.          *   first row is duplicate of second row:
  212.          *
  213.          *                1111111111
  214.          *      01234567890123456789
  215.          *    0|++++++++++++++++++++|<---
  216.          *    1|********************|        *=existing pixels
  217.          *    2|                    |        +=new pixels
  218.          *    3|********************|
  219.          *    .
  220.          *    .
  221.          */
  222.         for (x = 0; x < w2; x++)
  223.         {
  224.             pt[x] = pt[w2 + x];
  225.         }
  226.  
  227.  
  228.         /*
  229.          *   finally, make new rows (average):
  230.          *
  231.          *                1111111111
  232.          *      01234567890123456789
  233.          *    0|********************|        *=existing pixels
  234.          *    1|********************|        +=new pixels
  235.          *    2|++++++++++++++++++++|<---
  236.          *    3|********************|
  237.          *    .
  238.          *    .
  239.          */
  240.         for (y = 2; y < h2; y += 2)
  241.         {
  242.             for (x = 0; x < w2; x++)
  243.             {
  244.                 pt[y*w2 + x] = (uchar_t) (
  245.                      ((uint_t) pt[(y-1)*w2 + x]
  246.                     + (uint_t) pt[(y+1)*w2 + x]) / 2);
  247.             }
  248.         }
  249.         break;
  250.  
  251.  
  252.     case L_HOR:
  253.         /*
  254.          *   set new sizes
  255.          */
  256.         w2 = wold*2L;
  257.         h2 = hold;
  258.  
  259.  
  260.         /*
  261.          *   shift existing data:
  262.          *
  263.          *      0123456789
  264.          *    0|**********|            *=existing pixels
  265.          *    1|**********|            +=new pixels
  266.          *         .
  267.          *         .
  268.          *         |
  269.          *         v
  270.          *                1111111111
  271.          *      01234567890123456789
  272.          *    0| + + + + + + + + + +|
  273.          *    1| + + + + + + + + + +|
  274.          *    .
  275.          *    .
  276.          */
  277.         for (y = hold-1; y >= 0; y--)
  278.         {
  279.             for (x = wold-1; x >= 0; x--)
  280.             {
  281.                 x2 = (2*x)+1;
  282.                 pt[y*w2 + x2] = pt[y*wold + x];
  283.             }
  284.         }
  285.  
  286.  
  287.         /*
  288.          *   now make intermediate points within row (average):
  289.          *
  290.          *                1111111111
  291.          *      01234567890123456789
  292.          *    0|+*+*+*+*+*+*+*+*+*+*|        *=existing pixels
  293.          *    1|+*+*+*+*+*+*+*+*+*+*|        +=new pixels
  294.          *    .
  295.          *    .
  296.          */
  297.         for (y = 0; y < hold; y++)
  298.         {
  299.             /* first point is duplicate of second */
  300.             pt[y*w2 + 0] = pt[y*w2 + 1];
  301.  
  302.             /* others are average */
  303.             for (x = 2; x < w2; x += 2)
  304.             {
  305.                 pt[y*w2 + x] = (uchar_t) (
  306.                      ((uint_t) pt[y*w2 + (x-1)]
  307.                     + (uint_t) pt[y*w2 + (x+1)]) / 2);
  308.             }
  309.         }
  310.         break;
  311.  
  312.     case L_VERT:
  313.         /*
  314.          *   set new sizes
  315.          */
  316.         w2 = wold;
  317.         h2 = hold*2L;
  318.  
  319.  
  320.         /*
  321.          *   shift existing data:
  322.          *
  323.          *      0123456789
  324.          *    0|**********|            *=existing pixels
  325.          *    1|**********|            +=new pixels
  326.          *    .
  327.          *    .
  328.          *         |
  329.          *         v
  330.          *      0123456789
  331.          *    0|          |
  332.          *    1|++++++++++|
  333.          *    2|          |
  334.          *    3|++++++++++|
  335.          *    .
  336.          *    .
  337.          */
  338.         for (y = hold-1; y >= 0; y--)
  339.         {
  340.             for (x = wold-1; x >= 0; x--)
  341.             {
  342.                 y2 = (2*y)+1;
  343.                 pt[y2*wold + x] = pt[y*wold + x];
  344.             }
  345.         }
  346.  
  347.  
  348.         /*
  349.          *   first row is duplicate of second row:
  350.          *
  351.          *      0123456789
  352.          *    0|++++++++++|<---
  353.          *    1|**********|            *=existing pixels
  354.          *    2|          |            +=new pixels
  355.          *    3|**********|
  356.          *    .
  357.          *    .
  358.          */
  359.         for (x = 0; x < wold; x++)
  360.         {
  361.             pt[x] = pt[wold + x];
  362.         }
  363.  
  364.  
  365.         /*
  366.          *   finally, make new rows (average):
  367.          *
  368.          *      0123456789
  369.          *    0|**********|        *=existing pixels
  370.          *    1|**********|        +=new pixels
  371.          *    2|++++++++++|<---
  372.          *    3|**********|
  373.          *    .
  374.          *    .
  375.          */
  376.         for (y = 2; y < h2; y += 2)
  377.         {
  378.             for (x = 0; x < wold; x++)
  379.             {
  380.                 pt[y*wold + x] = (uchar_t) (
  381.                      ((uint_t) pt[(y-1)*wold + x]
  382.                     + (uint_t) pt[(y+1)*wold + x]) / 2);
  383.             }
  384.         }
  385.         break;
  386.     }
  387.  
  388.  
  389.     return (1);
  390. }
  391.  
  392.  
  393.  
  394.  
  395. /*------------------------------*/
  396. /*    zoom            */
  397. /*------------------------------*/
  398. int zoom (pras, w, h, xstart, ystart, ptrans)
  399. uchar_t           *pras;
  400. int        w;
  401. int        h;
  402. int        xstart;
  403. int        ystart;
  404. uchar_t           *ptrans;
  405. {
  406.  
  407. /*
  408.  *    zoom in and enlarge an image (so far 2x) starting at xstart,ystart.
  409.  *    return 1 if successful, else 0.
  410.  */
  411.  
  412.     register uchar_t       *pr;
  413.     register uchar_t       *pt;
  414.     register long        x;
  415.     register long        y;
  416.     long            x2;
  417.     long            y2;
  418.     register long        wold;
  419.     long            hold;
  420.     register long        w2;
  421.     long            h2;
  422.  
  423.  
  424.  
  425.     /*
  426.      *   enlarged image should ALWAYS fit in buffer!
  427.      *
  428.      *   here we always do the transform in situ (in ptrans)...
  429.      */
  430.     if (pras == ptrans)
  431.     {
  432.         /*
  433.          *   do in place. pr points to "cut" area, pt to start
  434.          */
  435.         pr = &pras[xstart + (ystart-1)*w];
  436.         pt = pras;
  437.  
  438.         /*
  439.          *   shift smaller image to ul corner of pt
  440.          */
  441.         if ((xstart != 0) && (ystart != 0))
  442.         {
  443.             for (y = 0L; y < h/2; y++)
  444.             {
  445.                 for (x = 0L; x < w/2; x++)
  446.                 {
  447.                     pt[x + w*(y-1)/2] = pr[x + w*(y-1)];
  448.                 }
  449.             }
  450.         }
  451.     }
  452.     else
  453.     {
  454.         /*
  455.          *   copy to new image
  456.          */
  457.         pr = &pras[xstart + (ystart-1)*w];
  458.         pt = ptrans;
  459.  
  460.         /*
  461.          *   first copy orig image to transform image
  462.          */
  463.         for (y = 0L; y < h/2; y++)
  464.         {
  465.             for (x = 0L; x < w/2; x++)
  466.             {
  467.                 pt[x + w*(y-1)/2] = pr[x + w*(y-1)];
  468.             }
  469.         }
  470.     }
  471.  
  472.  
  473.  
  474.     /*
  475.      *   set new sizes
  476.      */
  477.     wold = w/2L;
  478.     hold = h/2L;
  479.     w2   = wold*2L;
  480.     h2   = hold*2L;
  481.  
  482.  
  483.     /*
  484.      *   shift existing data:
  485.      *
  486.      *      0123456789
  487.      *    0|**********|            *=existing pixels
  488.      *    1|**********|            +=new pixels
  489.      *    .
  490.      *    .
  491.      *         |
  492.      *         v
  493.      *                1111111111
  494.      *      01234567890123456789
  495.      *    0|                    |
  496.      *    1| + + + + + + + + + +|
  497.      *    2|                    |
  498.      *    3| + + + + + + + + + +|
  499.      *    .
  500.      *    .
  501.      */
  502.     for (y = hold-1; y >= 0; y--)
  503.     {
  504.         for (x = wold-1; x >= 0; x--)
  505.         {
  506.             x2 = (2*x)+1;
  507.             y2 = (2*y)+1;
  508.             pt[y2*w2 + x2] = pt[y*wold + x];
  509.         }
  510.     }
  511.  
  512.  
  513.     /*
  514.      *   now make intermediate points within row (average):
  515.      *
  516.      *                1111111111
  517.      *      01234567890123456789
  518.      *    0|                    |        *=existing pixels
  519.      *    1|+*+*+*+*+*+*+*+*+*+*|        +=new pixels
  520.      *    2|                    |
  521.      *    3|+*+*+*+*+*+*+*+*+*+*|
  522.      *    .
  523.      *    .
  524.      */
  525.     for (y = 1; y < h2; y += 2)
  526.     {
  527.         /* first point is duplicate of second */
  528.         pt[y*w2 + 0] = pt[y*w2 + 1];
  529.  
  530.         /* others are average */
  531.         for (x = 2; x < w2; x += 2)
  532.         {
  533.             pt[y*w2 + x] = (uchar_t) (
  534.                  ((uint_t) pt[y*w2 + (x-1)]
  535.                 + (uint_t) pt[y*w2 + (x+1)]) / 2);
  536.         }
  537.     }
  538.  
  539.  
  540.     /*
  541.      *   first row is duplicate of second row:
  542.      *
  543.      *                1111111111
  544.      *      01234567890123456789
  545.      *    0|++++++++++++++++++++|<---
  546.      *    1|********************|        *=existing pixels
  547.      *    2|                    |        +=new pixels
  548.      *    3|********************|
  549.      *    .
  550.      *    .
  551.      */
  552.     for (x = 0; x < w2; x++)
  553.     {
  554.         pt[x] = pt[w2 + x];
  555.     }
  556.  
  557.  
  558.     /*
  559.      *   finally, make new rows (average):
  560.      *
  561.      *                1111111111
  562.      *      01234567890123456789
  563.      *    0|********************|        *=existing pixels
  564.      *    1|********************|        +=new pixels
  565.      *    2|++++++++++++++++++++|<---
  566.      *    3|********************|
  567.      *    .
  568.      *    .
  569.      */
  570.     for (y = 2; y < h2; y += 2)
  571.     {
  572.         for (x = 0; x < w2; x++)
  573.         {
  574.             pt[y*w2 + x] = (uchar_t) (
  575.                  ((uint_t) pt[(y-1)*w2 + x]
  576.                 + (uint_t) pt[(y+1)*w2 + x]) / 2);
  577.         }
  578.     }
  579.  
  580.     return (1);
  581. }
  582.  
  583.  
  584.  
  585.  
  586. /*------------------------------*/
  587. /*    smaller            */
  588. /*------------------------------*/
  589.  
  590. #define S_BOTH        0
  591. #define S_HOR        1
  592. #define S_VERT        2
  593.  
  594. int smaller (pras, w, h, opt, ptrans)
  595. uchar_t           *pras;
  596. int        w;
  597. int        h;
  598. int        opt;        /* checked by caller! */
  599. uchar_t           *ptrans;
  600. {
  601.  
  602. /*
  603.  *    reduce an image by half. return 1 if successful, else 0.
  604.  */
  605.  
  606.     register uchar_t       *pr;
  607.     register uchar_t       *pt;
  608.     register long        x;
  609.     register long        y;
  610.     register long        wold;
  611.     register long        w2;
  612.     long            hold;
  613.     long            h2;
  614.  
  615.  
  616.     /*
  617.      *   there is a limit to what is practical...
  618.      */
  619.     if ((w < 10) || (h < 10))
  620.         return (0);
  621.  
  622.  
  623.     if (pras == ptrans)
  624.     {
  625.         /*
  626.          *   do in place...
  627.          */
  628.         pr = pras;
  629.         pt = pras;
  630.     }
  631.     else
  632.     {
  633.         /*
  634.          *   copy to new image
  635.          */
  636.         pr = pras;
  637.         pt = ptrans;
  638.     }
  639.  
  640.  
  641.     /*
  642.      *   do it. skip odd lines and pixels
  643.      */
  644.     wold = w;
  645.     hold = h;
  646.     switch (opt)
  647.     {
  648.     case S_BOTH:
  649.         /*
  650.          *   set new sizes
  651.          */
  652.         w2 = wold/2L;
  653.         h2 = hold/2L;
  654.  
  655.         for (y = 0; y < h2; y++)
  656.         {
  657.             for (x = 0; x < w2; x++)
  658.             {
  659.                 pt[y*w2 + x] = pr[2*y*wold + x*2];
  660.             }
  661.         }
  662.         break;
  663.  
  664.     case S_HOR:
  665.         /*
  666.          *   set new sizes
  667.          */
  668.         w2 = wold/2L;
  669.         h2 = hold;
  670.  
  671.         for (y = 0; y < h2; y++)
  672.         {
  673.             for (x = 0; x < w2; x++)
  674.             {
  675.                 pt[y*w2 + x] = pr[y*wold + x*2];
  676.             }
  677.         }
  678.         break;
  679.  
  680.     case S_VERT:
  681.         /*
  682.          *   set new sizes
  683.          */
  684.         w2 = wold;
  685.         h2 = hold/2L;
  686.  
  687.         for (y = 0; y < h2; y++)
  688.         {
  689.             for (x = 0; x < w2; x++)
  690.             {
  691.                 pt[y*w2 + x] = pr[2*y*wold + x];
  692.             }
  693.         }
  694.         break;
  695.     }
  696.  
  697.     return (1);
  698. }
  699.  
  700.  
  701.  
  702.  
  703. /*------------------------------*/
  704. /*    cut            */
  705. /*------------------------------*/
  706. int cut (pras, w, h, x1, y1, x2, y2, ptrans)
  707. uchar_t           *pras;
  708. int        w;
  709. int        h;
  710. int        x1, y1;
  711. int        x2, y2;
  712. uchar_t           *ptrans;
  713. {
  714.  
  715. /*
  716.  *    cut out a section of the image from pras to ptrans
  717.  */
  718.  
  719.     register uchar_t       *pr;
  720.     register uchar_t       *pt;
  721.     register long        x;
  722.     register long        y;
  723.     register long        wold;
  724.     register long        w2;
  725.     register long        h2;
  726.  
  727.  
  728.     /*
  729.      *   check for bad coords...
  730.      */
  731.     if ((x1 >= x2) || (y1 >= y2))
  732.         return (0);
  733.     if ((x1 < 0) || (x2 < 0) || (y1 < 0) || (y2 < 0))
  734.         return (0);
  735.     if ((x2 >= w) || (y2 >= h))
  736.         return (0);
  737. #if 0
  738.     if ((x2 > 639) || (y2 > 399))
  739.         return (0);
  740.     if ((x2 - x1) > w)        /* don't fail just limit the cut */
  741.         x2 = x1 + w;
  742.     if ((y2 - y1) > h)
  743.         y2 = y1 + h;
  744. #endif
  745.  
  746.  
  747.     /*
  748.      *   set up pointers...
  749.      */
  750.     if (pras == ptrans)
  751.     {
  752.         /*
  753.          *   do in place...
  754.          */
  755.         pr = pras;
  756.         pt = pras;
  757.     }
  758.     else
  759.     {
  760.         /*
  761.          *   copy to new image
  762.          */
  763.         pr = pras;
  764.         pt = ptrans;
  765.     }
  766.     
  767.  
  768.     /*
  769.      *   do it...
  770.      */
  771.     wold = w;
  772.     w2   = x2 - x1 + 1;
  773.     h2   = y2 - y1 + 1;
  774.     for (y = 0; y < h2; y++)
  775.     {
  776.         for (x = 0; x < w2; x++)
  777.         {
  778.             pt[y*w2 + x] = pr[(y + y1)*wold + (x + x1)];
  779.         }
  780.     }
  781.  
  782.     return (1);
  783. }
  784.  
  785.  
  786.  
  787.  
  788. /*------------------------------*/
  789. /*    rotate            */
  790. /*------------------------------*/
  791. int rotate (pras, w, h, angle, ptrans)
  792. uchar_t           *pras;
  793. int        w;
  794. int        h;
  795. int        angle;        /* +90, -90, -180 or +180 */
  796. uchar_t           *ptrans;
  797. {
  798.  
  799. /*
  800.  *    rotate an image +/-90 or +/-180. does NOT work in place (yet)
  801.  *
  802.  *    based on (rotating about center):
  803.  *
  804.  *        xnew = (x * cos(angle)) + (y * sin(angle))
  805.  *        ynew = (y * cos(angle)) - (x * sin(angle))
  806.  *
  807.  *    note: 45's should be relatively simple:
  808.  *
  809.  *        +45:    xnew = (.707 * x) + (.707 * y)
  810.  *            ynew = (.707 * y) - (.707 * x)
  811.  *
  812.  *        -45:    xnew = (.707 * x) - (.707 * y)
  813.  *            ynew = (.707 * y) + (.707 * x)
  814.  */
  815.  
  816.     register uchar_t       *pr;
  817.     register uchar_t       *pt;
  818.     register long        xnew;
  819.     register long        ynew;
  820.     register long        wold;
  821.     register long        hold;
  822.  
  823.  
  824.     /*
  825.      *   set up pointers...
  826.      */
  827.     if (pras == ptrans)
  828.     {
  829.         /*
  830.          *   can't do in place (yet)...
  831.          */
  832.         return (0);
  833.     }
  834.  
  835.  
  836.     /*
  837.      *   copy to new image
  838.      */
  839.     pr = pras;
  840.     pt = ptrans;
  841.     
  842.  
  843.     /*
  844.      *   do it...
  845.      */
  846.     wold = (long) w;
  847.     hold = (long) h;
  848.     switch (angle)
  849.     {
  850.     case 90:
  851.         /*
  852.          *   counter clockwise:
  853.          *
  854.          *    xnew = y        ->    y = xnew
  855.          *    ynew = wold - x - 1        x = wold - ynew - 1
  856.          *    wnew = hold
  857.          *    hnew = wold
  858.          */
  859.         for (ynew = 0L; ynew < wold; ynew++)
  860.         {
  861.             for (xnew = 0L; xnew < hold; xnew++)
  862.             {
  863.                 pt[ynew*hold + xnew] = pr[xnew*wold + (wold-ynew-1)];
  864.             }
  865.         }
  866.         break;
  867.  
  868.     case -90:
  869.         /*
  870.          *   clockwise...
  871.          *
  872.          *    xnew = hold - y - 1    ->    y = hold - xnew - 1
  873.          *    ynew = x            x = ynew
  874.          *    wnew = hold
  875.          *    hnew = wold
  876.          */
  877.         for (ynew = 0L; ynew < wold; ynew++)
  878.         {
  879.             for (xnew = 0L; xnew < hold; xnew++)
  880.             {
  881.                 pt[ynew*hold + xnew] = pr[(hold-xnew-1)*wold + ynew];
  882.             }
  883.         }
  884.         break;
  885.  
  886.     case 180:
  887.     case -180:
  888.         /*
  889.          *   clockwise or counter clockwise...
  890.          *
  891.          *    xnew = wold - x - 1    ->    x = wold - xnew - 1
  892.          *    ynew = hold - y - 1        y = hold - ynew - 1
  893.          *    wnew = wold
  894.          *    hnew = hold
  895.          */
  896.         for (ynew = 0L; ynew < hold; ynew++)
  897.         {
  898.             for (xnew = 0L; xnew < wold; xnew++)
  899.             {
  900.                 pt[ynew*wold + xnew] = pr[(hold-ynew-1)*wold + (wold-xnew-1)];
  901.             }
  902.         }
  903.         break;
  904.  
  905.     default:
  906.         /*
  907.          *   undefined angle, fail...
  908.          */
  909.         return (0);
  910.     }
  911.  
  912.     return (1);
  913. }
  914.  
  915.  
  916.  
  917.  
  918. /*------------------------------*/
  919. /*    mirror            */
  920. /*------------------------------*/
  921. int mirror (pras, w, h, opt, ptrans)
  922. uchar_t           *pras;
  923. int        w;
  924. int        h;
  925. int        opt;        /* 0=vert mirror, 1=horiz mirror */
  926. uchar_t           *ptrans;
  927. {
  928.  
  929. /*
  930.  *    mirror image.
  931.  *
  932.  *    vert mirror is:
  933.  *
  934.  *         _______|_______
  935.  *        |    |    |
  936.  *        |    |    |
  937.  *        |    |    |
  938.  *        |_______|_______|
  939.  *            |
  940.  *
  941.  *    horiz mirror is:
  942.  *
  943.  *         _______________
  944.  *        |        |
  945.  *          __|_______________|__
  946.  *        |        |
  947.  *        |_______________|
  948.  */
  949.  
  950.     register uchar_t       *pr;
  951.     register uchar_t       *pt;
  952.     register long        x;
  953.     register long        y;
  954.     register uchar_t    ctemp;
  955.  
  956.  
  957.     /*
  958.      *   set up pointers...
  959.      */
  960.     if (pras == ptrans)
  961.     {
  962.         /*
  963.          *   do in place...
  964.          */
  965.         pr = pras;
  966.         pt = pras;
  967.  
  968.         if (opt)
  969.         {
  970.             /*
  971.              *   horizontal mirror
  972.              */
  973.             for (y = 0L; y < h/2; y++)
  974.             {
  975.                 for (x = 0L; x < w; x++)
  976.                 {
  977.                     ctemp           = pt[y*w + x];
  978.                     pt[y*w + x]     = pt[(h-y)*w + x];
  979.                     pt[(h-y)*w + x] = ctemp;
  980.                 }
  981.             }
  982.         }
  983.         else
  984.         {
  985.             /*
  986.              *   vertical mirror
  987.              */
  988.             for (y = 0L; y < h; y++)
  989.             {
  990.                 for (x = 0L; x < w/2; x++)
  991.                 {
  992.                     ctemp           = pt[y*w + x];
  993.                     pt[y*w + x]     = pt[y*w + (w-x)];
  994.                     pt[y*w + (w-x)] = ctemp;
  995.                 }
  996.             }
  997.         }
  998.     }
  999.     else
  1000.     {
  1001.         /*
  1002.          *   copy to new image
  1003.          */
  1004.         pr = pras;
  1005.         pt = ptrans;
  1006.  
  1007.         if (opt)
  1008.         {
  1009.             /*
  1010.              *   horizontal mirror
  1011.              */
  1012.             for (y = 0L; y < h; y++)
  1013.             {
  1014.                 for (x = 0L; x < w; x++)
  1015.                 {
  1016.                     pt[y*w + x] = pr[(h-y-1)*w + x];
  1017.                 }
  1018.             }
  1019.         }
  1020.         else
  1021.         {
  1022.             /*
  1023.              *   vertical mirror
  1024.              */
  1025.             for (y = 0L; y < h; y++)
  1026.             {
  1027.                 for (x = 0L; x < w; x++)
  1028.                 {
  1029.                     pt[y*w + x] = pr[y*w + (w-x-1)];
  1030.                 }
  1031.             }
  1032.         }
  1033.     }
  1034.  
  1035.     return (1);
  1036. }
  1037.  
  1038.  
  1039.  
  1040.  
  1041. /*------------------------------*/
  1042. /*    convolve        */
  1043. /*------------------------------*/
  1044.  
  1045. /*
  1046.  *    built-in convolution kernels
  1047.  *
  1048.  *    k[0..8] is kernel (always 3x3)
  1049.  *    k[9] is scaling flag: -1=divide, 1=multiply, 0=no scaling
  1050.  *    k[10] is scale
  1051.  *
  1052.  *    example:
  1053.  *        for lp1 with flag -1 (divide) and scale 9, use
  1054.  *
  1055.  *            p = ((p0 * k0) +...+ (p8 * k8)) / 9
  1056.  *
  1057.  *        for hp2 with flag 0 (no scaling), use
  1058.  *
  1059.  *            p = (p0 * k0) +...+ (p8 * k8)
  1060.  */
  1061. int    lp1[11] = { 1, 1, 1,            /* low pass */
  1062.             1, 1, 1,
  1063.             1, 1, 1,    -1, 9};
  1064. int    lp2[11] = { 1, 1, 1,
  1065.             1, 2, 1,
  1066.             1, 1, 1,    -1, 10};
  1067. int    lp3[11] = { 1, 2, 1,
  1068.             2, 4, 2,
  1069.             1, 2, 1,    -1, 16};
  1070.  
  1071. int    hp1[11] = {-1,-1,-1,            /* hi pass */
  1072.            -1, 9,-1,
  1073.            -1,-1,-1,    0, 1};
  1074. int    hp2[11] = { 0,-1, 0,
  1075.            -1, 5,-1,
  1076.             0,-1, 0,    0, 1};
  1077. int    hp3[11] = { 1,-2, 1,
  1078.            -2, 5,-2,
  1079.             1,-2, 1,    0, 1};
  1080.  
  1081.                         /* shift edge */
  1082. int    se1[11] = { 0, 0, 0,            /* vertical */
  1083.            -1, 1, 0,
  1084.             0, 0, 0,    0, 1};
  1085. int    se2[11] = { 0,-1, 0,            /* horizontal */
  1086.             0, 1, 0,
  1087.             0, 0, 0,    0, 1};
  1088. int    se3[11] = {-1, 0, 0,            /* hor and vert */
  1089.             0, 1, 0,
  1090.             0, 0, 0,    0, 1};
  1091.  
  1092.                         /* gradient edge */
  1093. int    ge1[11] = { 1, 1, 1,            /* north */
  1094.             1,-2, 1,
  1095.            -1,-1,-1,    0, 1};
  1096. int    ge2[11] = { 1, 1, 1,            /* northeast */
  1097.            -1,-2, 1,
  1098.            -1,-1, 1,    0, 1};
  1099. int    ge3[11] = {-1, 1, 1,            /* east */
  1100.            -1,-2, 1,
  1101.            -1, 1, 1,    0, 1};
  1102. int    ge4[11] = {-1,-1, 1,            /* southeast */
  1103.            -1,-2, 1,
  1104.             1, 1, 1,    0, 1};
  1105. int    ge5[11] = {-1,-1,-1,            /* south */
  1106.             1,-2, 1,
  1107.             1, 1, 1,    0, 1};
  1108. int    ge6[11] = { 1,-1,-1,            /* southwest */
  1109.             1,-2,-1,
  1110.             1, 1, 1,    0, 1};
  1111. int    ge7[11] = { 1, 1,-1,            /* west */
  1112.             1,-2,-1,
  1113.             1, 1,-1,    0, 1};
  1114. int    ge8[11] = { 1, 1, 1,            /* northwest */
  1115.             1,-2,-1,
  1116.             1,-1,-1,    0, 1};
  1117.  
  1118. int    le1[11] = { 0, 1, 0,            /* laplace edge */
  1119.             1,-4, 1,
  1120.             0, 1, 0,    0, 1};
  1121. int    le2[11] = {-1,-1,-1,
  1122.            -1, 8,-1,
  1123.            -1,-1,-1,    0, 1};
  1124. int    le3[11] = {-1,-1,-1,
  1125.            -1, 9,-1,
  1126.            -1,-1,-1,    0, 1};
  1127. int    le4[11] = { 1,-2, 1,
  1128.            -2, 4,-2,
  1129.             1,-2, 1,    0, 1};
  1130.  
  1131. int convolve (pras, w, h, opt, kernel, ptrans)
  1132. uchar_t           *pras;
  1133. register int    w;
  1134. int        h;
  1135. int        opt;        /* 0=user, 1,2,...=built-in */
  1136. int           *kernel;        /* user kernel, if any */
  1137. uchar_t           *ptrans;
  1138. {
  1139.  
  1140. /*
  1141.  *    convolute an image (3x3). return 1 if successful, else 0.
  1142.  *
  1143.  *    the basic algorithm is:
  1144.  *
  1145.  *        new[i] = sum (k  * p ) for i pixels in 3x3 neighborhood
  1146.  *                       i    i
  1147.  */
  1148.  
  1149.     uchar_t               *pr;
  1150.     uchar_t               *pt;
  1151.     register int        val;
  1152.     register long        x;
  1153.     register long        y;
  1154.     register uchar_t       *ps;
  1155.     register int           *pk;
  1156.  
  1157.  
  1158.     pr = pras;
  1159.     pt = ptrans;
  1160.  
  1161.     if (pras != ptrans)
  1162.     {
  1163.         /*
  1164.          *   first copy orig image to transform image
  1165.          */
  1166.         copyrast (pr, w, h, pt);
  1167.     }
  1168.  
  1169.  
  1170.     /*
  1171.      *   set pointer to user or built-in kernels, depending on opt
  1172.      */
  1173.     switch (opt)
  1174.     {
  1175.     case USER_KERN:        pk = kernel;        break;
  1176.  
  1177.     case LP1_KERN:        pk = lp1;        break;
  1178.     case LP2_KERN:        pk = lp2;        break;
  1179.     case LP3_KERN:        pk = lp3;        break;
  1180.  
  1181.     case HP1_KERN:        pk = hp1;        break;
  1182.     case HP2_KERN:        pk = hp2;        break;
  1183.     case HP3_KERN:        pk = hp3;        break;
  1184.  
  1185.     case SE1_KERN:        pk = se1;        break;
  1186.     case SE2_KERN:        pk = se2;        break;
  1187.     case SE3_KERN:        pk = se3;        break;
  1188.  
  1189.     case GE1_KERN:        pk = ge1;        break;
  1190.     case GE2_KERN:        pk = ge2;        break;
  1191.     case GE3_KERN:        pk = ge3;        break;
  1192.     case GE4_KERN:        pk = ge4;        break;
  1193.     case GE5_KERN:        pk = ge5;        break;
  1194.     case GE6_KERN:        pk = ge6;        break;
  1195.     case GE7_KERN:        pk = ge7;        break;
  1196.     case GE8_KERN:        pk = ge8;        break;
  1197.  
  1198.     case LE1_KERN:        pk = le1;        break;
  1199.     case LE2_KERN:        pk = le2;        break;
  1200.     case LE3_KERN:        pk = le3;        break;
  1201.     case LE4_KERN:        pk = le4;        break;
  1202.  
  1203.     default:        return (0);
  1204.     }
  1205.  
  1206.  
  1207.     /*
  1208.      *   do it...
  1209.      */
  1210.     ps = pt;
  1211.     for (y = 1; y < h-1; y++)
  1212.     {
  1213.         for (x = 1; x < w-1; x++)
  1214.         {
  1215.             val  = ((uint_t) ps[(y-1)*w+(x-1)]) * pk[0];
  1216.             val += ((uint_t) ps[(y-1)*w+(x  )]) * pk[1];
  1217.             val += ((uint_t) ps[(y-1)*w+(x+1)]) * pk[2];
  1218.             val += ((uint_t) ps[(y  )*w+(x-1)]) * pk[3];
  1219.             val += ((uint_t) ps[(y  )*w+(x  )]) * pk[4];
  1220.             val += ((uint_t) ps[(y  )*w+(x+1)]) * pk[5];
  1221.             val += ((uint_t) ps[(y+1)*w+(x-1)]) * pk[6];
  1222.             val += ((uint_t) ps[(y+1)*w+(x  )]) * pk[7];
  1223.             val += ((uint_t) ps[(y+1)*w+(x+1)]) * pk[8];
  1224.  
  1225.             if ((pk[9] < 0) && pk[10])
  1226.                 val /= pk[10];
  1227.             else if (pk[9] > 0)
  1228.                 val *= pk[10];
  1229.  
  1230.             if (val < 0)
  1231.                 val = 0;
  1232.             else if (val > 255)
  1233.                 val = 255;
  1234.  
  1235.             ps[(y*w) + x] = (uchar_t) val;
  1236.         }
  1237.     }
  1238.  
  1239.     return (1);
  1240. }
  1241.  
  1242.  
  1243.  
  1244.  
  1245. /*------------------------------*/
  1246. /*    blur            */
  1247. /*------------------------------*/
  1248. int blur (pras, w, h, ptrans)
  1249. uchar_t           *pras;
  1250. register int    w;
  1251. int        h;
  1252. uchar_t           *ptrans;
  1253. {
  1254.  
  1255. /*
  1256.  *    blur an image. return 1 if successful, else 0.
  1257.  *
  1258.  *    the basic algorithm is:
  1259.  *
  1260.  *        new[i] = average of neighboring cells (3x3)
  1261.  */
  1262.  
  1263.     uchar_t               *pr;
  1264.     uchar_t               *pt;
  1265.     register long        x;
  1266.     register long        y;
  1267.     register uchar_t       *ps;
  1268.  
  1269.  
  1270.  
  1271.     pr = pras;
  1272.     pt = ptrans;
  1273.  
  1274.     if (pras != ptrans)
  1275.     {
  1276.         /*
  1277.          *   first copy orig image to transform image
  1278.          */
  1279.         copyrast (pr, w, h, pt);
  1280.     }
  1281.  
  1282.  
  1283.     /*
  1284.      *   do it...
  1285.      */
  1286.     ps = pt;
  1287.     for (y = 1; y < h-1; y++)
  1288.     {
  1289.         for (x = 1; x < w-1; x++)
  1290.         {
  1291.             ps[(y*w) + x] = (uchar_t) (
  1292.                     ( (uint_t) ps[(y-1)*w + (x-1)]
  1293.                     + (uint_t) ps[(y-1)*w + (x  )]
  1294.                     + (uint_t) ps[(y-1)*w + (x+1)]
  1295.                     + (uint_t) ps[(y  )*w + (x-1)]
  1296.                     + (uint_t) ps[(y  )*w + (x  )]
  1297.                     + (uint_t) ps[(y  )*w + (x+1)]
  1298.                     + (uint_t) ps[(y+1)*w + (x-1)]
  1299.                     + (uint_t) ps[(y+1)*w + (x  )]
  1300.                     + (uint_t) ps[(y+1)*w + (x+1)]) / 9);
  1301.         }
  1302.     }
  1303.  
  1304.     return (1);
  1305. }
  1306.  
  1307.  
  1308.  
  1309.  
  1310. /*------------------------------*/
  1311. /*    median            */
  1312. /*------------------------------*/
  1313. int median (pras, w, h, ptrans)
  1314. uchar_t           *pras;
  1315. int        w;
  1316. int        h;
  1317. uchar_t           *ptrans;
  1318. {
  1319.  
  1320. /*
  1321.  *    median filter an image. return 1 if successful, else 0.
  1322.  *
  1323.  *    the basic algorithm is:
  1324.  *
  1325.  *        new[i] = median of neighboring cells
  1326.  */
  1327.  
  1328.     uchar_t               *pr;
  1329.     register uchar_t       *pt;
  1330.     register long        x;
  1331.     register long        y;
  1332. #ifdef INL_SORT
  1333.     register int        i;
  1334.     register uint_t        a;
  1335. #endif
  1336.     register uint_t           *pl;
  1337.     uint_t            l[9];
  1338.  
  1339.  
  1340.     pr = pras;
  1341.     pt = ptrans;
  1342.  
  1343.     if (pras != ptrans)
  1344.     {
  1345.         /*
  1346.          *   first copy orig image to transform image
  1347.          */
  1348.         copyrast (pr, w, h, pt);
  1349.     }
  1350.  
  1351.  
  1352.     /*
  1353.      *   do it...
  1354.      */
  1355.     pl = l;
  1356.     for (y = 1; y < h-1; y++)
  1357.     {
  1358.         for (x = 1; x < w-1; x++)
  1359.         {
  1360.             pl[0] = (uint_t) pt[(y-1)*w + (x-1)];
  1361.             pl[1] = (uint_t) pt[(y-1)*w + (x  )];
  1362.             pl[2] = (uint_t) pt[(y-1)*w + (x+1)];
  1363.             pl[3] = (uint_t) pt[(y  )*w + (x-1)];
  1364.             pl[4] = (uint_t) pt[(y  )*w + (x  )];
  1365.             pl[5] = (uint_t) pt[(y  )*w + (x+1)];
  1366.             pl[6] = (uint_t) pt[(y+1)*w + (x-1)];
  1367.             pl[7] = (uint_t) pt[(y+1)*w + (x  )];
  1368.             pl[8] = (uint_t) pt[(y+1)*w + (x+1)];
  1369. #ifdef INL_SORT
  1370.             /* unroll j loop, too... */
  1371.             for (a=pl[1], i=0; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1372.             pl[i+1] = a;
  1373.             for (a=pl[2], i=1; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1374.             pl[i+1] = a;
  1375.             for (a=pl[3], i=2; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1376.             pl[i+1] = a;
  1377.             for (a=pl[4], i=3; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1378.             pl[i+1] = a;
  1379.             for (a=pl[5], i=4; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1380.             pl[i+1] = a;
  1381.             for (a=pl[6], i=5; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1382.             pl[i+1] = a;
  1383.             for (a=pl[7], i=6; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1384.             pl[i+1] = a;
  1385.             for (a=pl[8], i=7; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
  1386.             pl[i+1] = a;
  1387. #else
  1388.             piksrt (9, l);
  1389. #endif
  1390.             pt[(y*w) + x] = pl[4];
  1391.         }
  1392.     }
  1393.  
  1394.     return (1);
  1395. }
  1396.  
  1397.  
  1398.  
  1399.  
  1400. /*------------------------------*/
  1401. /*    piksrt            */
  1402. /*------------------------------*/
  1403. piksrt (num, arr)
  1404. int        num;
  1405. uint_t           *arr;
  1406. {
  1407.  
  1408. /*
  1409.  *    straight insertion sort (num. rec. in C, pp 243). is N^2 sort,
  1410.  *    probably ok for N=9. shell sort is 3x faster for N=9.
  1411.  */
  1412.  
  1413.     register uint_t           *parr;
  1414.     register int        n;
  1415.     register int        i;
  1416.     register int        j;
  1417.     register uint_t        a;
  1418.  
  1419.     n    = num;
  1420.     parr = arr;
  1421.     for (j = 1; j < n; j++)
  1422.     {
  1423.         for (a=parr[j], i=j-1; i>=0 && parr[i]>a; i--)
  1424.             parr[i+1] = parr[i];
  1425.  
  1426.         parr[i+1] = a;
  1427.     }
  1428. }
  1429.  
  1430.  
  1431.  
  1432.  
  1433. /*------------------------------*/
  1434. /*    findmedian        */
  1435. /*------------------------------*/
  1436. uint_t findmedian (num, arr)
  1437. int        num;
  1438. uint_t           *arr;
  1439. {
  1440.  
  1441. /*
  1442.  *    find median of an array of numbers. this should be faster than sort.
  1443.  *    there are pathalogical cases: if all are the same or all but 1 or 2
  1444.  *    are the same...
  1445.  */
  1446.  
  1447.     register uint_t           *parr;
  1448.     register int        n;
  1449.     register int        i;
  1450.     register int        j;
  1451.     register int        count;
  1452.     register uint_t        a;
  1453.  
  1454.     parr = arr;
  1455.     n    = num;
  1456.     for (j = 0; j < n; j++)
  1457.     {
  1458.         for (a = parr[j], count = 0, i = 0; i < n; i++)
  1459.         {
  1460.             if (i == j)
  1461.                 continue;
  1462.             if (a > parr[i])
  1463.                 count++;
  1464.         }
  1465.         if (count == (n>>1))
  1466.             return (a);
  1467.     }
  1468.         
  1469. }
  1470.  
  1471.  
  1472.  
  1473.  
  1474. /*------------------------------*/
  1475. /*    logscale        */
  1476. /*------------------------------*/
  1477. int logscale (pras, w, h, ptrans)
  1478. uchar_t           *pras;
  1479. int        w;
  1480. int        h;
  1481. uchar_t           *ptrans;
  1482. {
  1483.  
  1484. /*
  1485.  *    apply log scaling to an image. return 1 if successful, else 0.
  1486.  *
  1487.  *    the basic algorithm is:
  1488.  *
  1489.  *        new[i] = maxval * log(old[i]) / log(maxval)
  1490.  *    or
  1491.  *        new[i] = maxval * log2(old[i]) / log2(maxval)
  1492.  */
  1493.  
  1494.     uchar_t               *pr;
  1495.     uchar_t               *pt;
  1496.     register ulong_t    maxval;
  1497.     register ulong_t    l2maxval;
  1498.     register ulong_t    l2pr;
  1499.     uchar_t            uctmp;
  1500.     long            x;
  1501.     long            y;
  1502.     long            val;
  1503.     register long        ii;
  1504.     register long        lim;
  1505.     register uchar_t       *ps;
  1506.  
  1507.  
  1508.  
  1509.     pr = pras;
  1510.     pt = ptrans;
  1511.  
  1512.     if (pras != ptrans)
  1513.     {
  1514.         /*
  1515.          *   first copy orig image to transform image
  1516.          */
  1517.         copyrast (pr, w, h, pt);
  1518.     }
  1519.  
  1520.  
  1521.     /*
  1522.      *   find maxval. here it is max value a pixel can have, 255.
  1523.      */
  1524. #if 1
  1525.     maxval = 0L;
  1526.     for (y = 0; y < h; y++)
  1527.     {
  1528.         for (x = 0; x < w; x++)
  1529.         {
  1530.             uctmp = pt[(y*w) + x];
  1531.             if (uctmp > maxval)
  1532.                 maxval = (ulong_t) uctmp;
  1533.         }
  1534.     }
  1535. #endif
  1536. /*!!!    maxval = 255L;*/
  1537.  
  1538.  
  1539.     /*
  1540.      *   do it...
  1541.      */
  1542. #if 1
  1543.     l2maxval = (ulong_t) Log2x10 ((uint_t) maxval);
  1544.     if (l2maxval == 0)
  1545.         return (0);
  1546. #endif
  1547. /*!!!    l2maxval = 80;*/        /* approx 10 times log2(255) */
  1548.  
  1549.  
  1550. #ifdef DBL_LOOP
  1551.     for (y = 0; y < h; y++)
  1552.     {
  1553.         for (x = 0; x < w; x++)
  1554.         {
  1555.             l2pr          = (ulong_t) Log2x10 ((uint_t) pt[(y*w)+x]);
  1556.             pt[(y*w) + x] = (uchar_t) ((maxval * l2pr) / l2maxval);
  1557.         }
  1558.     }
  1559. #else
  1560.     lim = (long) w * (long) h;
  1561.     for (ps = pt, ii = 0L; ii < lim; ii++)
  1562.     {
  1563.         l2pr  = (ulong_t) Log2x10 ((uint_t) *ps);
  1564.         *ps++ = (uchar_t) ((maxval * l2pr) / l2maxval);
  1565.     }
  1566. #endif
  1567.  
  1568.     return (1);
  1569. }
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575. /*------------------------------*/
  1576. /*    Log2x10            */
  1577. /*------------------------------*/
  1578. int Log2x10(x)
  1579. uint_t    x;
  1580. {
  1581. /*
  1582.  *    VERY approximate log base 2 times 10. basically finds MS bit...
  1583.  */
  1584.     if (x < 256)        goto lobyte;
  1585.     if (x & 0x8000)        return (150);
  1586.     if (x & 0x4000)        return (140);
  1587.     if (x & 0x2000)        return (130);
  1588.     if (x & 0x1000)        return (120);
  1589.     if (x & 0x0800)        return (110);
  1590.     if (x & 0x0400)        return (100);
  1591.     if (x & 0x0200)        return (90);
  1592.     if (x & 0x0100)        return (80);
  1593. lobyte:
  1594.     if (x == 0x00ff)
  1595.         return (80);
  1596.     if (x == 0x0000)
  1597.         return (1);
  1598.     if (x & 0x0080)
  1599.     {
  1600.         if (x & 0x0040)
  1601.             return (78);
  1602.         else if (x & 0x0020)
  1603.             return (75);
  1604.         else
  1605.             return (71);
  1606.     }
  1607.     if (x & 0x0040)
  1608.     {
  1609.         if (x & 0x0020)
  1610.             return (68);
  1611.         else if (x & 0x0010)
  1612.             return (65);
  1613.         else
  1614.             return (61);
  1615.     }
  1616.     if (x & 0x0020)
  1617.     {
  1618.         if (x & 0x0010)
  1619.             return (58);
  1620.         else if (x & 0x0008)
  1621.             return (55);
  1622.         else
  1623.             return (51);
  1624.     }
  1625.     if (x & 0x0010)
  1626.     {
  1627.         if (x & 0x0008)
  1628.             return (48);
  1629.         else if (x & 0x0004)
  1630.             return (45);
  1631.         else
  1632.             return (41);
  1633.     }
  1634.     if (x & 0x0008)
  1635.     {
  1636.         if (x & 0x0004)
  1637.             return (38);
  1638.         else if (x & 0x0002)
  1639.             return (35);
  1640.         else
  1641.             return (31);
  1642.     }
  1643.     if (x & 0x0004)
  1644.     {
  1645.         if (x & 0x0002)
  1646.             return (28);
  1647.         else if (x & 0x0001)
  1648.             return (25);
  1649.         else
  1650.             return (21);
  1651.     }
  1652.     if (x & 0x0002)
  1653.     {
  1654.         if (x & 0x0001)
  1655.             return (18);
  1656.         else
  1657.             return (13);
  1658.     }
  1659.     if (x & 0x0001)        return (10);
  1660.     return (0);
  1661. }
  1662.  
  1663.  
  1664.  
  1665.  
  1666. /*------------------------------*/
  1667. /*    contrast        */
  1668. /*------------------------------*/
  1669. int contrast (pras, w, h, thresh, hist, ptrans)
  1670. uchar_t           *pras;
  1671. int        w;
  1672. int        h;
  1673. long        thresh;
  1674. long           *hist;
  1675. uchar_t           *ptrans;
  1676. {
  1677.  
  1678. /*
  1679.  *    apply contrast expansion to an image. return 1 if successful, else 0.
  1680.  *
  1681.  *    the basic algorithm is:
  1682.  *
  1683.  *        new[i] = maxval * (old[i] - lo) / (hi - lo)
  1684.  *
  1685.  *        where lo to hi is new contrast range
  1686.  */
  1687.  
  1688.     uchar_t               *pr;
  1689.     uchar_t               *pt;
  1690.     ulong_t            maxval;
  1691.     uchar_t            uctmp;
  1692.     long            x;
  1693.     long            y;
  1694.     long            hi_lo;
  1695.     long            newlo;
  1696.     long            newhi;
  1697.     int            i;
  1698.     register long        val;
  1699.     register long        rng;
  1700.     register long        lim;
  1701.     register long        ii;
  1702.     register uchar_t       *ps;
  1703.  
  1704.  
  1705.     pr = pras;
  1706.     pt = ptrans;
  1707.  
  1708.     if (pras != ptrans)
  1709.     {
  1710.         /*
  1711.          *   first copy orig image to transform image
  1712.          */
  1713.         copyrast (pr, w, h, pt);
  1714.     }
  1715.  
  1716.  
  1717.     /*
  1718.      *   get current histogram...
  1719.      */
  1720.     if (do_hist (pt, w, h, hist) == 0)
  1721.         return (0);
  1722.  
  1723.  
  1724.     /*
  1725.      *    find intensities on either side of hist where pixel count
  1726.      *    exceeds thresh
  1727.      */
  1728.     for (i = 0; i < HISTSIZ; i++)
  1729.     {
  1730.         if (hist[i] > thresh)
  1731.             break;
  1732.     }
  1733.     newlo = i;
  1734.     for (i = HISTSIZ-1; i > newlo; i--)
  1735.     {
  1736.         if (hist[i] > thresh)
  1737.             break;
  1738.     }
  1739.     newhi = i;
  1740.  
  1741.  
  1742.     /*
  1743.      *   do it. set pixels below lower threshold 0 and those above to 255.
  1744.      *   contrast expand pixels between...
  1745.      */
  1746. #ifdef DBL_LOOP
  1747.     rng = newhi - newlo + 1;
  1748.     for (y = 0; y < h; y++)
  1749.     {
  1750.         for (x = 0; x < w; x++)
  1751.         {
  1752.             val = (ulong_t) pt[(y*w) + x];
  1753.             if (val < newlo)
  1754.                 pt[(y*w) + x] = 0;
  1755.             else if (val > newhi)
  1756.                 pt[(y*w) + x] = 255;
  1757.             else
  1758.             {
  1759.                 pt[(y*w) + x] = (uchar_t) ((255L * (val - newlo)) / rng);
  1760.             }
  1761.         }
  1762.     }
  1763. #else
  1764.     rng = newhi - newlo + 1;
  1765.     lim = (long) w * (long) h;
  1766.     for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  1767.     {
  1768.         val = (ulong_t) *ps;
  1769.         if (val < newlo)
  1770.             *ps = 0;
  1771.         else if (val > newhi)
  1772.             *ps = 255;
  1773.         else
  1774.             *ps = (uchar_t) ((255L * (val - newlo)) / rng);
  1775.     }
  1776. #endif
  1777.  
  1778.     return (1);
  1779. }
  1780.  
  1781.  
  1782.  
  1783.  
  1784. /*------------------------------*/
  1785. /*    brighten        */
  1786. /*------------------------------*/
  1787. int brighten (pras, w, h, brite, ptrans)
  1788. uchar_t           *pras;
  1789. int        w;
  1790. int        h;
  1791. register int    brite;
  1792. uchar_t           *ptrans;
  1793. {
  1794.  
  1795. /*
  1796.  *    brighten an image. return 1 if successful, else 0.
  1797.  *
  1798.  *    the basic algorithm is:
  1799.  *
  1800.  *        new[i] = old[i] + brite
  1801.  */
  1802.  
  1803.     uchar_t               *pr;
  1804.     uchar_t               *pt;
  1805.     long            x;
  1806.     long            y;
  1807.     int            sign;
  1808.     register uint_t        val;
  1809.     register long        ii;
  1810.     register long        lim;
  1811.     register uchar_t       *ps;
  1812.  
  1813.  
  1814.  
  1815.     pr = pras;
  1816.     pt = ptrans;
  1817.  
  1818.     if (pras != ptrans)
  1819.     {
  1820.         /*
  1821.          *   first copy orig image to transform image
  1822.          */
  1823.         copyrast (pr, w, h, pt);
  1824.     }
  1825.  
  1826.  
  1827.     sign = 0;
  1828.     if (brite < 0)
  1829.     {
  1830.         sign = 1;
  1831.         brite = -brite;
  1832.     }
  1833.  
  1834.  
  1835.     /*
  1836.      *   do it...
  1837.      */
  1838.     if (sign)
  1839.     {
  1840. #ifdef DBL_LOOP
  1841.         for (y = 0; y < h; y++)
  1842.         {
  1843.             for (x = 0; x < w; x++)
  1844.             {
  1845.                 val = (uint_t) pt[y*w + x];
  1846.                 if (val < brite)
  1847.                     val  = 0;
  1848.                 else
  1849.                     val -= brite;
  1850.                 pt[(y*w) + x] = (uchar_t) val;
  1851.             }
  1852.         }
  1853. #else
  1854.         lim = (long) w * (long) h;
  1855.         for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  1856.         {
  1857.             if ((uint_t) *ps < brite)
  1858.                 *ps  = 0;
  1859.             else
  1860.                 *ps -= brite;
  1861.         }
  1862. #endif
  1863.     }
  1864.     else
  1865.     {
  1866. #ifdef DBL_LOOP
  1867.         for (y = 0; y < h; y++)
  1868.         {
  1869.             for (x = 0; x < w; x++)
  1870.             {
  1871.                 val = (uint_t) ((uint_t) pt[y*w + x] + brite);
  1872.                 if (val > 255)
  1873.                     val = 255;
  1874.                 pt[(y*w) + x] = (uchar_t) val;
  1875.             }
  1876.         }
  1877. #else
  1878.         lim = (long) w * (long) h;
  1879.         for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  1880.         {
  1881.             val = (uint_t) ((uint_t) *ps + brite);
  1882.             if (val > 255)
  1883.                 val = 255;
  1884.             *ps = (uchar_t) val;
  1885.         }
  1886. #endif
  1887.     }
  1888.  
  1889.     return (1);
  1890. }
  1891.  
  1892.  
  1893.  
  1894.  
  1895. /*------------------------------*/
  1896. /*    invert            */
  1897. /*------------------------------*/
  1898. int invert (pras, w, h, thresh, ptrans)
  1899. uchar_t           *pras;
  1900. int        w;
  1901. int        h;
  1902. int        thresh;
  1903. uchar_t           *ptrans;
  1904. {
  1905.  
  1906. /*
  1907.  *    invert (negate) an image. return 1 if successful, else 0.
  1908.  *
  1909.  *    the basic algorithm is:
  1910.  *
  1911.  *        new[i] = 255 - old[i]
  1912.  */
  1913.  
  1914.     uchar_t               *pr;
  1915.     uchar_t               *pt;
  1916.     long            x;
  1917.     long            y;
  1918.     int            sign;
  1919.     register long        lim;
  1920.     register long        ii;
  1921.     register int        thr;
  1922.     register uchar_t       *ps;
  1923.  
  1924.  
  1925.     pr = pras;
  1926.     pt = ptrans;
  1927.  
  1928.     if (pras != ptrans)
  1929.     {
  1930.         /*
  1931.          *   first copy orig image to transform image
  1932.          */
  1933.         copyrast (pr, w, h, pt);
  1934.     }
  1935.  
  1936.  
  1937.     sign = 0;
  1938.     if (thresh < 0)
  1939.     {
  1940.         sign   = 1;
  1941.         thresh = -thresh;
  1942.     }
  1943.  
  1944.  
  1945.     /*
  1946.      *   do it...
  1947.      */
  1948. #ifdef DBL_LOOP
  1949.     if (thresh == 0)
  1950.     {
  1951.         for (y = 0; y < h; y++)
  1952.         {
  1953.             for (x = 0; x < w; x++)
  1954.             {
  1955.                 pt[(y*w) + x] = 255 - pt[(y*w) + x];
  1956.             }
  1957.         }
  1958.     }
  1959.     else if (sign)
  1960.     {
  1961.         /*
  1962.          *   invert only below thresh
  1963.          */
  1964.         for (y = 0; y < h; y++)
  1965.         {
  1966.             for (x = 0; x < w; x++)
  1967.             {
  1968.                 if ((uint_t) pt[(y*w) + x] < thresh)
  1969.                     pt[(y*w) + x] = 255 - pt[(y*w) + x];
  1970.             }
  1971.         }
  1972.     }
  1973.     else
  1974.     {
  1975.         /*
  1976.          *   invert only above thresh
  1977.          */
  1978.         for (y = 0; y < h; y++)
  1979.         {
  1980.             for (x = 0; x < w; x++)
  1981.             {
  1982.                 if ((uint_t) pt[(y*w) + x] > thresh)
  1983.                     pt[(y*w) + x] = 255 - pt[(y*w) + x];
  1984.             }
  1985.         }
  1986.     }
  1987. #else
  1988.     lim = (long) h * (long) w;
  1989.     thr = thresh;
  1990.     if (thr == 0)
  1991.     {
  1992.         for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  1993.         {
  1994.             *ps = 255 - *ps;
  1995.         }
  1996.     }
  1997.     else if (sign)
  1998.     {
  1999.         /*
  2000.          *   invert only below thresh
  2001.          */
  2002.         for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  2003.         {
  2004.             if ((uint_t) *ps < thr)
  2005.                 *ps = 255 - *ps;
  2006.         }
  2007.     }
  2008.     else
  2009.     {
  2010.         /*
  2011.          *   invert above below thresh
  2012.          */
  2013.         for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  2014.         {
  2015.             if ((uint_t) *ps > thr)
  2016.                 *ps = 255 - *ps;
  2017.         }
  2018.     }
  2019. #endif
  2020.  
  2021.     return (1);
  2022. }
  2023.  
  2024.  
  2025.  
  2026.  
  2027. /*------------------------------*/
  2028. /*    threshold        */
  2029. /*------------------------------*/
  2030. int threshold (pras, w, h, thresh, ptrans)
  2031. uchar_t           *pras;
  2032. int        w;
  2033. int        h;
  2034. int        thresh;
  2035. uchar_t           *ptrans;
  2036. {
  2037.  
  2038. /*
  2039.  *    threshold an image. return 1 if successful, else 0.
  2040.  *
  2041.  *    the basic algorithm is:
  2042.  *
  2043.  *        new[i] =   0 if old[i] <= thresh
  2044.  *        new[i] = 255 if old[i] >  thresh
  2045.  */
  2046.  
  2047.     uchar_t               *pr;
  2048.     uchar_t               *pt;
  2049.     long            x;
  2050.     long            y;
  2051.     uint_t            val;
  2052.     register long        ii;
  2053.     register long        lim;
  2054.     register uchar_t       *ps;
  2055.  
  2056.  
  2057.     pr = pras;
  2058.     pt = ptrans;
  2059.  
  2060.     if (pras != ptrans)
  2061.     {
  2062.         /*
  2063.          *   first copy orig image to transform image
  2064.          */
  2065.         copyrast (pr, w, h, pt);
  2066.     }
  2067.  
  2068.  
  2069.     /*
  2070.      *   do it...
  2071.      */
  2072. #ifdef DBL_LOOP
  2073.     for (y = 0; y < h; y++)
  2074.     {
  2075.         for (x = 0; x < w; x++)
  2076.         {
  2077.             val = (uint_t) pt[(y*w) + x];
  2078.             if (val > thresh)
  2079.                 pt[(y*w) + x] = 255;
  2080.             else
  2081.                 pt[(y*w) + x] = 0;
  2082.         }
  2083.     }
  2084. #else
  2085.     lim = (long) h * (long) w;
  2086.     for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
  2087.     {
  2088.         if ((uint_t) *ps > thresh)
  2089.             *ps = 255;
  2090.         else
  2091.             *ps = 0;
  2092.     }
  2093. #endif
  2094.  
  2095.     return (1);
  2096. }
  2097.  
  2098.  
  2099.  
  2100.  
  2101. /*------------------------------*/
  2102. /*    histeq            */
  2103. /*------------------------------*/
  2104. int histeq (pras, w, h, hist, ptrans)
  2105. uchar_t           *pras;
  2106. int        w;
  2107. int        h;
  2108. long           *hist;
  2109. uchar_t           *ptrans;
  2110. {
  2111.  
  2112. /*
  2113.  *    histogram equalization of image. return 1 if successful, else 0.
  2114.  */
  2115.  
  2116.     long            p_r[HISTSIZ];
  2117.     long            s_k[HISTSIZ];
  2118.     long            s_kapprx[HISTSIZ];
  2119.     uchar_t               *pr;
  2120.     uchar_t               *pt;
  2121.     int            i;
  2122.     long            count;
  2123.  
  2124.  
  2125.  
  2126.     pr = pras;
  2127.     pt = ptrans;
  2128.  
  2129.     if (pras != ptrans)
  2130.     {
  2131.         /*
  2132.          *   first copy orig image to transform image
  2133.          */
  2134.         copyrast (pr, w, h, pt);
  2135.     }
  2136.  
  2137.  
  2138.     /*
  2139.      *   get current histogram...
  2140.      */
  2141.     if (do_hist (pt, w, h, hist) == 0)
  2142.         return (0);
  2143.  
  2144.  
  2145.     /*
  2146.      *   find prob density function (p_r), transformation function (s_k),
  2147.      *   and new distribution. note the 1000 to avoid floats...
  2148.      */
  2149.     count = (long) w * (long) h;
  2150.     for (i = 0; i < HISTSIZ; i++)
  2151.     {
  2152.         p_r[i] = (hist[i] * 1000L) / count;
  2153.     }
  2154.     for (s_k[0] = p_r[0], i = 1; i < HISTSIZ; i++)
  2155.     {
  2156.         s_k[i] = s_k[i-1] + p_r[i];
  2157.     }
  2158.     for (i = 0; i < HISTSIZ; i++)
  2159.     {
  2160.         /* the 500 is for rounding to nearest int... */
  2161.         s_kapprx[i] = ((s_k[i] * 255L) + 500L) / 1000L;
  2162.     }
  2163.  
  2164. #if 0
  2165.     printf ("\n    i      hist       p_r       s_k  s_kapprx\n");
  2166.     for (count = 0, i = 0; i < HISTSIZ; i++)
  2167.     {
  2168.         printf ("%5d%10ld%10ld%10ld%10ld\n",
  2169.             i,hist[i],p_r[i],s_k[i],s_kapprx[i]);
  2170.     }
  2171. #endif
  2172.  
  2173.     /*
  2174.      *   now redistribute. s_kapprx will contain the new value for
  2175.      *   a given pixel intensity
  2176.      */
  2177.     redistribute (pt, w, h, s_kapprx);
  2178.  
  2179.     return (1);
  2180. }
  2181.  
  2182.  
  2183.  
  2184.  
  2185. /*------------------------------*/
  2186. /*    redistribute        */
  2187. /*------------------------------*/
  2188. int redistribute (pras, w, h, s_kapprx)
  2189. uchar_t           *pras;
  2190. int        w;
  2191. int        h;
  2192. register long  *s_kapprx;
  2193. {
  2194.  
  2195. /*
  2196.  *    redistribute pixels. each pixel set to value given by s_kapprx
  2197.  */
  2198.  
  2199.     register uchar_t       *pr;
  2200.     register long        ii;
  2201.     register long        lim;
  2202.  
  2203.  
  2204.     lim = (long) w * (long) h;
  2205.     for (pr = pras, ii = 0L; ii < lim; ii++, pr++)
  2206.     {
  2207.         *pr = (uchar_t) s_kapprx[(uint_t) *pr];
  2208.     }
  2209. }
  2210.  
  2211.  
  2212.  
  2213.  
  2214. /*------------------------------*/
  2215. /*    copyrast        */
  2216. /*------------------------------*/
  2217. int copyrast (ps, w, h, pd)
  2218. uchar_t           *ps;        /* source */
  2219. int        w;
  2220. int        h;
  2221. uchar_t           *pd;        /* dest */
  2222. {
  2223.  
  2224. /*
  2225.  *    copy an image. return 1 if successful, else 0.
  2226.  */
  2227.  
  2228. #ifdef DBL_LOOP
  2229.     long        x;
  2230.     long        y;
  2231.  
  2232.     for (y = 0; y < h; y++)
  2233.     {
  2234.         for (x = 0; x < w; x++)
  2235.         {
  2236.             pd[(y*w) + x] = ps[(y*w) + x];
  2237.         }
  2238.     }
  2239. #else
  2240.     register long    ii;
  2241.     register long    lim;
  2242.  
  2243.     lim = (long) w * (long) h;
  2244.     for (ii = 0L; ii < lim; ii++)
  2245.         *pd++ = *ps++;
  2246. #endif
  2247.     return (1);
  2248. }
  2249.  
  2250.