home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / fontutils-0.6-base.tgz / fontutils-0.6-base.tar / fsf / fontutils / fontconvert / random.c < prev    next >
C/C++ Source or Header  |  1992-08-24  |  5KB  |  172 lines

  1. /* random.c: distort a bitmap.
  2.  
  3. Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include "rand.h"
  22.  
  23. #include "random.h"
  24.  
  25. /* Distort the bitmap (see below).  (-randomize)  */
  26. real random_max = 0.0;
  27. real random_threshold = 0.2;
  28.  
  29.  
  30. static bitmap_type enlarge_bitmap (bitmap_type, int, int);
  31. static real random_number (void);
  32.  
  33.  
  34.  
  35. /* Randomize the bitmap B by moving each black pixel a randomly chosen
  36.    distance between -random_max and random_max (both horizontally and
  37.    vertically).  Return the enlargement of B on all four side in ADJUST.
  38.    */
  39.  
  40. void
  41. randomize_bitmap (bitmap_type *b, bounding_box_type *adjust)
  42. {
  43.   unsigned this_row, this_col;
  44.  
  45.   MIN_ROW (*adjust) = MAX_ROW (*adjust) = MIN_COL (*adjust) = MAX_COL (*adjust)
  46.     = 0;
  47.  
  48.   for (this_row = 0; this_row < BITMAP_HEIGHT (*b); this_row++)
  49.     for (this_col = 0; this_col < BITMAP_WIDTH (*b); this_col++)
  50.       {
  51.         if (BITMAP_PIXEL (*b, this_row, this_col) != WHITE)
  52.           {
  53.             int row_enlarge, col_enlarge;
  54.             /* Generate two random numbers between -random_max and
  55.                random_max to give rise to the new x and y.  */
  56.             real random1 = random_number ();
  57.             int row_delta = random1 + .5 * SIGN (random1);
  58.             int new_row = this_row + row_delta;
  59.  
  60.             real random2 = random_number ();
  61.             int col_delta = random2 + .5 * SIGN (random2);
  62.             int new_col = this_col + col_delta;
  63.  
  64.             /* Clear the old location before we (possibly) mess with the
  65.                bitmap dimensions.  */
  66.             BITMAP_PIXEL (*b, this_row, this_col) = WHITE;
  67.  
  68.             /* Check if the new location is outside the current bitmap.  */
  69.             if (new_row < 0)
  70.               {
  71.                 row_enlarge = new_row;
  72.                 /* Negative rows are off the top of the bitmap -- it's
  73.                    in C coordinates, not Cartesian.  */
  74.                 MAX_ROW (*adjust) -= row_enlarge;
  75.               }
  76.             else if (new_row >= BITMAP_HEIGHT (*b))
  77.               {
  78.                 row_enlarge = new_row - BITMAP_HEIGHT (*b) + 1;
  79.                 MIN_ROW (*adjust) += row_enlarge;
  80.               }
  81.             else
  82.               row_enlarge = 0;
  83.  
  84.             if (new_col < 0)
  85.               {
  86.                 col_enlarge = new_col;
  87.                 MIN_COL (*adjust) -= col_enlarge;
  88.               }
  89.             else if (new_col >= BITMAP_WIDTH (*b))
  90.               {
  91.                 col_enlarge = new_col - BITMAP_WIDTH (*b) + 1;
  92.                 MAX_COL (*adjust) += col_enlarge;
  93.               }
  94.             else
  95.               col_enlarge = 0;
  96.  
  97.             if (row_delta != 0 || col_delta != 0)
  98.               { /* Enlarge the bitmap to make the new location valid.  */
  99.                 bitmap_type new_b
  100.                   = enlarge_bitmap (*b, row_enlarge, col_enlarge);
  101.                 free_bitmap (b);
  102.                 *b = new_b;
  103.                 
  104.                 /* We've made the new row/column at the edge.  */
  105.                 if (new_row < 0) new_row = 0;
  106.                 if (new_col < 0) new_col = 0;
  107.               }
  108.  
  109.             BITMAP_PIXEL (*b, new_row, new_col) = BLACK;
  110.           }
  111.       }
  112. }
  113.  
  114.  
  115. /* Return the enlargement of the bitmap B by ROW_DELTA and COL_DELTA. 
  116.    Negative deltas enlarge to the bottom/left, positive to the
  117.    top/right.  */
  118.  
  119. static bitmap_type
  120. enlarge_bitmap (bitmap_type b, int row_delta, int col_delta)
  121. {
  122.   bitmap_type new;
  123.   dimensions_type new_size;
  124.   unsigned row;
  125.   int row_addend = row_delta < 0 ? abs (row_delta) : 0;
  126.   int col_addend = col_delta < 0 ? abs (col_delta) : 0;
  127.   
  128.   DIMENSIONS_HEIGHT (new_size) = BITMAP_HEIGHT (b) + abs (row_delta);
  129.   DIMENSIONS_WIDTH (new_size) = BITMAP_WIDTH (b) + abs (col_delta);
  130.   
  131.   new = new_bitmap (new_size);
  132.   
  133.   /* `new_bitmap' initializes all the pixels to white, so we don't have
  134.      to do anything to the new rows and columns.  */
  135.   for (row = 0; row < BITMAP_HEIGHT (b); row++)
  136.     {
  137.       one_byte *source = BITMAP_ROW (b, row);
  138.       one_byte *target = BITMAP_ROW (new, row + row_addend) + col_addend;
  139.       
  140.       memcpy (target, source, BITMAP_WIDTH (b));
  141.     }
  142.   
  143.   return new;
  144. }
  145.  
  146.  
  147.  
  148. /* Return a random number between -random_max and random_max.  */
  149.  
  150. static real
  151. random_number ()
  152. {
  153.   static boolean initialized = false;
  154.   real r;
  155.   
  156.   if (!initialized)
  157.     {
  158.       seed_rand (getpid ());
  159.       initialized = true;
  160.     }
  161.  
  162.   /* If the random number is less than `random_threshold', return zero.
  163.      Otherwise, return a random number in the interval
  164.      [-random_max,random_max].  */
  165.   r = (real) k_rand () / RAND_MAX;
  166.   r = r > random_threshold
  167.       ? (real) k_rand () / RAND_MAX * random_max - random_max
  168.       : 0;
  169.  
  170.   return r;
  171. }
  172.