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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
|
\
.\" This man page was generated by the Netpbm tool 'makeman' from HTML source.
.\" Do not hand-hack it! If you have bug fixes or improvements, please find
.\" the corresponding HTML page on the Netpbm website, generate a patch
.\" against that, and send it to the Netpbm maintainer.
.TH "pamhomography" 1 "04 December 2022" "netpbm documentation"
<script type="text/javascript" src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
.SH NAME
.PP
pamhomography - stretch/shrink a quadrilateral region of an image to
another quadrilateral shape
.UN SYNOPSIS
.SH SYNOPSIS
.PP
\fBpamhomography\fP
[\fB-from\fP=\fIcoords\fP]
[\fB-to\fP=\fIcoords\fP]
[\fB-mapfile\fP=\fImap_file\fP]
[\fB-view\fP=\fIcoords\fP]
[\fB-fill\fP=\fIcolor\fP]
[\fB-verbose\fP
[\fIpam_file\fP]
.PP
You can abbreviate any option to its shortest unique prefix. You can use
two hyphens instead of one to delimit an option. You can separate an option
from its value with whitespace instead of \f(CW=\fP.
.UN DESCRIPTION
.SH DESCRIPTION
.PP
This program is part
of
.UR http://netpbm.sourceforge.net/
Netpbm
.UE
\&.
.PP
\fBpamhomography\fP stretches and shrinks an arbitrary quadrilateral
portion of an input image you specify (not necessarily rectangular), into a
new quadrilateral shape you specify, producing a new image.
.PP
You can do any
.UR https://en.wikipedia.org/wiki/Affine_transformation#Image_transformation
affine image transformation
.UE
\&: translation, reflection, scaling,
rotation, and shearing/skewing. However, \fBpamhomography\fP additionally can
do \fIbilinear\fP transforms, which means it can warp any quadrilateral to any
other quadrilateral, even when this mapping cannot be described using a single
set of linear equations. This can be useful, for example, for creating
perspective views of rectangular images or for reverse-mapping a perspective
view back to a rectangular projection.
.UN OPTIONS
.SH OPTIONS
.PP
In addition to the options common to all programs based on libnetpbm (most
notably \fB-quiet\fP, see
.UR http://index.html#commonoptions
Common Options
.UE
\&), \fBpamhomography\fP recognizes the following command line
options:
.TP
\fB-from\fP=\fIcoords\fP
.sp
This defines the source quadrilateral. \fIcoords\fP is a list of four
integer-valued (\fIx\fP, \fIy\fP) coordinates. If you do not specify the
source with either \fB-from\fP or \fB-mapfile\fP, the source quadrilateral
is the entire input image.
.TP
\fB-to\fP=\fIcoords\fP
.sp
This defines the target quadrilateral. \fIcoords\fP is a list of four
integer-valued (\fIx\fP, \fIy\fP) coordinates. If you do not specify the
target with either \fB-to\fP or \fB-mapfile\fP, the target quadrilateral is
the same as the entire input image.
.TP
\fB-mapfile\fP=\fImap_file\fP
.sp
This names a text file that describes the mapping from the source to the
target quadrilateral. The file \fImap_file\fP must contain either eight
integer-valued (\fIx\fP, \fIy\fP) coordinates, being the four source
coordinates followed by the corresponding four target coordinates, or only
four (\fIx\fP, \fIy\fP) coordinates, being only the four target
coordinates. In the latter case, the source quadrilateral is taken to be the
four corners of the input image in clockwise order, starting from the upper
left.
.sp
Anything you specify with \fB-to\fP or \fB-from\fP overrides what is in
this file.
.TP
\fB-view\fP=\fIcoords\fP
.sp
This defines the target view. \fIcoords\fP is a list of two integer-valued
(\fIx\fP, \fIy\fP) coordinates: the upper left and lower right boundaries,
respectively, of the pixels that will be visible in the output image. If
\fB-view\fP is not specified, the target view will fit precisely the target
quadrilateral.
.TP
\fB-fill\fP=\fIcolor\fP
.sp
This is the color with which the program fills all pixels that lie outside
of the target quadrilateral. Specify the color as described for the
.UR http://libnetpbm_image.html#colorname
argument of the pnm_parsecolor() library routine
.UE
\&.
.sp
The default is black, and for images with a transparency plane, transparent.
.TP
\fB-verbose\fP
This makes the program issue some informational messages about what it is
doing.
.PP
Cooordinates should normally be specified in clockwise order. The syntax is
fairly flexible: all characters other than the plus sign, minus sign, and
digits are treated as separators. Although coordinates need to be integers,
they may lie outside the image's boundary.
.UN PARAMETERS
.SH PARAMETERS
.PP
\fBpamhomography\fP's only parameter, \fIpam_file\fP, is the name of the
file containing the input image. If you don't specify \fIpam_file\fP, the
image comes from Standard Input.
.UN NOTES
.SH NOTES
.PP
The output image uses the same Netpbm format as the input image.
.PP
Simple transformations are best handled by other Netpbm programs, such as
those listed in the
.UR #SEE-ALSO
\&'SEE ALSO'
.UE
\& section
below. Use \fBpamhomography\fP for more sophisticated transformations such as
perspective adjustments, rotations around an arbitrary point in the image,
extraction of non-rectangular quadrilaterals, shearings by coordinates rather
than by angle, and, in general, all transformations that are most easily
expressed as mapping four points in one image to four points in another
image.
.UN EXAMPLES
.SH EXAMPLES
.PP
The following examples use the
.UR park_row.ppm
park_row.ppm
.UE
\& test image, which is a
.UR https://commons.wikimedia.org/wiki/File:15_Park_Row_3.JPG
photograph of New York City's Park Row Building
.UE
\&, scaled to
441×640, converted to a PPM file, and redistributed under the terms of
the
.UR https://en.wikipedia.org/wiki/GNU_Free_Documentation_License
GFDL
.UE
\&.
.PP
The first example showcases the real power of bilinear transformations.
Assuming \fIpark_row_rect.map\fP has the following contents:
.nf\f(CW (147, 51) (316, 105) (402, 595) (92, 560)
(0, 0) (440, 0) (440, 639) (0, 639)\fP
.fi
.PP
then
.nf\f(CW pamhomography -mapfile park_row_rect.map park_row.ppm > park_row_rect.ppm\fP
.fi
.PP
projects the building's facade from a perspective view to a rectilinear
front-on view. Remember that \fBpamhomography\fP ignores the parentheses and
commas used in \fIpark_row_rect.map\fP; they merely make the file more
human-readable. We equivalently could have written
.nf\f(CW 147 51 316 105 402 595 92 560 0 0 440 0 440 639 0 639\fP
.fi
.PP
or any of myriad other variations.
.PP
\fBpamhomography\fP can warp the image to a trapezoid to make it look like
it's leaning backwards in 3-D:
.nf\f(CW pamhomography -to '50,0 390,0 440,200 0,200' park_row.ppm > park_row_trap.ppm\fP
.fi
.PP
As a very simple example,
.nf\f(CW pamhomography -to '440,0 0,0 0,639 440,639' park_row.ppm > park_row_flip.ppm\fP
.fi
.PP
flips the image left-to-right. Note that in this case the target
quadrilateral's coordinates are listed in counterclockwise order because
that represents the correspondence between points (0, 0) ↔ (440, 0) and
(0, 639) ↔ (639, 0).
.PP
Scaling is also straightforward. The following command scales down the
image from 441×640 to 341×540:
.nf\f(CW pamhomography -to '0,0 340,0 340,539 0,539' park_row.ppm > park_row_small.ppm\fP
.fi
.PP
Let's add 100 pixels of tan border to the above. We use \fB-view\fP and
\fB-fill\fP to accomplish that task:
.nf\f(CW pamhomography -to '0,0 340,0 340,539 0,539' -view '-100,-100 440,639' -fill tan park_row.ppm > park_row_small_border.ppm\fP
.fi
.PP
We can add a border without having to scale the image:
.nf\f(CW pamhomography -view '-100,-100 540,739' -fill tan park_row.ppm > park_row_border.ppm\fP
.fi
.PP
The \fB-view\fP option can also be used to extract a rectangle out of an
image, discarding the rest of the image:
.nf\f(CW pamhomography -view '130,10 205,80' park_row.ppm > park_row_cut.ppm\fP
.fi
.PP
Specifying the same set of coordinates to \fB-from\fP and \fB-to\fP has
the same effect but also allows you to extract non-rectangular quadrilaterals
from an image:
.nf\f(CW pamhomography -from '185,300 310,325 320,425 180,405' -to '185,300 310,325 320,425 180,405' park_row.ppm > park_row_cut_2.ppm\fP
.fi
.PP
Rotation is doable but takes some effort. The challenge is that you need to
compute the rotated coordinates yourself. The matrix expression to rotate
points \e((x_1, y_1)\e) \e((x_2, y_2)\e), \e((x_3, y_3)\e), and \e((x_4, y_4)\e)
clockwise by \e(\etheta\e) degrees around point \e((c_x, c_y)\e) is
.PP
\e[ \ebegin{bmatrix} 1 & 0 & c_x \e\e 0 & 1 & c_y \e\e 0 & 0
& 1 \eend{bmatrix} \ebegin{bmatrix} \ecos \etheta & -\esin \etheta & 0
\e\e \esin \etheta & \ecos \etheta & 0 \e\e 0 & 0 & 1 \eend{bmatrix}
\ebegin{bmatrix} 1 & 0 & -c_x \e\e 0 & 1 & -c_y \e\e 0 & 0
& 1 \eend{bmatrix} \ebegin{bmatrix} x_1 & x_2 & x_3 & x_4 \e\e y_1
& y_2 & y_3 & y_4 \e\e 1 & 1 & 1 & 1 \eend{bmatrix}
\equad. \e]
.PP
For example, to rotate \fIpark_row.ppm\fP 30° clockwise around (220,
320) you would compute
.PP
\e[ \ebegin{bmatrix} 1 & 0 & 220 \e\e 0 & 1 & 320 \e\e 0 & 0
& 1 \eend{bmatrix} \ebegin{bmatrix} \ecos 30^{\ecirc} & -\esin 30^{\ecirc}
& 0 \e\e \esin 30^{\ecirc} & \ecos 30^{\ecirc} & 0 \e\e 0 & 0 & 1
\eend{bmatrix} \ebegin{bmatrix} 1 & 0 & -220 \e\e 0 & 1 & -320 \e\e
0 & 0 & 1 \eend{bmatrix} \ebegin{bmatrix} 0 & 440 & 440 & 0
\e\e 0 & 0 & 639 & 639 \e\e 1 & 1 & 1 & 1 \eend{bmatrix} =
\ebegin{bmatrix} 189.4744 & 570.5256 & 251.0256 & -130.0256 \e\e
-67.1281 & 152.8719 & 706.2621 & 486.2621 \e\e 1.0000 & 1.0000
& 1.0000 & 1.0000 \eend{bmatrix} \equad, \e]
.PP
round these coordinates to integers, transpose the matrix, and produce the
following map file, \fIpark_row_rot30.map\fP:
.nf\f(CW 189 -67
571 153
251 706
-130 486\fP
.fi
.PP
(These are the 'to' coordinates; we use the default, full-image
\&'from' coordinates.) The mapping then works as in all of the
preceding examples:
.nf\f(CW pamhomography -mapfile park_row_rot30.map park_row.ppm > park_row_rot30.ppm\fP
.fi
.UN SEE-ALSO
.SH SEE ALSO
.IP \(bu
.BR "pamcut" (1)\c
\&
.IP \(bu
.BR "pamenlarge" (1)\c
\&
.IP \(bu
.BR "pamflip" (1)\c
\&
.IP \(bu
.BR "pamperspective" (1)\c
\&
.IP \(bu
.BR "pamscale" (1)\c
\&
.IP \(bu
.BR "pamstretch" (1)\c
\&
.IP \(bu
.BR "pam" (1)\c
\&
.IP \(bu
.BR "pnmmargin" (1)\c
\&
.IP \(bu
.BR "pnmpad" (1)\c
\&
.IP \(bu
.BR "pnmrotate" (1)\c
\&
.IP \(bu
.BR "pnmshear" (1)\c
\&
.UN HISTORY
.SH HISTORY
.PP
\fBpamhomography\fP was new in Netpbm 10.94 (March 2021).
.UN AUTHOR
.SH AUTHOR
.PP
Copyright \(co 2020 Scott
Pakin, \fIscott+pbm@pakin.org\fP
.UN index
.SH Table of Contents
.IP \(bu
.UR #SYNOPSIS
SYNOPSIS
.UE
\&
.IP \(bu
.UR #DESCRIPTION
DESCRIPTION
.UE
\&
.IP \(bu
.UR #OPTIONS
OPTIONS
.UE
\&
.IP \(bu
.UR #PARAMETERS
PARAMETERS
.UE
\&
.IP \(bu
.UR #NOTES
NOTES
.UE
\&
.IP \(bu
.UR #EXAMPLES
EXAMPLES
.UE
\&
.IP \(bu
.UR #SEE-ALSO
SEE ALSO
.UE
\&
.IP \(bu
.UR #HISTORY
HISTORY
.UE
\&
.IP \(bu
.UR #AUTHOR
AUTHOR
.UE
\&
.SH DOCUMENT SOURCE
This manual page was generated by the Netpbm tool 'makeman' from HTML
source. The master documentation is at
.IP
.B http://netpbm.sourceforge.net/doc/pamhomography.html
.PP
|