aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/imdkern/imdpcell.x
blob: deb61d1873ce284e6ae2b5061394750412076825 (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
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<gki.h>
include	"imd.h"

define	DEF_YRES	8192	# default height of device pixel in GKI units
define	ZSTEP		4	# bit to be tested (step function width)


# IMD_PUTCELLARRAY -- Draw a cell array, i.e., two dimensional array of pixels
# (greylevels or colors).  The algorithm used here maps 8 bits in into 1 bit
# out, using a step function lookup table.  The result is a band-contoured
# image, where the spacing and width of the contour bands decreases as the
# rate of change of intensity in the input cell array increases.

procedure imd_putcellarray (m, nx, ny, ax1,ay1, ax2,ay2)

short	m[nx,ny]		# cell array
int	nx, ny			# number of pixels in X and Y
int	ax1, ay1		# lower left corner of output window
int	ax2, ay2		# upper right corner of output window

bool	ttygetb()
include	"imd.com"

begin
	if (ttygetb (g_tty, "BI"))
	    call imd_bcell (m, nx, ny, ax1,ay1, ax2,ay2)
	else
	    call imd_mcell (m, nx, ny, ax1,ay1, ax2,ay2)
end


# IMD_BCELL -- Put cell array, optimized for a bitmap device.  In this case,
# to get the maximum resolution at maximum efficiency it is desirable for the
# main loop to be over device pixels, mapping the device pixel into the
# nearest line of the input cell array.

procedure imd_bcell (m, nx, ny, ax1,ay1, ax2,ay2)

short	m[nx,ny]		# cell array
int	nx, ny			# number of pixels in X and Y
int	ax1, ay1		# lower left corner of output window
int	ax2, ay2		# upper right corner of output window

real	dx, dy
int	my, i1, i2, v, i, j, k
include	"imd.com"
int	and()

begin
	# Count drawing instruction, set polyline width to 1 for max y-res.
	g_ndraw = g_ndraw + 1
	call idk_linewidth (g_out, 1)
	IMD_WIDTH(g_kt) = 0

	# Determine the width of a cell array pixel in GKI units.
	dx = real (ax2 - ax1) / nx

	# Determine the height of a device pixel in GKI units.
	if (IMD_YRES(g_kt) <= 0)
	    dy = GKI_MAXNDC / DEF_YRES
	else
	    dy = max (1.0, real(GKI_MAXNDC) / real(IMD_YRES(g_kt)))

	# Process the cell array.  The outer loop runs over device pixels in Y;
	# each iteration writes one line of the output raster.  The inner loop
	# runs down a line of the cell array.

	k = 0
	for (my = ay1 + dy/2;  my < ay2;  my = k * dy + ay1) {
	    j = max(1, min(ny, int (real(my-ay1) / real(ay2-ay1) * (ny-1)) + 1))
	    my = min (my, int (ay2 - dy/2))

	    for (i=1;  i <= nx;  ) {
		do i = i, nx {
		    v = m[i,j]
		    if (and (v, ZSTEP) != 0)
			break
		}

		if (i <= nx) {
		    i1 = i
		    i2 = nx
		    do i = i1 + 1, nx {
			v = m[i,j]
			if (and (v, ZSTEP) == 0) {
			    i2 = i
			    break
			}
		    }

		    # The following decreases the length of dark line segments
		    # to make features more visible.

		    if (i2 - i1 >= 2)
			if (i1 > 1 && i2 < nx) {
			    i1 = i1 + 1
			    i2 = i2 - 1
			}

		    # Draw the line segment.
		    call idk_move (g_out, int ((i1-1) * dx + ax1), my)
		    call idk_draw (g_out, int (i2 * dx + ax1), my)

		    if (i2 >= nx)
			i = nx + 1
		}
	    }

	    k = k + 1
	}
end


# IMD_MCELL -- Put cell array, optimized for a metafile device.  In this case,
# it is prohibitively expensive to draw into each resolvable line of the
# output device.  It is better to set the linewidth to the width of a cell
# array pixel, output the minimum number of drawing instructions, and let the
# metafile device widen the lines.

procedure imd_mcell (m, nx, ny, ax1,ay1, ax2,ay2)

short	m[nx,ny]		# cell array
int	nx, ny			# number of pixels in X and Y
int	ax1, ay1		# lower left corner of output window
int	ax2, ay2		# upper right corner of output window

real	dx, dy
int	yres, my, i1, i2, v, i, j
include	"imd.com"
int	and()

begin
	# Count drawing instruction, clobber saved polyline width.
	g_ndraw = g_ndraw + 1
	IMD_WIDTH(g_kt) = 0

	# Determine the width and height of a cell array pixel in GKI units.
	dx = real (ax2 - ax1) / nx
	dy = real (ay2 - ay1) / ny

	# Set the IDK line width to the height of a pixel in the cell array.
	yres = IMD_YRES(g_kt)
	if (yres <= 0)
	    yres = DEF_YRES
	call idk_linewidth (g_out,
	    max (1, nint (dy / (real(GKI_MAXNDC) / real(yres)))))

	# Process the cell array.  The outer loop runs over lines of the input
	# cell array; each iteration writes only one line of the output raster,
	# but the width of the line is adjusted to the height of a pixel in
	# the cell array (the resolution of the cell array should not exceed
	# that of the device).

	for (j=1;  j <= ny;  j=j+1) {
	    my = int ((j - 0.5) * dy) + ay1

	    for (i=1;  i <= nx;  ) {
		do i = i, nx {
		    v = m[i,j]
		    if (and (v, ZSTEP) != 0)
			break
		}

		if (i <= nx) {
		    i1 = i
		    i2 = nx
		    do i = i + 1, nx {
			v = m[i,j]
			if (and (v, ZSTEP) == 0) {
			    i2 = i
			    break
			}
		    }

		    # The following decreases the length of dark line segments
		    # to make features more visible.

		    if (i2 - i1 >= 2)
			if (i1 > 1 && i2 < nx) {
			    i1 = i1 + 1
			    i2 = i2 - 1
			}

		    # Draw the line segment.
		    call idk_move (g_out, int ((i1-1) * dx + ax1), my)
		    call idk_draw (g_out, int (i2 * dx + ax1), my)

		    if (i2 >= nx)
			i = nx + 1
		}
	    }
	}
end