summaryrefslogtreecommitdiffstats
path: root/dis/Neighborhood/initializeImage.c
blob: a030a1a90c7ff20d3573e54c578b6f5a6c5748a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/* Copyright 2000, Atlantic Aerospace Electronics Corp */
/*
 * Name:    initializeImage
 * Input:   dimension      dimension of image
 *	    maxImageValue  max legal image value
 *	    numberLines    number line segments for image
 *	    minThickness   min thickness for line segment
 *	    maxThickness   max thickness for line segment
 * Output:  image          image initialized
 * Comment: This routine allocates memory to store an image and fills
 *          in the image structure except for the image data.  The 
 *          pixels of the image are of type ShortInt. If there
 *          is an error allocating memory, than a NULL pointer is 
 *          returned. Assumptions: the image dimensions given are 
 *          positive.
 * Calls:   errorMessage()
 * (system) malloc()
 *          free()
 * Return:  image structure pointer (partially filled in - no data -  
 *                                   and allocated)
 *          NULL (error allocating memory for image/image structure)
 *
 * Revision   History:
 * Date       Name         Revision
 * ---------  -----------  -----------------------------
 * 25May2000  May Leung    Created
 * 05Jun2000  May Leung    Add maxImageValue as input to initializeImage()
 * XXMay2020 Joshua Bakita Commented out significant portions to allow this to
 *                         be #include(d) elsewhere.
 */
typedef int Int;
typedef short int ShortInt;
typedef float Float;
void drawRowPoint (Int   value,
              Int   pointThickness,
              Int   row,
              Int   column,
              Image *image);
void drawColumnPoint (Int   value,
                 Int   pointThickness,
                 Int   row,
                 Int   column,
                 Image *image);
#define MIN_RANDOM_VALUE 0
#if 0
#ifndef NDEBUG
#include <stdio.h>
#endif /* NDEBUG */
#include <assert.h>                         /* define assert() */
#include <stdlib.h>                         /* define NULL, malloc(), free() */
#include "stressmark.h"                     /* system include file */
#include "neighborhood.h"	            /* define types, structures, etc  */
#include "errorMessage.h"                   /* define errorMessage() */
#include "random.h"		            /* define randomUInt() */
#include "initializeImage.h"                /* define initializeImage() */

Image *initializeImage (Int dimension,     /* dimension of image */
			Int maxImageValue, /* max legal image value */
			Int numberLines,   /* number line segments for image */
			Int minThickness,  /* min thickness for line segment */
			Int maxThickness)  /* max thickness for line segment */
{ /* beginning of initializeImage() */

  Image    *image;              /* pointer to image structure to allocate */   
  ShortInt *data;	        /* pointer to the data for the image structure*/
  Int      lineIndex;	        /* loop index variable for line segments */    
  Int      pixelIndex;	        /* loop index variable for pixels */           
  Int      limit;	        /* limit for loop using pixelIndex */          
			                                                       
  Coord    startPoint;	        /* starting point for a line segment */        
  Coord    endPoint;	        /* ending point for a line segment */          
  Int      lineThickness;       /* thickness for a line segment */
  Int      startValue;	        /* starting value for a line segment */        
  Int      endValue;	        /* ending value for a line segment */          

  /*
   * Assert the assumptions that the number of columns and number of rows
   * are positive values.  No test on the maximum possible value is done since
   * numColumns and numRows are of type Int and the maximum value of an Int
   * type is possible.
   */
  assert(dimension > 0);
  assert(numberLines > 0);
  assert((minThickness > 0) && (minThickness < dimension));
  assert((maxThickness > 0) && (maxThickness < dimension));
  assert(minThickness <= maxThickness);

  /* create image */
  image = createImage(dimension,dimension,maxImageValue);
  if (image == NULL) {
    return(NULL);
  } /* end error check from createImage */

  /* zero out the image */
  limit = dimension * dimension;
  data = image->data;
  for (pixelIndex = 0; pixelIndex < limit; pixelIndex++) {
    *data++ = 0;
  } /* end for loop */

  /*
   * Populate the image with line segments where the endpoints, values, and 
   * thickness of each line segment are randomly generated.
   */
  for (lineIndex = 0; lineIndex < numberLines; lineIndex++) {
    randomImageLocation(image, &startPoint);
    randomImageLocation(image, &endPoint);
    lineThickness = randomUInt(minThickness,maxThickness);
    startValue = randomUInt(MIN_RANDOM_VALUE, maxImageValue);
    endValue = randomUInt(MIN_RANDOM_VALUE, maxImageValue);

    /* add line segment to the image */
    drawLineSegment(&startPoint, &endPoint, startValue, endValue, lineThickness,
		    image);

    } /* end for loop */

  return(image);
} /* end initializeImage() */
#endif

