aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/tv/imedit/t_imedit.x
blob: 984ce86ba4f091b3beb0d968eb0dec5108c7a275 (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
include	<error.h>
include	<imhdr.h>
include	"epix.h"
 
define	HELP		"imedit_help$"
define	PROMPT		"imedit options"
 
# T_IMEDIT -- Edit image pixels.
# This task provides selection of pixels to be edit via cursor or file
# input.  The regions to be edited may be defined as a rectangle or a
# center and radius for a circular or square aperture.  The replacement
# options include constant substitution, background substitution, column
# or line interpolation, and moving one region to another.  In addition
# this task can be used to select and display regions in surface perspective
# and to print statistics.  The image display interface temporarily
# used simple calls to a user specified display task (such as TV.DISPLAY).
# The editing is done in a temporary image buffer.  The commands which
# alter the input image may be logged if a log file is given.
 
procedure t_imedit ()
 
int	inlist		# List of input images
int	outlist		# List of output images
 
int	i, key, ap, xa, ya, xb, yb, x1, x2, y1, y2
int	change, changes, newdisplay, newimage
bool	erase
pointer	sp, ep, cmd, temp
pointer	im
 
bool	streq()
pointer	immap(), imgl2r(), impl2r()
int	imtopenp(), imtlen(), imtgetim(), imaccess(), ep_gcur()
errchk	immap, imdelete, ep_imcopy, ep_setpars, imgl2r, impl2r
 
define	newim_	99
 
begin
	call smark (sp)
	call salloc (cmd, SZ_LINE, TY_CHAR)

	# Allocate and initialize imedit descriptor.
	call salloc (ep, EP_LEN, TY_STRUCT)
	call aclri (Memi[ep], EP_LEN)
 
	# Check the input and output image lists have proper format.
	inlist = imtopenp ("input")
	outlist = imtopenp ("output")
	if (imtlen (outlist) > 0 && imtlen (outlist) != imtlen (inlist))
	    call error (1, "Input and output lists are not the same length")
 
	# Set the rest of the task parameters.
	call ep_setpars (ep)
 
	# Repeat on each input image.
	while (imtgetim (inlist, EP_INPUT(ep), EP_SZFNAME) != EOF) {
	    if (imtgetim (outlist, EP_OUTPUT(ep), EP_SZFNAME) == EOF)
		call strcpy (EP_INPUT(ep), EP_OUTPUT(ep), EP_SZFNAME)
	    else if (imaccess (EP_OUTPUT(ep), READ_ONLY) == YES) {
		call eprintf ("%s: Output image %s exists\n")
		    call pargstr (EP_INPUT(ep))
		    call pargstr (EP_OUTPUT(ep))
		next
	    }
 
	    # The editing takes place in a temporary editing image buffer.
newim_	    call strcpy (EP_OUTPUT(ep), EP_WORK(ep), EP_SZFNAME)
	    call xt_mkimtemp (EP_OUTPUT(ep), EP_WORK(ep), EP_OUTPUT(ep),
		EP_SZFNAME)
	    iferr (call ep_imcopy (EP_INPUT(ep), EP_WORK(ep))) {
		call erract (EA_WARN)
		next
	    }

	    EP_IM(ep) = immap (EP_WORK(ep), READ_WRITE, 0)
	    EP_INDATA(ep) = NULL
	    EP_OUTDATA(ep) = NULL
 
	    if (EP_LOGFD(ep) != NULL) {
		call fprintf (EP_LOGFD(ep), "# Input image %s\n")
		    call pargstr (EP_INPUT(ep))
	    }
 
	    if (EP_DISPLAY(ep) == YES) {
		key = '0'
		call ep_zoom (ep, xa, ya, xb, yb, key, erase)
	        call ep_command (ep, EP_WORK(ep), erase)
	    }
 
 
	    # Enter the cursor loop.  The apertures and commands are
	    # returned by the EP_GCUR procedure.
 
	    newimage = NO
	    changes = 0
	    while (ep_gcur (ep,ap,xa,ya,xb,yb,key,Memc[cmd],SZ_LINE) != EOF) {
	        newdisplay = NO
	        change = NO
 
		iferr {
		    switch (key) {
		    case '?':	# Print help
			call pagefile (HELP, PROMPT)
		    case ':':	# Process colon commands
			call ep_colon (ep, Memc[cmd], newimage)
			if (newimage == YES)
			    break
		    case 'a', 'b':	# Background replacement
			call ep_background (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'c':	# Column interpolation
			call ep_col (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'd', 'e', 'v':	# Constant value
			call ep_constant (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'f':	# Diagonal aperture
			if (ap == APCDIAG)
			    call ep_col (ep, ap, xa, ya, xb, yb)
			else
			    call ep_line (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case '=', '<', '>':	# Replace
			if (IM_PIXTYPE(EP_IM(ep)) == TY_INT)
			    call ep_replacei (ep, xa, ya, key)
			else
			    call ep_replacer (ep, xa, ya, key)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'i':	# Initialize
			call imunmap (EP_IM(ep))
			goto newim_
		    case 'j', 'k':	# Replace with input
			call ep_input (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'l':	# Line interpolation
			call ep_line (ep, ap, xa, ya, xb, yb)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'm', 'n':	# Move
			    i = ep_gcur (ep, ap, x1, y1, x2, y2, key,
				Memc[cmd],SZ_LINE)
			call ep_move (ep, ap, xa, ya, xb, yb, x1, y1, x2, y2,
			    key)
			if (EP_OUTDATA(ep) != NULL) {
			    change = YES
			    changes = changes + 1
			}
		    case 'g':	# Surface graph
			call ep_dosurface (ep)
		    case ' ':	# Statistics
			call ep_statistics (ep, ap, xa, ya, xb, yb, NO)
		    case 'p':
			call ep_statistics (ep, ap, xa, ya, xb, yb, YES)
		    case 't':
			EP_SEARCH(ep) = -EP_SEARCH(ep)
			call ep_colon (ep, "search", newimage)
		    case '+':
			EP_RADIUS(ep) = EP_RADIUS(ep) + 1.
			call ep_colon (ep, "radius", newimage)
		    case '-':
			EP_RADIUS(ep) = max (0., EP_RADIUS(ep) - 1.)
			call ep_colon (ep, "radius", newimage)
		    case 's':	# Surface plot
			i = max (5.,
			    abs (EP_SEARCH(ep))+EP_BUFFER(ep)+EP_WIDTH(ep)+1)
			x1 = min (xa, xb) - i
			x2 = max (xa, xb) + i
			y1 = min (ya, yb) - i
			y2 = max (ya, yb) + i
			call ep_gindata (ep, x1, x2, y1, y2)
			EP_OUTDATA(ep) = NULL
			call ep_dosurface (ep)
		    case 'q':	# Quit and save
		    case 'u':	# Undo
			if (EP_OUTDATA(ep) != NULL && EP_INDATA(ep) != NULL) {
			    call malloc (temp, EP_NPTS(ep), TY_REAL)
			    call amovr (Memr[EP_OUTDATA(ep)], Memr[temp],
				EP_NPTS(ep))
			    call amovr (Memr[EP_INDATA(ep)],
				Memr[EP_OUTDATA(ep)], EP_NPTS(ep))
			    call amovr (Memr[temp], Memr[EP_INDATA(ep)],
				EP_NPTS(ep))
			    call mfree (temp, TY_REAL)
			    change = YES
			} else
			    call eprintf ("Can't undo last change\007\n")
		    case 'r', 'E', 'P', 'R', 'Z', '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9':
			if (EP_DISPLAY(ep) == YES) {
			    call ep_zoom (ep, xa, ya, xb, yb, key, erase)
			    newdisplay = YES
			}
		    case 'Q':	# Quit and no save
			changes = 0
		    case 'I':	# Immediate interrupt
			    call imdelete (EP_WORK(ep))
			call fatal (1, "Interrupt")
		    default:
			call printf ("\007")
		    }
		} then
		    call erract (EA_WARN)

		if (key == 'q' || key == 'Q')
		    break
 
		if (change == YES && EP_AUTOSURFACE(ep) == YES)
		    call ep_dosurface (ep)
 
		if (change == YES && EP_AUTODISPLAY(ep) == YES)
		    newdisplay = YES
		if (newdisplay == YES && EP_DISPLAY(ep) == YES)
		    call ep_display (ep, EP_WORK(ep), erase)
 
		# Log certain commands.  Note that this is done after
		# centering.
		if (EP_LOGFD(ep) != NULL) {
		    switch (key) {
		    case 'a', 'c', 'd', 'f', 'j', 'l', 'v':
			call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n")
			    call pargi (xa)
			    call pargi (ya)
			    call pargi (key)
			call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n")
			    call pargi (xb)
			    call pargi (yb)
			    call pargi (key)
		    case 'b', 'e', 'k':
			call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n")
			    call pargi ((xa+xb)/2)
			    call pargi ((ya+yb)/2)
			    call pargi (key)
		    case 'u':
			if (EP_OUTDATA(ep) != NULL) {
			    call fprintf (EP_LOGFD(ep), "%c\n")
				call pargi (key)
			}
		    case 'm', 'n':
			call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n")
			    call pargi ((xa+xb)/2)
			    call pargi ((ya+yb)/2)
			    call pargi (key)
			call fprintf (EP_LOGFD(ep), "%d %d 1 %c\n")
			    call pargi ((x1+x2)/2)
			    call pargi ((y1+y2)/2)
			    call pargi (key)
		    }
		}
	    }
 
	    call imunmap (EP_IM(ep))
	    # Only create the output if the input has been changed.
	    if (changes > 0) {
		if (streq (EP_INPUT(ep), EP_OUTPUT(ep))) {
		    EP_IM(ep) = immap (EP_OUTPUT(ep), READ_WRITE, 0)
		    im = immap (EP_WORK(ep), READ_ONLY, 0)
		    do i = 1, IM_LEN(EP_IM(ep),2)
		        call amovr (Memr[imgl2r(im,i)],
			    Memr[impl2r(EP_IM(ep),i)], IM_LEN(im,1))
		    call imunmap (im)
		    call imunmap (EP_IM(ep))
		    call imdelete (EP_WORK(ep))
		} else {
		    if (imaccess (EP_OUTPUT(ep), READ_ONLY) == YES)
			call imdelete (EP_OUTPUT(ep))
		    call imrename (EP_WORK(ep), EP_OUTPUT(ep))
		}
	    } else
	        call imdelete (EP_WORK(ep))
 
	    # Check for a new image based on a colon command.  This case
	    # always uses the input image name as output.
	    if (newimage == YES) {
		call strcpy (EP_INPUT(ep), EP_OUTPUT(ep), EP_SZFNAME)
		goto newim_
	    }
	}
 
	# Finish up.
	if (EP_LOGFD(ep) != NULL)
	    call close (EP_LOGFD(ep))
	call imtclose (inlist)
	call imtclose (outlist)
	call sfree (sp)
end