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 >
Wrap
C/C++ Source or Header
|
1992-08-24
|
5KB
|
172 lines
/* random.c: distort a bitmap.
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "rand.h"
#include "random.h"
/* Distort the bitmap (see below). (-randomize) */
real random_max = 0.0;
real random_threshold = 0.2;
static bitmap_type enlarge_bitmap (bitmap_type, int, int);
static real random_number (void);
/* Randomize the bitmap B by moving each black pixel a randomly chosen
distance between -random_max and random_max (both horizontally and
vertically). Return the enlargement of B on all four side in ADJUST.
*/
void
randomize_bitmap (bitmap_type *b, bounding_box_type *adjust)
{
unsigned this_row, this_col;
MIN_ROW (*adjust) = MAX_ROW (*adjust) = MIN_COL (*adjust) = MAX_COL (*adjust)
= 0;
for (this_row = 0; this_row < BITMAP_HEIGHT (*b); this_row++)
for (this_col = 0; this_col < BITMAP_WIDTH (*b); this_col++)
{
if (BITMAP_PIXEL (*b, this_row, this_col) != WHITE)
{
int row_enlarge, col_enlarge;
/* Generate two random numbers between -random_max and
random_max to give rise to the new x and y. */
real random1 = random_number ();
int row_delta = random1 + .5 * SIGN (random1);
int new_row = this_row + row_delta;
real random2 = random_number ();
int col_delta = random2 + .5 * SIGN (random2);
int new_col = this_col + col_delta;
/* Clear the old location before we (possibly) mess with the
bitmap dimensions. */
BITMAP_PIXEL (*b, this_row, this_col) = WHITE;
/* Check if the new location is outside the current bitmap. */
if (new_row < 0)
{
row_enlarge = new_row;
/* Negative rows are off the top of the bitmap -- it's
in C coordinates, not Cartesian. */
MAX_ROW (*adjust) -= row_enlarge;
}
else if (new_row >= BITMAP_HEIGHT (*b))
{
row_enlarge = new_row - BITMAP_HEIGHT (*b) + 1;
MIN_ROW (*adjust) += row_enlarge;
}
else
row_enlarge = 0;
if (new_col < 0)
{
col_enlarge = new_col;
MIN_COL (*adjust) -= col_enlarge;
}
else if (new_col >= BITMAP_WIDTH (*b))
{
col_enlarge = new_col - BITMAP_WIDTH (*b) + 1;
MAX_COL (*adjust) += col_enlarge;
}
else
col_enlarge = 0;
if (row_delta != 0 || col_delta != 0)
{ /* Enlarge the bitmap to make the new location valid. */
bitmap_type new_b
= enlarge_bitmap (*b, row_enlarge, col_enlarge);
free_bitmap (b);
*b = new_b;
/* We've made the new row/column at the edge. */
if (new_row < 0) new_row = 0;
if (new_col < 0) new_col = 0;
}
BITMAP_PIXEL (*b, new_row, new_col) = BLACK;
}
}
}
/* Return the enlargement of the bitmap B by ROW_DELTA and COL_DELTA.
Negative deltas enlarge to the bottom/left, positive to the
top/right. */
static bitmap_type
enlarge_bitmap (bitmap_type b, int row_delta, int col_delta)
{
bitmap_type new;
dimensions_type new_size;
unsigned row;
int row_addend = row_delta < 0 ? abs (row_delta) : 0;
int col_addend = col_delta < 0 ? abs (col_delta) : 0;
DIMENSIONS_HEIGHT (new_size) = BITMAP_HEIGHT (b) + abs (row_delta);
DIMENSIONS_WIDTH (new_size) = BITMAP_WIDTH (b) + abs (col_delta);
new = new_bitmap (new_size);
/* `new_bitmap' initializes all the pixels to white, so we don't have
to do anything to the new rows and columns. */
for (row = 0; row < BITMAP_HEIGHT (b); row++)
{
one_byte *source = BITMAP_ROW (b, row);
one_byte *target = BITMAP_ROW (new, row + row_addend) + col_addend;
memcpy (target, source, BITMAP_WIDTH (b));
}
return new;
}
/* Return a random number between -random_max and random_max. */
static real
random_number ()
{
static boolean initialized = false;
real r;
if (!initialized)
{
seed_rand (getpid ());
initialized = true;
}
/* If the random number is less than `random_threshold', return zero.
Otherwise, return a random number in the interval
[-random_max,random_max]. */
r = (real) k_rand () / RAND_MAX;
r = r > random_threshold
? (real) k_rand () / RAND_MAX * random_max - random_max
: 0;
return r;
}