home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 343_02 / scale.c < prev    next >
C/C++ Source or Header  |  1992-04-25  |  19KB  |  557 lines

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