/*
 * drawLineSegment() This routine draws a line segment into the given image
 *                   starting at the coordinate startPoint and ending at the
 *                   coordinate endPoint.  The values along this line segment
 *                   vary linearly from the given starting value startValue to
 *                   the end value endValue and have a lineThickness associated
 *                   to it.
 *
 * This routine is modeled after the routine draw_line() from 
 * "Practical Computer Vision using C", by J.R. Parker, Wiley, 1994, pp 114-116.
 * It has been enhanced to have values on the line segment vary and to have
 * a thickness to the line segment.
 */
void drawLineSegment (Coord *startPoint,   /* starting point for line segment */
		      Coord *endPoint,	   /* ending point for line segment */  
		      Int   startValue,	   /* starting value for line segment */
		      Int   endValue,	   /* ending value for line segment */  
		      Int   lineThickness, /* thickness for line segment */     
		      Image *image)	   /* image to add line segment to */   
{ /* beginning of drawLineSegment() */

  /*
   * Modeled after draw_line() from "Practical Computer Vision using C",
   * by J.R. Parker, Wiley, 1994, pp 114-116.  Enhanced to have values
   * on the line segment vary and to have a thickness to the line segment.
   * The value along the line segment is kept in a float variable so that 
   * fractional increments along the line segment can accumulate to integer
   * values.
   */
  Int   changeColumn, changeRow; /* change along line segment in col/row */     
  Int   absColumn, absRow;	 /* absolute value of change in col/row */      
  Int   signColumn, signRow;	 /* sign of change along line segment col/row */
  Int   delta;			 /* increment alone line segment */             
  Int   column, row;		 /* column & row of coordinate along line seg */
  Float value, valueDelta;	 /* value & value change along line segment */  

//  assert(validImage(image));
  assert(startPoint != NULL);
  assert(endPoint != NULL);

#ifdef DEBUG0
  fprintf(stderr,
	  "drawLineSegment: start row %6ld col %6ld\tend row %6ld col %6ld\n",
	  startPoint->row,startPoint->column,endPoint->row,endPoint->column);
  fprintf(stderr,"                 startVal %6ld endVal %6ld thickness %6ld\n",
	  startValue, endValue, lineThickness);
#endif /* DEBUG0 */

  changeColumn = endPoint->column - startPoint->column;
  if (changeColumn < 0) {
    absColumn  = - changeColumn;
    signColumn = - 1;
  } /* end changeColumn < 0 */
  else { /* changeColumn >= 0 */
    absColumn  = changeColumn;
    signColumn = 1;
  } /* end changeColumn >= 0 */
  absColumn *= 2;

  changeRow = endPoint->row - startPoint->row;
  if (changeRow < 0) {
    absRow  = - changeRow;
    signRow = - 1;
  } /* end changeRow < 0 */
  else { /* changeRow >= 0 */
    absRow  = changeRow;
    signRow = 1;
  } /* end changeRow >= 0 */
  absRow *= 2;

  column = startPoint->column;
  row    = startPoint->row;
  value  = startValue;		/* add changing value to algorithm */

  if (signColumn * changeColumn > signRow * changeRow) { /* column dominant */
    /* determine the change in value for each step (added to algorithm) */
    valueDelta = ((Float) endValue - startValue) / 
                 ((Float) changeColumn * signColumn);

    delta = absRow - (absColumn / 2);
    while (TRUE) { /* inifinite loop */
      /*
       * Line is column dominant, so line thickness will be along rows. Make
       * sure the ending value doesn't go beyond endValue. (Added to algorithm)
       */
      drawRowPoint((Int) value, lineThickness, row, column, image);
      if (valueDelta >=0) {
	value = MIN(endValue, value+valueDelta);
      } /* values are incrementing */
      else { /* valueDelta < 0 */
	value = MAX(endValue, value+valueDelta);
      } /* values are decreasing */

      if (column == endPoint->column) {
	return; /* done with line segment exit routine */
      } /* end exit criteria */
      if (delta >= 0) {
	row += signRow;
	delta -= absColumn;
      } /* end if delta >= 0 */
      column += signColumn;
      delta += absRow;
    } /* end while infinite loop */
  } /* end row dominant case */
  else {			  /* row dominant case */
    /* determine the change in value for each step (added to algorithm) */
    if (changeRow == 0) {
      valueDelta = 0;
      assert(changeColumn == 0);
    } /* end if changeRow == 0 */
    else {
      valueDelta = ((Float) endValue - startValue) / 
	           ((Float) changeRow * signRow);
    } /* end else */

    delta = absColumn - (absRow / 2);
    while (TRUE) { /* inifinite loop */
      /*
       * Line is row dominant, so line thickness will be along columns. Make
       * sure the ending value doesn't go beyond endValue. (Added to algorithm)
       */
      drawColumnPoint((Int) value, lineThickness, row, column, image);
      if (valueDelta >=0) {
	value = MIN(endValue, value+valueDelta);
      } /* values are incrementing */
      else { /* valueDelta < 0 */
	value = MAX(endValue, value+valueDelta);
      } /* values are decreasing */

      if (row == endPoint->row) {
	return; /* done with line segment exit routine */
      } /* end exit criteria */
      if (delta >= 0) {
	column += signColumn;
	delta -= absRow;
      } /* end if delta >= 0 */
      row += signRow;
      delta += absColumn;
    } /* end while infinite loop */
  } /* end column dominant case */

  return;
} /* end of drawLineSegment() */

