home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_11 / 1011099a < prev    next >
Text File  |  1992-09-02  |  19KB  |  554 lines

  1.        /***********************************************
  2.        *
  3.        *       file d:\cips\scale.c
  4.        *
  5.        *       Functions: This file contains
  6.        *          zoom_image_array
  7.        *          shrink_image_array
  8.        *          interpolate_pixel
  9.        *          average_pixel
  10.        *          median_pixel
  11.        *          get_scaling_options
  12.        *          blank_image_array
  13.        *
  14.        *       Purpose:
  15.        *          These functions implement image array
  16.        *          zooming (enlarging) and shrinking.
  17.        *
  18.        *       External Calls:
  19.        *          wtiff.c - does_not_exist
  20.        *                    round_off_image_size
  21.        *                    create_allocate_tiff_file
  22.        *                    write_array_into_tiff_image
  23.        *          tiff.c - read_tiff_header
  24.        *          rtiff.c - read_tiff_image
  25.        *          rstring.c - read_string
  26.        *          numcvrt.c - get_integer
  27.        *          filter.c - median_of
  28.        *
  29.        *       Modifications:
  30.        *          8 April 1992 - created
  31.        *
  32.        *************************************************/
  33.  
  34. #include "d:\cips\cips.h"
  35. #include <malloc.h>
  36.  
  37.      /*******************************************
  38.      *
  39.      *   zoom_image_array(...
  40.      *
  41.      *   This function zooms in on an input
  42.      *   image array.  It zooms by enlarging
  43.      *   an input image array and writing the
  44.      *   resulting image arrays to an output
  45.      *   image file.  It can zoom or enlarge by
  46.      *   a factor of 2 or 4.
  47.      *
  48.      *   You can zoom or enlarge an image array
  49.      *   by using either the replication or
  50.      *   interpolation methods.
  51.      *
  52.      *******************************************/
  53.  
  54.  
  55. zoom_image_array(in_name, out_name, the_image, out_image,
  56.           il, ie, ll, le, scale, method)
  57.    char   in_name[], out_name[], method[];
  58.    int    il, ie, ll, le, scale;
  59.    short  the_image[ROWS][COLS],
  60.           out_image[ROWS][COLS];
  61. {
  62.    int    A, B, a, b, count, factor, i, j, length, width;
  63.    struct tiff_header_struct image_header;
  64.  
  65.            /*******************************************
  66.            *
  67.            *   Check the scale factor.  If it is not
  68.            *   a valid factor (2 or 4), then set
  69.            *   it to 2.
  70.            *
  71.            *******************************************/
  72.  
  73.    factor = scale;
  74.    if(factor != 2 &&
  75.       factor != 4) factor = 2;
  76.  
  77.    if(does_not_exist(out_name)){
  78.       printf("\n\n output file does not exist %s", out_name);
  79.       read_tiff_header(in_name, &image_header);
  80.       image_header.image_length = ROWS*factor;
  81.       image_header.image_width  = COLS*factor;
  82.       create_allocate_tiff_file(out_name, &image_header,
  83.                                 out_image);
  84.    }  /* ends if does_not_exist */
  85.  
  86.            /*******************************************
  87.            *
  88.            *   Let me try to explain the nested loops
  89.            *   shown below.
  90.            *
  91.            *   We will enlarge the_image by the factor.
  92.            *   Therefore, we want to divide the_image
  93.            *   into parts of size ROWS/factor by
  94.            *   COLS/factor.  We will loop through
  95.            *   the_image parts ROWS/factor and COLS/factor
  96.            *   using the loops over i and j.
  97.            *
  98.            *   We divided the_image into parts so we must
  99.            *   include all of these parts.  That is why we
  100.            *   do the loops over A and B.  There are
  101.            *   factor*factor parts.
  102.            *
  103.            *   Finally, we do the loops over a and b.
  104.            *   We must replicate every element in the_image
  105.            *   factor*factor times and put these into
  106.            *   out_image.  The a and b loops perform this
  107.            *   task.
  108.            *
  109.            *   The equations inside the []'s for
  110.            *   the_image and out_image are also confusing.
  111.            *   If you work them out, you'll see that we
  112.            *   are bouncing through the image arrays
  113.            *   and fitting the pixels into the right
  114.            *   places.
  115.            *
  116.            *   The final proof is that this works.
  117.            *
  118.            *   One final note:  the factor should divide
  119.            *   evenly into ROWS.  For example, ROWS=100
  120.            *   so using a factor of 8 is not good.
  121.            *   100/8 = 12.5 and this leave you with
  122.            *   an empty strip along the right and
  123.            *   bottom edges of the out_image.
  124.            *
  125.            *******************************************/
  126.  
  127.            /*******************************************
  128.            *
  129.            *   Replication method
  130.            *
  131.            *******************************************/
  132.  
  133.    if(method[0] == 'r' || method[0] == 'R'){
  134.       read_tiff_image(in_name, the_image, il, ie, ll, le);
  135.       count = 1;
  136.       for(A=0; A<factor; A++){
  137.        for(B=0; B<factor; B++){
  138.         for(i=0; i<ROWS/factor; i++){
  139.          for(j=0; j<COLS/factor; j++){
  140.           for(a=0; a<factor; a++){
  141.            for(b=0; b<factor; b++){
  142.              out_image[factor*i+a][factor*j+b] =                  
  143.               the_image[i+A*ROWS/factor][j+B*COLS/factor];
  144.            }  /* ends loop over b */
  145.           }  /* ends loop over a */
  146.          }  /* ends loop over j */
  147.         }  /* ends loop over i */
  148.         printf("\nzooming replication %3d of %3d",
  149.                count++, factor*factor);
  150.         write_array_into_tiff_image(out_name, out_image,
  151.             1+A*ROWS, 1+B*COLS, 101+A*ROWS, 101+B*COLS);
  152.        }  /* ends loop over B */
  153.       }  /* ends loop over A */
  154.    }  /* ends replication method */
  155.  
  156.            /***************************
  157.            *
  158.            *   Interpolation method
  159.            *
  160.            ****************************/
  161.  
  162.    if(method[0] == 'i' || method[0] == 'I'){
  163.       read_tiff_image(in_name, the_image, 
  164.                       il, ie, ll, le);
  165.       count = 1;
  166.       for(A=0; A<factor; A++){
  167.          for(B=0; B<factor; B++){
  168.           for(i=0; i<ROWS/factor; i++){
  169.            for(j=0; j<COLS/factor; j++){
  170.             for(a=0; a<factor; a++){
  171.              for(b=0; b<factor; b++){
  172.                 out_image[factor*i+a][factor*j+b] =
  173.                   interpolate_pixel(the_image, A, B,
  174.                               i, j, a, b, factor);
  175.              }  /* ends loop over b */
  176.             }  /* ends loop over a */
  177.            }  /* ends loop over j */
  178.           }  /* ends loop over i */
  179.        printf("\nzooming interpolation %3d of %3d",
  180.                      count++, factor*factor);
  181.        write_array_into_tiff_image(out_name, out_image,
  182.                  1+A*ROWS, 1+B*COLS, 
  183.                  101+A*ROWS, 101+B*COLS);
  184.      }  /* ends loop over B */
  185.     }  /* ends loop over A */
  186.    }  /* ends interpolation method */
  187.  
  188.  
  189. }  /* ends zoom_image_array */
  190.  
  191.  
  192.  
  193.  
  194.     /***********************************************
  195.     *
  196.     *    interpolate_pixel(...
  197.     *
  198.     *    This function interpolates between pixel
  199.     *    values and returns the interlopated value.
  200.     *
  201.     ***********************************************/
  202.  
  203. interpolate_pixel(the_image, A, B, i, j, a, b, factor)
  204.    int   A, B, a, b, factor, i, j;
  205.    short the_image[ROWS][COLS];
  206. {
  207.    int   num, x = 0, y = 0;
  208.    short diff, result;
  209.  
  210.    if(a > 0) y = 1;
  211.    if(b > 0) x = 1;
  212.    diff = the_image[y+i+A*ROWS/factor][x+j+B*COLS/factor] -
  213.           the_image[i+A*ROWS/factor][j+B*COLS/factor];
  214.  
  215.           /***********************************************
  216.           *
  217.           *    If you are at the edge of the input image
  218.           *    array, then you cannot interpolate to the
  219.           *    next point because there is no next point.
  220.           *    Therefore, set the diff to 0.
  221.           *
  222.           ***********************************************/
  223.  
  224.    if((y+i+A*ROWS/factor) >= ROWS) diff = 0;
  225.    if((x+j+B*COLS/factor) >= COLS) diff = 0;
  226.  
  227.    num = a+b;
  228.    if(num > factor) num = factor;
  229.    result = the_image[i+A*ROWS/factor][j+B*COLS/factor] +
  230.             num*diff/factor;
  231.    return(result);
  232. }  /* ends interpolate_pixel */
  233.  
  234.  
  235.  
  236.      /*******************************************
  237.      *
  238.      *   shrink_image_array(...
  239.      *
  240.      *   This function shrinks a part of an
  241.      *   image.  It takes a part of an input
  242.      *   image (described by il1, ie1, ll1, le1)
  243.      *   shrinks a 200x200 or 400x400 area down
  244.      *   to a 100x100 array, and writes this result
  245.      *   to an output file.  The location in the
  246.      *   output file is described by il2, ie2,
  247.      *   ll2, le2.
  248.      *
  249.      *   You can shrink the input image area
  250.      *   by using either the averaging, median,
  251.      *   or corner method.
  252.      *
  253.      *******************************************/
  254.  
  255. shrink_image_array(in_name, out_name, the_image, out_image,
  256.           il1, ie1, ll1, le1, il2, ie2, ll2, le2,
  257.           scale, method)
  258.    char   in_name[], out_name[], method[];
  259.    int    il1, ie1, ll1, le1,
  260.           il2, ie2, ll2, le2, scale;
  261.    short  the_image[ROWS][COLS],
  262.           out_image[ROWS][COLS];
  263. {
  264.    int    A, B, a, b, count, factor, i, j, length, width;
  265.    struct tiff_header_struct image_header;
  266.  
  267.            /*******************************************
  268.            *
  269.            *   Check the scale factor.  If it is not
  270.            *   a valid factor (2 or 4), then set
  271.            *   it to 2.
  272.            *
  273.            *******************************************/
  274.  
  275.    factor = scale;
  276.    if(factor != 2 &&
  277.       factor != 4) factor = 2;
  278.  
  279.    if(does_not_exist(out_name)){
  280.       printf("\n\n output file does not exist %s", out_name);
  281.       read_tiff_header(in_name, &image_header);
  282.       image_header.image_length = ROWS;
  283.       image_header.image_width  = COLS;
  284.       create_allocate_tiff_file(out_name, &image_header,
  285.                                 out_image);
  286.    }  /* ends if does_not_exist */
  287.  
  288.    read_tiff_header(in_name, &image_header);
  289.  
  290.            /*******************************************
  291.            *
  292.            *   Let me try to explain the nested loops
  293.            *   shown below.
  294.            *
  295.            *   We will shrink the_image by the factor.
  296.            *   Therefore, we want to read in factor*factor
  297.            *   image arrays and produce one ROWS by COLS
  298.            *   array for writing to disk.
  299.            *   That is why we loop over A and B.
  300.            *
  301.            *   We want to set every pixel in the out_image
  302.            *   array so we loop over i and j.
  303.            *
  304.            *   The equations inside the out_image []'s
  305.            *   look a little strange.  What we are doing is
  306.            *   setting every element and moving over every
  307.            *   time through the loops over A and B.  The first 
  308.            *   loop is for i=0,49 then i=50,99 for a factor=2
  309.            *   and ROWS=100.
  310.            *
  311.            *   The final proof is that this works.
  312.            *
  313.            *   One final note:  the factor should divide
  314.            *   evenly into ROWS.  For example, ROWS=100
  315.            *   so using a factor of 8 is not good.
  316.            *   100/8 = 12.5 and this leave you with
  317.            *   an empty strip along the right and
  318.            *   bottom edges of the out_image.
  319.            *
  320.            *******************************************/
  321.  
  322.            /********************************
  323.            *
  324.            *   Corner method
  325.            *
  326.            *********************************/
  327.  
  328.    if(method[0] == 'c' || method[0] == 'C'){
  329.       count = 1;
  330.       for(A=0; A<factor; A++){
  331.        for(B=0; B<factor; B++){
  332.         printf("\n shrinking by corner %3d of %3d",
  333.                      count++, factor*factor);
  334.         if(image_header.image_length < il1+A*ROWS   ||
  335.            image_header.image_width  < ie1+B*COLS)
  336.            blank_image_array(the_image);
  337.         else
  338.            read_tiff_image(in_name, the_image,
  339.                            il1+A*ROWS, ie1+B*COLS,
  340.                            ll1+A*ROWS, le1+B*COLS);
  341.         for(i=0; i<ROWS/factor; i++){
  342.          for(j=0; j<COLS/factor; j++){
  343.             out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  344.                      the_image[factor*i][factor*j];
  345.          }  /* ends loop over j */
  346.         }  /* ends loop over i */
  347.        }  /* ends loop over B */
  348.       }  /* ends loop over A */
  349.       write_array_into_tiff_image(out_name, out_image,
  350.                                   il2, ie2, ll2, le2);
  351.    } /* ends corner method */
  352.  
  353.            /******************************
  354.            *
  355.            *   Average Method
  356.            *
  357.            ******************************/
  358.  
  359.    if(method[0] == 'a' || method[0] == 'A'){
  360.       count = 1;
  361.       for(A=0; A<factor; A++){
  362.        for(B=0; B<factor; B++){
  363.         printf("\n shrinking by average %3d of %3d",
  364.                      count++, factor*factor);
  365.         if(image_header.image_length < il1+A*ROWS   ||
  366.            image_header.image_width  < ie1+B*COLS)
  367.            blank_image_array(the_image);
  368.         else
  369.            read_tiff_image(in_name, the_image,
  370.                           il1+A*ROWS, ie1+B*COLS,
  371.                           ll1+A*ROWS, le1+B*COLS);
  372.         for(i=0; i<ROWS/factor; i++){
  373.          for(j=0; j<COLS/factor; j++){
  374.              out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  375.                    average_pixel(the_image, factor, i, j);
  376.          }  /* ends loop over j */
  377.         }  /* ends loop over i */
  378.        }  /* ends loop over B */
  379.       }  /* ends loop over A */
  380.       write_array_into_tiff_image(out_name, out_image,
  381.                                   il2, ie2, ll2, le2);
  382.    } /* ends average method */
  383.  
  384.            /************************
  385.            *
  386.            *   Median Method
  387.            *
  388.            *************************/
  389.  
  390.    if(method[0] == 'm' || method[0] == 'M'){
  391.       count = 1;
  392.       for(A=0; A<factor; A++){
  393.        for(B=0; B<factor; B++){
  394.         printf("\n shrinking by median %3d of %3d",
  395.                      count++, factor*factor);
  396.         if(image_header.image_length < il1+A*ROWS   ||
  397.            image_header.image_width  < ie1+B*COLS)
  398.            blank_image_array(the_image);
  399.         else
  400.            read_tiff_image(in_name, the_image,
  401.                            il1+A*ROWS, ie1+B*COLS,
  402.                            ll1+A*ROWS, le1+B*COLS);
  403.         for(i=0; i<ROWS/factor; i++){
  404.          for(j=0; j<COLS/factor; j++){
  405.             out_image[i+A*ROWS/factor][j+B*COLS/factor] =
  406.                     median_pixel(the_image, factor, i, j);
  407.          }  /* ends loop over j */
  408.         }  /* ends loop over i */
  409.        }  /* ends loop over B */
  410.       }  /* ends loop over A */
  411.       write_array_into_tiff_image(out_name, out_image,
  412.                                   il2, ie2, ll2, le2);
  413.    } /* ends median method */
  414. }  /* ends shrink_image_array */
  415.  
  416.  
  417.  
  418.     /***********************************************
  419.     *
  420.     *   average_pixel(...
  421.     *
  422.     *   This function calculates the average
  423.     *   pixel value of a factor x factor array
  424.     *   of pixels inside the the_image array.
  425.     *   The coordinates i and j point to the upper 
  426.     *   left hand corner of the small array.
  427.     *
  428.     ***********************************************/
  429.  
  430. average_pixel(the_image, factor, i, j)
  431.    int   factor, i, j;
  432.    short the_image[ROWS][COLS];
  433. {
  434.    int a, b, result = 0;
  435.  
  436.    for(a=0; a<factor; a++)
  437.       for(b=0; b<factor; b++)
  438.          result = result + the_image[factor*i+a][factor*j+a];
  439.    result = result/(factor*factor);
  440.  
  441.    return(result);
  442. }  /* ends average_pixel */
  443.  
  444.  
  445.  
  446.     /***********************************************
  447.     *
  448.     *   median_pixel(...
  449.     *
  450.     *   This function calculates the median
  451.     *   pixel value of a factor x factor array
  452.     *   of pixels inside the the_image array.
  453.     *   The coordinates i and j point to the upper 
  454.     *   left hand corner of the small array.
  455.     *
  456.     ***********************************************/
  457.  
  458. median_pixel(the_image, factor, i, j)
  459.    int   factor, i, j;
  460.    short the_image[ROWS][COLS];
  461. {
  462.    int   a, b, count, ff, result = 0;
  463.    short *elements;
  464.  
  465.    ff       = factor*factor;
  466.    elements = (short *) malloc(ff * sizeof(short));
  467.  
  468.      count = 0;
  469.    for(a=0; a<factor; a++){
  470.          for(b=0; b<factor; b++){
  471.             elements[count] = the_image[factor*i+a][factor*j+b];
  472.               count++;
  473.         }
  474.      }
  475.  
  476.    result = median_of(elements, &ff);
  477.    free(elements);
  478.    return(result);
  479.  
  480. }  /* ends median_pixel */
  481.  
  482.  
  483.  
  484.     /***********************************************
  485.     *
  486.     *   blank_image_array(...
  487.     *
  488.     *   This function blanks out an image array
  489.     *   by filling it with zeros.
  490.     *
  491.     ***********************************************/
  492.  
  493. blank_image_array(image)
  494.    short image[ROWS][COLS];
  495. {
  496.    int i, j;
  497.    for(i=0; i<ROWS; i++)
  498.       for(j=0; j<COLS; j++)
  499.          image[i][j] = 0;
  500. }  /* ends blank_image_array */
  501.  
  502.  
  503.  
  504.     /***********************************************
  505.     *
  506.     *    get_scaling_options(...
  507.     *
  508.     *    This function queries the user for the
  509.     *    parameters needed to perform scaling.
  510.     *
  511.     ***********************************************/
  512.  
  513.  
  514. get_scaling_options(zoom_shrink, scale, method)
  515.    int *scale;
  516.    char method[], zoom_shrink[];
  517. {
  518.    int not_finished = 1, response;
  519.  
  520.    while(not_finished){
  521.       printf("\n\t1. Zoom or Shrink is - %s", zoom_shrink);
  522.       printf("\n\t2. Scale factor is %d", *scale);
  523.       printf("\n\t3. Scaling Method is - %s", method);
  524.       printf("\n\t     Replication or Interpolation for Zooming"
  525.              "\n\t     Averaging Median or Corner for Shrinking");
  526.       printf("\n\n\tEnter choice (0 = no change) _\b");
  527.       get_integer(&response);
  528.  
  529.       if(response == 0){
  530.         not_finished = 0;
  531.       }
  532.  
  533.       if(response == 1){
  534.          printf("\nEnter Zoom or Shrink (z or s) __\b");
  535.          read_string(zoom_shrink);
  536.       }
  537.  
  538.       if(response == 2){
  539.          printf("\nEnter Scale Factor (2 or 4) __\b");
  540.          get_integer(scale);
  541.       }
  542.  
  543.       if(response == 3){
  544.          printf("\nEnter Scaling Method: "
  545.                 "Replication or Interpolation for Zooming"
  546.                 "\n                      "
  547.                 "Averaging Median or Corner for Shrinking"
  548.                 "\n\t__\b");
  549.          read_string(method);
  550.       }
  551.  
  552.    }  /* ends while not_finished */
  553. }  /* ends get_scaling_options */
  554.