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
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <mach.h>
include <imhdr.h>
include <gset.h>
define SZ_CHOICE 18
define HIST_TYPES "|normal|cumulative|difference|second_difference|"
define NORMAL 1
define CUMULATIVE 2
define DIFFERENCE 3
define SECOND_DIFF 4
define PLOT_TYPES "|line|box|"
define LINE 1
define BOX 2
define SZ_TITLE 512 # plot title buffer
# IMHISTOGRAM -- Compute and plot the histogram of an image.
procedure t_imhistogram()
long v[IM_MAXDIM]
real z1, z2, dz, z1temp, z2temp, zstart
int npix, nbins, nbins1, nlevels, nwide, z1i, z2i, i, maxch, histtype
pointer gp, im, sp, hgm, hgmr, buf, image, device, str, title, op
real clgetr()
pointer immap(), gopen()
int clgeti(), clgwrd()
int imgnlr(), imgnli()
bool clgetb(), fp_equalr()
begin
call smark (sp)
call salloc (image, SZ_LINE, TY_CHAR)
call salloc (str, SZ_CHOICE, TY_CHAR)
# Get the image name.
call clgstr ("image", Memc[image], SZ_LINE)
im = immap (Memc[image], READ_ONLY, 0)
npix = IM_LEN(im,1)
# Get histogram range.
z1 = clgetr ("z1")
z2 = clgetr ("z2")
if (IS_INDEFR(z1) || IS_INDEFR(z2)) {
if (IM_LIMTIME(im) >= IM_MTIME(im)) {
z1temp = IM_MIN(im)
z2temp = IM_MAX(im)
} else
call im_minmax (im, z1temp, z2temp)
if (IS_INDEFR(z1))
z1 = z1temp
if (IS_INDEFR(z2))
z2 = z2temp
}
if (z1 > z2) {
dz = z1; z1 = z2; z2 = dz
}
# Get default histogram resolution.
dz = clgetr ("binwidth")
if (IS_INDEFR(dz))
nbins = clgeti ("nbins")
else {
nbins = nint ((z2 - z1) / dz)
z2 = z1 + nbins * dz
}
# Set the limits for integer images.
switch (IM_PIXTYPE(im)) {
case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
z1i = nint (z1)
z2i = nint (z2)
z1 = real (z1i)
z2 = real (z2i)
}
# Adjust the resolution of the histogram and/or the data range
# so that an integral number of data values map into each
# histogram bin (to avoid aliasing effects).
if (clgetb ("autoscale"))
switch (IM_PIXTYPE(im)) {
case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
nlevels = z2i - z1i
nwide = max (1, nint (real (nlevels) / real (nbins)))
nbins = max (1, nint (real (nlevels) / real (nwide)))
z2i = z1i + nbins * nwide
z2 = real (z2i)
}
# The extra bin counts the pixels that equal z2 and shifts the
# remaining bins to evenly cover the interval [z1,z2].
# Real numbers could be handled better - perhaps adjust z2
# upward by ~ EPSILONR (in ahgm itself).
nbins1 = nbins + 1
# Initialize the histogram buffer and image line vector.
call salloc (hgm, nbins1, TY_INT)
call aclri (Memi[hgm], nbins1)
call amovkl (long(1), v, IM_MAXDIM)
# Read successive lines of the image and accumulate the histogram.
switch (IM_PIXTYPE(im)) {
case TY_SHORT, TY_USHORT, TY_INT, TY_LONG:
# Test for constant valued image, which causes zero divide in ahgm.
if (z1i == z2i) {
call eprintf ("Warning: Image `%s' has no data range.\n")
call pargstr (Memc[image])
call imunmap (im)
call sfree (sp)
return
}
while (imgnli (im, buf, v) != EOF)
call ahgmi (Memi[buf], npix, Memi[hgm], nbins1, z1i, z2i)
default:
# Test for constant valued image, which causes zero divide in ahgm.
if (fp_equalr (z1, z2)) {
call eprintf ("Warning: Image `%s' has no data range.\n")
call pargstr (Memc[image])
call imunmap (im)
call sfree (sp)
return
}
while (imgnlr (im, buf, v) != EOF)
call ahgmr (Memr[buf], npix, Memi[hgm], nbins1, z1, z2)
}
# "Correct" the topmost bin for pixels that equal z2. Each
# histogram bin really wants to be half open.
if (clgetb ("top_closed"))
Memi[hgm+nbins-1] = Memi[hgm+nbins-1] + Memi[hgm+nbins1-1]
dz = (z2 - z1) / real (nbins)
histtype = clgwrd ("hist_type", Memc[str], SZ_CHOICE, HIST_TYPES)
switch (histtype) {
case NORMAL:
# do nothing
case CUMULATIVE:
call ih_acumi (Memi[hgm], Memi[hgm], nbins)
case DIFFERENCE:
call ih_amrgi (Memi[hgm], Memi[hgm], nbins)
z1 = z1 + dz / 2.
z2 = z2 - dz / 2.
nbins = nbins - 1
case SECOND_DIFF:
call ih_amrgi (Memi[hgm], Memi[hgm], nbins)
call ih_amrgi (Memi[hgm], Memi[hgm], nbins-1)
z1 = z1 + dz
z2 = z2 - dz
nbins = nbins - 2
default:
call error (1, "bad switch 1")
}
# List or plot the histogram. In list format, the bin value is the
# z value of the left side (start) of the bin.
if (clgetb ("listout")) {
zstart = z1 + dz / 2.0
do i = 1, nbins {
call printf ("%g %d\n")
call pargr (zstart)
call pargi (Memi[hgm+i-1])
zstart = zstart + dz
}
} else {
call salloc (device, SZ_FNAME, TY_CHAR)
call salloc (title, SZ_TITLE, TY_CHAR)
call salloc (hgmr, nbins, TY_REAL)
call achtir (Memi[hgm], Memr[hgmr], nbins)
call clgstr ("device", Memc[device], SZ_FNAME)
gp = gopen (Memc[device], NEW_FILE, STDGRAPH)
if (clgetb ("logy"))
call gseti (gp, G_YTRAN, GW_LOG)
call gswind (gp, z1, z2, INDEF, INDEF)
call gascale (gp, Memr[hgmr], nbins, 2)
# Format the plot title, starting with the system banner.
call sysid (Memc[title], SZ_TITLE)
for (op=title; Memc[op] != '\n' && Memc[op] != EOS; op=op+1)
;
Memc[op] = '\n'; op = op + 1
maxch = SZ_TITLE - (op - title)
# Format the remainder of the plot title.
call sprintf (Memc[op], maxch,
"%s of %s = %s\nFrom z1=%g to z2=%g, nbins=%d, width=%g")
switch (histtype) {
case NORMAL:
call pargstr ("Histogram")
case CUMULATIVE:
call pargstr ("Cumulative histogram")
case DIFFERENCE:
call pargstr ("Difference histogram")
case SECOND_DIFF:
call pargstr ("Second difference histogram")
default:
call error (1, "bad switch 3")
}
call pargstr (Memc[image])
call pargstr (IM_TITLE(im))
call pargr (z1)
call pargr (z2)
call pargi (nbins)
call pargr (dz)
# Draw the plot. Center the bins for plot_type=line.
call glabax (gp, Memc[title], "", "")
switch (clgwrd ("plot_type", Memc[str], SZ_LINE, PLOT_TYPES)) {
case LINE:
call gvline (gp, Memr[hgmr], nbins, z1 + dz/2., z2 - dz/2.)
case BOX:
call hgline (gp, Memr[hgmr], nbins, z1, z2)
default:
call error (1, "bad switch 2")
}
call gclose (gp)
}
call imunmap (im)
call sfree (sp)
end
# HGLINE -- Draw a stepped curve of the histogram data.
procedure hgline (gp, ydata, npts, x1, x2)
pointer gp # Graphics descriptor
real ydata[ARB] # Y coordinates of the line endpoints
int npts # Number of line endpoints
real x1, x2
int pixel
real x, y, dx
begin
dx = (x2 - x1) / npts
# Do the first horizontal line
x = x1
y = ydata[1]
call gamove (gp, x, y)
x = x + dx
call gadraw (gp, x, y)
do pixel = 2, npts {
x = x1 + dx * (pixel - 1)
y = ydata[pixel]
# vertical connection
call gadraw (gp, x, y)
# horizontal line
call gadraw (gp, x + dx, y)
}
end
# These two routines are intended to be generic vops routines. Only
# the integer versions are included since that's all that's used here.
# <NOT IMPLEMENTED!> The operation is carried out in such a way that
# the result is the same whether or not the output vector overlaps
# (partially) the input vector. The routines WILL work in place!
# ACUM -- Compute a cumulative vector (generic). Should b[1] be zero?
procedure ih_acumi (a, b, npix)
int a[ARB], b[ARB]
int npix, i
# int npix, i, a_first, b_first
begin
# call zlocva (a, a_first)
# call zlocva (b, b_first)
#
# if (b_first <= a_first) {
# Shouldn't use output arguments internally,
# but no reason to use this routine unsafely.
b[1] = a[1]
do i = 2, npix
b[i] = b[i-1] + a[i]
# } else {
# overlapping solution not implemented yet!
# }
end
# AMRG -- Compute a marginal (forward difference) vector (generic).
procedure ih_amrgi (a, b, npix)
int a[ARB], b[ARB]
int npix, i
# int npix, i, a_first, b_first
begin
# call zlocva (a, a_first)
# call zlocva (b, b_first)
#
# if (b_first <= a_first) {
do i = 1, npix-1
b[i] = a[i+1] - a[i]
b[npix] = 0
# } else {
# overlapping solution not implemented yet!
# }
end
|