/*
 * drawRowPoint() This routine draws a point with a row thickness onto the
 *                given image for the coordinate and value provided.
 */
void drawRowPoint (Int   value,          /* value for point */           
		   Int   pointThickness, /* thickness for point */       
		   Int   row, 		 /* row coordinate of point */   
		   Int   column,	 /* column coordinate of point */
		   Image *image)	 /* image to draw point onto */  
{ /* beginning of drawRowPoint() */
  Int      halfThickness;		 /* half the point thickness */
  Int      lowerRow, upperRow, rowIndex; /* loop boundaries and index for row */
  ShortInt *data;			 /* image data pointer */

//  assert(validImage(image));
  assert(value >= MIN_RANDOM_VALUE);
  assert(value <= image->maxImageValue);
  assert(pointThickness > 0);

#ifdef DEBUG0
  fprintf(stderr,
	  "drawRowPoint: value %5ld, thickness %6ld, row %6ld, column %6ld\n",
	  value,pointThickness,row,column);
#endif /* DEBUG0 */

  halfThickness = (Int) pointThickness / 2; /* use integer division */
  lowerRow = MAX(0, row - halfThickness);
  upperRow = MIN(image->numRows, row + pointThickness - halfThickness);

  data = image->data + (lowerRow * image->numColumns) + column;
  for (rowIndex = lowerRow; rowIndex < upperRow; rowIndex++) {
    *data  = (ShortInt) value;
    data  += image->numColumns; /* increment pointer to next row */
  } /* end for loop */

  return;
} /* end of drawRowPoint() */

/*
 * drawColumnPoint() This routine draws a point with a column thickness onto the
 *                   given image for the coordinate and value provided.
 */
void drawColumnPoint (Int   value,          /* value for point */
		      Int   pointThickness, /* thickness for point */
		      Int   row,            /* row coordinate of point */
		      Int   column,         /* column coordinate of point */
		      Image *image)         /* image to draw point onto */
{ /* beginning of drawColumnPoint() */
  Int      halfThickness;		         /* half the point thickness */
  Int      leftColumn, rightColumn, columnIndex; /* col loop boundaries&index*/
  ShortInt *data;			         /* image data pointer */

//  assert(validImage(image));
  assert(value >= MIN_RANDOM_VALUE);
  assert(value <= image->maxImageValue);
  assert(pointThickness > 0);

#ifdef DEBUG0
  fprintf(stderr,
	  "drawColumnPoint: value %5ld, thickness %6ld, row %6ld, column %6ld\n",
	  value,pointThickness,row,column);
#endif /* DEBUG0 */

  halfThickness = (Int) pointThickness / 2; /* use integer division */
  leftColumn = MAX(0, column - halfThickness);
  rightColumn = MIN(image->numColumns, column + pointThickness - halfThickness);

  data = image->data + (row * image->numColumns) + leftColumn;
  for (columnIndex = leftColumn; columnIndex < rightColumn; columnIndex++) {
    *data  = (ShortInt) value;
    data++; /* increment pointer to next column */
  } /* end for loop */

  return;
} /* end of drawColumnPoint() */

/*
 * randomImageLocation() This routine generates a random coordinate yielding a
 *                       coordinate in the given image using randomUInt().
 */
#if 0
#include "random.h"

void randomImageLocation (Image *image,	   /* image in question */
			  Coord *location) /* random location generated */
{ /* beginning of randomImageLocation() */
  Int index;			/* random location in image */
  Int maxIndex;			/* maximum index in image */

  assert(validImage(image));
  assert(location != NULL);

  maxIndex = image->numColumns * image->numRows - 1;
  index = randomUInt(0, maxIndex);

  /* use integer division to clip to closest integer value */
  location->row = (Int) index / image->numColumns;
  location->column = index - (location->row * image->numColumns);

  assert((location->row >= 0) && (location->row < image->numRows));
  assert((location->column >= 0) && (location->column < image->numColumns));
  assert(index = location->column + (location->row * image->numColumns));

  return;
} /* end of randomImageLocation() */
#endif