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