summary refs log tree commit diff
path: root/pamscale.html
blob: 278d190390fd0275dff5f7979efa3c9a9ceb9aff (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
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
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.3//EN">
<html><head><title>Pamscale User Manual</title></head>
<body>
<h1>pamscale</h1>
Updated: 29 June 2020
<br>
<a href="#index">Table Of Contents</a>

<h2>NAME</h2>

pamscale - scale a Netpbm image

<h2 id="synopsis">SYNOPSIS</h2>

<pre>
   <b>pamscale</b>
      [ 
         <i>scale_factor</i> 
         |
         {<b>-xyfit</b> | <b>-xyfill</b> | <b>-xysize</b>}
           <i>cols</i> <i>rows</i> 
         |
         <b>-reduce</b> <i>reduction_factor</i> 
         |
         [<b>-xsize=</b><i>cols</i> | <b>-width=</b><i>cols</i> | <b>-xscale=</b><i>factor</i>]
         [<b>-ysize=</b><i>rows</i> | <b>-height=</b><i>rows</i> | <b>-yscale=</b><i>factor</i>]
         |
         <b>-pixels</b> <i>n</i>
      ]
      [
         <b>-nomix</b> 
         |
         <b>-filter=</b><i>functionName</i> [<b>-window=</b>functionName]
      ]
      [<b>-linear</b>]
      [<b>-reportonly</b>]
      [<b>-verbose</b>]

      [<i>pnmfile</i>]

</pre>

<p>Minimum unique abbreviation of option is acceptable.  You may use
double hyphens instead of single hyphen to denote options.  You may use
white space in place of the equals sign to separate an option name
from its value.

<h2 id="description">DESCRIPTION</h2>

<p>This program is part of <a href="index.html">Netpbm</a>.

<p><b>pamscale</b> scales a Netpbm image by a specified factor, or
scales individually horizontally and vertically by specified factors.

<p>You can either enlarge (scale factor &gt; 1) or reduce (scale factor
&lt; 1).

<p><b>pamscale</b> works on multi-image streams, scaling each one
independently.  But before Netpbm 10.49 (December 2009), it scales only the
first image and ignores the rest of the stream.

<h3 id="scalefactor">The Scale Factors</h3>

<p>The options <b>-width</b>, <b>-height</b>, <b>-xsize</b>, <b>-ysize</b>,
<b>-xscale</b>, <b>-yscale</b>, <b>-xyfit</b>, <b>-xyfill</b>, <b>-reduce</b>,
and <b>-pixels</b> control the amount of scaling.  For backward compatibility,
there are also <b>-xysize</b> and the <i>scale_factor</i> argument, but you
shouldn't use those.

<p><b>-width</b> and <b>-height</b> specify the width and height in pixels
you want the resulting image to be.  See below for rules when you specify
one and not the other.

<p><b>-xsize</b> and <b>-ysize</b> are synonyms for <b>-width</b> and
<b>-height</b>, respectively.

<p><b>-xscale</b> and <b>-yscale</b> tell the factor by which you want the
width and height of the image to change from source to result (e.g.
<b>-xscale 2</b> means you want to double the width; <b>-xscale .5</b>
means you want to halve it).  See below for rules when you specify one and
not the other.

<p>When you specify an absolute size or scale factor for both
dimensions, <b>pamscale</b> scales each dimension independently
without consideration of the aspect ratio.

<p>If you specify one dimension as a pixel size and don't specify the
other dimension, <b>pamscale</b> scales the unspecified dimension to
preserve the aspect ratio.

<p>If you specify one dimension as a scale factor and don't specify
the other dimension, <b>pamscale</b> leaves the unspecified dimension
unchanged from the input.

<p>If you specify the <i>scale_factor</i> parameter instead of
dimension options, that is the scale factor for both dimensions.  It
is equivalent to <b>-xscale=</b><i>scale_factor</i><b>
-yscale=</b><i>scale_factor</i>.

<p>Specifying the <b>-reduce</b> <i>reduction_factor</i> option is
equivalent to specifying the <i>scale_factor </i> parameter, where
<i>scale_factor</i> is the reciprocal of <i>reduction_factor</i>.

<p><b>-xyfit</b> specifies a bounding box.  <b>pamscale</b> scales
the input image to the largest size that fits within the box, while
preserving its aspect ratio.  <b>-xysize</b> is a synonym for this.
Before Netpbm 10.20 (January 2004), <b>-xyfit</b> did not exist, but
<b>-xysize</b> did.

<p><b>-xyfill</b> is similar, but <b>pamscale</b> scales the input image
to the smallest size that completely fills the box, while preserving
its aspect ratio.  This option has existed since Netpbm 10.20 (January
2004).

<p><b>-pixels</b> specifies a maximum total number of output pixels.
<b>pamscale</b> scales the image down to that number of pixels.  If
the input image is already no more than that many pixels,
<b>pamscale</b> just copies it as output; <b>pamscale</b> does not
scale up with <b>-pixels</b>.

<p>If you enlarge by a factor of 3 or more, you should probably add a
<i>pnmsmooth</i> step; otherwise, you can see the original pixels in
the resulting image.

<h4 id="reportonly"><b>-reportonly</b></h4>

<p>The option <b>-reportonly</b> causes <b>pamscale</b> not to scale the
image, but instead to report to Standard Output what scaling the options and
the input image dimensions indicate.  For example, if you specify
<pre>
<kbd>    -xyfill 100 100 -reportonly </kbd>
</pre>
and the input image is 500 x 400, <b>pamscale</b> tells you that this means
scaling by .25 to end up with a 125 x 100 image.

<p>You can use this information with other programs, such as
<b>pamscalefixed</b>, that don't have as rich facilities as <b>pamscale</b>
for choosing scale factors.

<p>The output is intended to be convenient for machine processing.  In the
example above, it would be

<pre>
<span style="font-family: monospace">
    500 400 0.250000 0.250000 125 100
</span>
</pre>

<p>The output is a single line of text per input image, with blank-separated
tokens as follows.

<ol>
<li>input width in pixels, decimal unsigned integer
<li>input height in pixels, decimal unsigned integer
<li>horizontal scale factor, floating point decimal, unsigned
<li>vertical scale factor, floating point decimal, unsigned
<li>output width in pixels, decimal unsigned integer
<li>output height in pixels, decimal unsigned integer
</ol>

<p><b>-reportonly</b> was new in Netpbm 10.86 (March 2019).


<h3 id="usage">Usage Notes</h3>

<p>A useful application of <b>pamscale</b> is to blur an image.  Scale
it down (without <b>-nomix</b>) to discard some information, then
scale it back up using <b>pamstretch</b>.

<p>Or scale it back up with <b>pamscale</b> and create a "pixelized" image,
which is sort of a computer-age version of blurring.


<h3 id="transparency">Transparency</h3>

<p><b>pamscale</b> understands transparency and properly mixes pixels
considering the pixels' transparency.  

<p>Proper mixing <em>does not</em> mean just mixing the transparency
value and the color component values separately.  In a PAM image, a
pixel which is not opaque represents a color that contains light of
the foreground color indicated explicitly in the PAM and light of a
background color to be named later.  But the numerical scale of a
color component sample in a PAM is as if the pixel is opaque.  So a
pixel that is supposed to contain half-strength red light for the
foreground plus some light from the background has a red color sample
that says <em>full</em> red and a transparency sample that says 50%
opaque.  In order to mix pixels, you have to first convert the color
sample values to numbers that represent amount of light directly
(i.e. multiply by the opaqueness) and after mixing, convert back
(divide by the opaqueness).

<h3 id="imagetype">Input And Output Image Types</h3>

<p><b>pamscale</b> produces output of the same type (and tuple type if
the type is PAM) as the input, except if the input is PBM.  In that
case, the output is PGM with maxval 255.  The purpose of this is to
allow meaningful pixel mixing.  Note that there is no equivalent
exception when the input is PAM.  If the PAM input tuple type is
BLACKANDWHITE, the PAM output tuple type is also BLACKANDWHITE, and
you get no meaningful pixel mixing.

<p>If you want PBM output with PBM input, use <b>pamditherbw</b> to
convert <b>pamscale</b>'s output to PBM.  Also consider
<b>pbmreduce</b>.

<p><b>pamscale</b>'s function is essentially undefined for PAM input
images that are not of tuple type RGB, GRAYSCALE, BLACKANDWHITE, or
the _ALPHA variations of those.  (By standard Netpbm backward compatibility,
this includes PBM, PGM, and PPM images).

<p>You might think it would have an obvious effect on other tuple
types, but remember that the aforementioned tuple types have
gamma-adjusted sample values, and <b>pamscale</b> uses that fact in
its calculations.  And it treats a transparency plane different from any
other plane.

<p><b>pamscale</b> does not simply reject unrecognized tuple types
because there's a possibility that just by coincidence you can get
useful function out of it with some other tuple type and the right
combination of options (consider <b>-linear</b> in particular).


<h3 id="methods">Methods Of Scaling</h3>

<p>There are numerous ways to scale an image.  <b>pamscale</b> implements
a bunch of them; you select among them with invocation options.

<h4 id="mixing">Pixel Mixing</h4>

<p>Pamscale's default method is pixel mixing.  To understand this, imagine the
source image as composed of square tiles.  Each tile is a pixel and has
uniform color.  The tiles are all the same size.  Now take a transparent sheet
the size of the target image, marked with a square grid of tiles the same
size.  Stretch or compress the source image to the size of the sheet and lay
the sheet over the source.

<p>Each cell in the overlay grid stands for a pixel of the target
image.  For example, if you are scaling a 100x200 image up by 1.5, the
source image is 100 x 200 tiles, and the transparent sheet is marked
off in 150 x 300 cells.

<p>Each cell covers parts of multiple tiles.  To make the target image,
just color in each cell with the color which is the average of the colors
the cell covers -- weighted by the amount of that color it covers.  A
cell in our example might cover 4/9 of a blue tile, 2/9 of a red tile,
2/9 of a green tile, and 1/9 of a white tile.  So the target pixel
would be somewhat unsaturated blue.

<p>When you are scaling up or down by an integer, the results are
simple.  When scaling up, pixels get duplicated.  When scaling down,
pixels get thrown away.  In either case, the colors in the target
image are a subset of those in the source image.

<p>When the scale factor is weirder than that, the target image can
have colors that didn't exist in the original.  For example, a red
pixel next to a white pixel in the source might become a red pixel,
a pink pixel, and a white pixel in the target.

<p>This method tends to replicate what the human eye does as it moves
closer to or further away from an image.  It also tends to replicate
what the human eye sees, when far enough away to make the pixelization
disappear, if an image is not made of pixels and simply stretches
or shrinks.

<h4 id="sampling">Discrete Sampling</h4>

<p>Discrete sampling is basically the same thing as pixel mixing except
that, in the model described above, instead of averaging the colors of
the tiles the cell covers, you pick the one color that covers the most
area.

<p>The result you see is that when you enlarge an image, pixels
get duplicated and when you reduce an image, some pixels get discarded.

<p>The advantage of this is that you end up with an image made from the
same color palette as the original.  Sometimes that's important.

<p>The disadvantage is that it distorts the picture.  If you scale up
by 1.5 horizontally, for example, the even numbered input pixels are
doubled in the output and the odd numbered ones are copied singly.  If
you have a bunch of one pixel wide lines in the source, you may find
that some of them stretch to 2 pixels, others remain 1 pixel when you
enlarge.  When you reduce, you may find that some of the lines
disappear completely.

<p>You select discrete sampling with <b>pamscale</b>'s <b>-nomix</b>
option.

<p>Actually, <b>-nomix</b> doesn't do exactly what I described above.
It does the scaling in two passes - first horizontal, then vertical.
This can produce slightly different results.

<p>There is one common case in which one often finds it burdensome to
have <b>pamscale</b> make up colors that weren't there originally:
Where one is working with an image format such as GIF that has a
limited number of possible colors per image.  If you take a GIF with
256 colors, convert it to PPM, scale by .625, and convert back to GIF,
you will probably find that the reduced image has way more than 256
colors, and therefore cannot be converted to GIF.  One way to solve
this problem is to do the reduction with discrete sampling instead of
pixel mixing.  Probably a better way is to do the pixel mixing, but
then color quantize the result with <b>pnmquant</b> before converting
to GIF.

<p>When the scale factor is an integer (which means you're scaling
up), discrete sampling and pixel mixing are identical -- output pixels
are always just N copies of the input pixels.  In this case, though,
consider using <b>pamstretch</b> instead of <b>pamscale</b> to get the
added pixels interpolated instead of just copied and thereby get a
smoother enlargement.

<p><b>pamscale</b>'s discrete sampling is faster than pixel mixing,
but <b>pamenlarge</b> is faster still.  <b>pamenlarge</b> works only
on integer enlargements.

<p>discrete sampling (<b>-nomix</b>) was new in Netpbm 9.24 (January 2002).


<h4 id="resampling">Resampling</h4>

<p>Resampling assumes that the source image is a discrete sampling of some
original continuous image.  That is, it assumes there is some non-pixelized
original image and each pixel of the source image is simply the color of
that image at a particular point.  Those points, naturally, are the
intersections of a square grid.

<p>The idea of resampling is just to compute that original image, then
sample it at a different frequency (a grid of a different scale).

<p>The problem, of course, is that sampling necessarily throws away the
information you need to rebuild the original image.  So we have to make
a bunch of assumptions about the makeup of the original image.

<p>You tell <b>pamscale</b> to use the resampling method by specifying
the <b>-filter</b> option.  The value of this option is the name of a
function, from the set listed below.

<p><strong>To explain resampling, we are going to talk about a simple
one dimensional scaling</strong> -- scaling a single row of grayscale
pixels horizontally.  If you can understand that, you can easily
understand how to do a whole image: Scale each of the rows of the
image, then scale each of the resulting columns.  And scale each of the
color component planes separately.

<p>As a first step in resampling, <b>pamscale</b> converts the source
image, which is a set of discrete pixel values, into a continuous step
function.  A step function is a function whose graph is a staircase-y
thing.

<p>Now, we convolve the step function with a proper scaling of the
filter function that you identified with <b>-filter</b>.  If you don't
know what the mathematical concept of convolution (convolving) is, you
are officially lost.  You cannot understand this explanation.  The
result of this convolution is the imaginary original continuous image
we've been talking about.

<p>Finally, we make target pixels by picking values from that function.

<p>To understand what is going on, we use Fourier analysis:

<p>The idea is that the only difference between our step function and
the original continuous function (remember that we constructed the
step function from the source image, which is itself a sampling of the
original continuous function) is that the step function has a bunch of
high frequency Fourier components added.  If we could chop out all the
higher frequency components of the step function, and know that
they're all higher than any frequency in the original function, we'd
have the original function back.  

<p>The resampling method <em>assumes</em> that the original function
was sampled at a high enough frequency to form a perfect sampling.  A
perfect sampling is one from which you can recover exactly the
original continuous function.  The Nyquist theorem says that as long
as your sample rate is at least twice the highest frequency in your
original function, the sampling is perfect.  So we <em>assume</em>
that the image is a sampling of something whose highest frequency is
half the sample rate (pixel resolution) or less.  Given that, our
filtering does in fact recover the original continuous image from the
samples (pixels).

<p>To chop out all the components above a certain frequency, we just
multiply the Fourier transform of the step function by a rectangle
function.

<p>We could find the Fourier transform of the step function, multiply
it by a rectangle function, and then Fourier transform the result
back, but there's an easier way.  Mathematicians tell us that
multiplying in the frequency domain is equivalent to convolving in the
time domain.  That means multiplying the Fourier transform of F by a
rectangle function R is the same as convolving F with the Fourier
transform of R.  It's a lot better to take the Fourier transform of
R, and build it into <b>pamscale</b> than to have <b>pamscale</b>
take the Fourier transform of the input image dynamically.

<p>That leaves only one question:  What <em>is</em> the Fourier
transform of a rectangle function?  Answer: sinc.  Recall from
math that sinc is defined as sinc(x) = sin(PI*x)/PI*x.

<p>Hence, when you specify <b>-filter=sinc</b>, you are effectively
passing the step function of the source image through a low pass
frequency filter and recovering a good approximation of the original
continuous image.

<h4>Refiltering</h4>

<p>There's another twist: If you simply sample the reconstructed
original continuous image at the new sample rate, and that new sample
rate isn't at least twice the highest frequency in the original
continuous image, you won't get a perfect sampling.  In fact, you'll
get something with ugly aliasing in it.  Note that this can't be a
problem when you're scaling up (increasing the sample rate), because
the fact that the old sample rate was above the Nyquist level means so
is the new one.  But when scaling down, it's a problem.  Obviously,
you have to give up image quality when scaling down, but aliasing is
not the best way to do it.  It's better just to remove high frequency
components from the original continuous image before sampling, and
then get a perfect sampling of that.

<p>Therefore, <b>pamscale</b> filters out frequencies above half the
new sample rate before picking the new samples.

<h4>Approximations</h4>

<p>Unfortunately, <b>pamscale</b> doesn't do the convolution
precisely.  Instead of evaluating the filter function at every point,
it samples it -- assumes that it doesn't change any more often than
the step function does.  <b>pamscale</b> could actually do the true
integration fairly easily.  Since the filter functions are built into
the program, the integrals of them could be too.  Maybe someday it
will.

<p>There is one more complication with the Fourier analysis.  sinc
has nonzero values on out to infinity and minus infinity.  That makes
it hard to compute a convolution with it.  So instead, there are
filter functions that approximate sinc but are nonzero only within a
manageable range.  To get those, you multiply the sinc function by a
<i>window function</i>, which you select with the <b>-window</b> option.  The
same holds for other filter functions that go on forever like sinc.  By
default, for a filter that needs a window function, the window function is the
Blackman function.  Hanning, Hamming, and Kaiser are alternatives.

<h4>Filter Functions Besides Sinc</h4>

<p>The math described above works only with sinc as the filter
function.  <b>pamscale</b> offers many other filter functions, though.
Some of these approximate sinc and are faster to compute.  For most of
them, I have no idea of the mathematical explanation for them, but
people do find they give pleasing results.  They may not be based on
resampling at all, but just exploit the convolution that is
coincidentally part of a resampling calculation.

<p>For some filter functions, you can tell just by looking at the
convolution how they vary the resampling process from the perfect one
based on sinc:

<p>The impulse filter assumes that the original continuous image is in
fact a step function -- the very one we computed as the first step in
the resampling.  This is mathematically equivalent to the discrete
sampling method.

<p>The box (rectangle) filter assumes the original image is a
piecewise linear function.  Its graph just looks like straight lines
connecting the pixel values.  This is mathematically equivalent to the
pixel mixing method (but mixing brightness, not light intensity, so
like <b>pamscale -linear</b>) when scaling down, and interpolation
(ala <b>pamstretch</b>) when scaling up.

<h4>Gamma</h4>

<p><b>pamscale</b> assumes the underlying continuous function is a
function of brightness (as opposed to light intensity), and therefore
does all this math using the gamma-adjusted numbers found in a PNM or
PAM image.  The <b>-linear</b> option is not available with resampling
(it causes <b>pamscale</b> to fail), because it wouldn't be useful enough
to justify the implementation effort.

<p>Resampling (<b>-filter</b>) was new in Netpbm 10.20 (January 2004).

<h4>The filter and window functions</h4>

<p>Here is a list of the function names you can specify for the
<b>-filter</b> or <b>-window</b>option.  For most of them, you're on your own
to figure out just what the function is and what kind of scaling it does.
These are common functions from mathematics.  Note that some of these make
sense only as filter functions and some make sense only as window funcions.

<dl>
<dt>point
<dd>The graph of this is a single point at X=0, Y=1.

<dt>box

<dd>The graph of this is a rectangle sitting on the X axis and centered
on the Y axis with height 1 and base 1.

<dt>triangle

<dd>The graph of this is an isosceles triangle sitting on the X axis
and centered on the Y axis with height 1 and base 2.

<dt>quadratic
<dt>cubic
<dt>catrom
<dt>mitchell
<dt>gauss
<dt>sinc
<dt>bessel
<dt>hanning
<dt>hamming
<dt>blackman
<dt>kaiser
<dt>normal
<dt>hermite
<dt>lanczos
<dd>Not documented</dd>
</dl>


<h3 id="linear">Linear vs Gamma-adjusted</h3>

<p>The pixel mixing scaling method described above involves intensities
of pixels (more precisely, it involves individual intensities of
primary color components of pixels).  But the PNM and PNM-equivalent
PAM image formats represent intensities with gamma-adjusted numbers
that are not linearly proportional to intensity.  So <b>pamscale</b>,
by default, performs a calculation on each sample read from its input
and each sample written to its output to convert between these
gamma-adjusted numbers and internal intensity-proportional numbers.

<p>Sometimes you are not working with true PNM or PAM images, but
rather a variation in which the sample values are in fact directly
proportional to intensity.  If so, use the <b>-linear</b> option to
tell <b>pamscale</b> this.  <b>pamscale</b> then will skip the
conversions.

<p>The conversion takes time.  In one experiment, it increased by a factor of
10 the time required to reduce an image.  And the difference between
intensity-proportional values and gamma-adjusted values may be small enough
that you would barely see a difference in the result if you just pretended
that the gamma-adjusted values were in fact intensity-proportional.  So just
to save time, at the expense of some image quality, you can specify
<b>-linear</b> even when you have true PPM input and expect true PPM output.

<p>For the first 13 years of Netpbm's life, until Netpbm 10.20
(January 2004), <b>pamscale</b>'s predecessor <b>pnmscale</b> always
treated the PPM samples as intensity-proportional even though they
were not, and drew few complaints.  So using <b>-linear</b> as a lie
is a reasonable thing to do if speed is important to you.  But if
speed is important, you also should consider the <b>-nomix</b> option
and <b>pnmscalefixed</b>.

<p>Another technique to consider is to convert your PNM image to the
linear variation with <b>pnmgamma</b>, run <b>pamscale</b> on it and
other transformations that like linear PNM, and then convert it back
to true PNM with <b>pnmgamma -ungamma</b>.  <b>pnmgamma</b> is often
faster than <b>pamscale</b> in doing the conversion.

<p>With <b>-nomix</b>, <b>-linear</b> has no effect.  That's because
<b>pamscale</b> does not concern itself with the meaning of the sample
values in this method; <b>pamscale</b> just copies numbers from its
input to its output.


<h3 id="precision">Precision</h3>

<p><b>pamscale</b> uses floating point arithmetic internally.  There
is a speed cost associated with this.  For some images, you can get
the acceptable results (in fact, sometimes identical results) faster
with <b>pnmscalefixed</b>, which uses fixed point arithmetic.
<b>pnmscalefixed</b> may, however, distort your image a little.  See
the <b>pnmscalefixed</b> user manual for a complete discussion of the
difference.

<h2 id="options">OPTIONS</h2>

<p>In addition to the options common to all programs based on libnetpbm
(most notably <b>-quiet</b>, see <a href="index.html#commonoptions">
Common Options</a>), <b>pamscale</b> recognizes the following
command line options:

<dl>

<dt><b>-width</b>
<dt><b>-height</b>
<dt><b>-xsize</b>
<dt><b>-ysize</b>
<dt><b>-xscale</b>
<dt><b>-yscale</b>
<dt><b>-xyfit</b>
<dt><b>-xyfill</b>
<dt><b>-reduce</b>
<dt><b>-pixels</b>
<dt><b>-xysize</b>
<dd>
  These options determine the horizontal and vertical scale factors.
  <p>
  See <a href="#scalefactor">The Scale Factors</a>.

<dt><b>-reportonly</b>
<dd>
  This causes <b>pamscale</b> not to scale the image, but instead to
  report to Standard Output what scaling the options and the input image
  dimensions indicate.
  <p>
  See <a href="#reportonly">-reportonly</a>.
  
<dt><b>-nomix</b>
<dd>
  This option selects <a href="#sampling">discrete sampling</a> as the
  <a href="#methods">method of scaling</a>.

<dt><b>-filter=</b><i>functionName</i>
<dd>
  This option selects <a href="#resampling">resampling</a> as the
  <a href="#methods">method of scaling</a>.

<dt><b>-window=</b><i>functionName</i>
<dd>
  This option selects a window function to modify the filter function
  specified with <b>-filter</b>.

  <p>See <a href="#resampling">Resampling</a>.

<dt><b>-verbose</b>
<dd>
  This option causes <b>pamscale</b> to issue messages to Standard Error about
  the scaling.
  
</dl>


<h2 id="seealso">SEE ALSO</h2>

<b><a href="pnmscalefixed.html">pnmscalefixed</a></b>,
<b><a href="pamstretch.html">pamstretch</a></b>,
<b><a href="pamstretch-gen.html">pamstretch-gen</a></b>,
<b><a href="pamditherbw.html">pamditherbw</a></b>,
<b><a href="pbmreduce.html">pbmreduce</a></b>,
<b><a href="pbmpscale.html">pbmpscale</a></b>,
<b><a href="pamenlarge.html">pamenlarge</a></b>,
<b><a href="pnmsmooth.html">pnmsmooth</a></b>,
<b><a href="pamcut.html">pamcut</a></b>,
<b><a href="pnmgamma.html">pnmgamma</a></b>,
<b><a href="pnmscale.html">pnmscale</a></b>,
<b><a href="pnm.html">pnm</a></b>,
<b><a href="pam.html">pam</a></b>

<h2 id="history">HISTORY</h2>

<p><b>pamscale</b> was new in Netpbm 10.20 (January 2004).  It was
adapted from, and obsoleted, <b>pnmscale</b>.  <b>pamscale</b>'s
primary difference from <b>pnmscale</b> is that it handles the PAM
format and uses the "pam" facilities of the Netpbm programming
library.  But it also added the resampling class of scaling method.
Furthermore, it properly does its pixel mixing arithmetic (by default)
using intensity-proportional values instead of the gamma-adjusted
values the <b>pnmscale</b> uses.  To get the old <b>pnmscale</b>
arithmetic, you can specify the <b>-linear</b> option.

<p>The intensity proportional stuff came out of suggestions by <a
href="mailto://amc+j5luho+@nicemice.net">Adam M Costello</a> in January
2004.

<p>The resampling algorithms are mostly taken from code contributed by
<a href="mailto://reinelt@eunet.at">Michael Reinelt</a> in December 2003.

<p>The version of <b>pnmscale</b> from which <b>pamscale</b> was
derived, itself evolved out of the original Pbmplus version of
<b>pnmscale</b> by Jef Poskanzer (1989, 1991).  But none of that
original code remains.

<hr>
<h2 id="index">Table Of Contents</h2>
<ul>
<li><a href="#synopsis">SYNOPSIS</a>
<li><a href="#description">DESCRIPTION</a>
  <ul>
  <li><a href="#scalefactor">The Scale Factors</a>
    <ul>
    <li><a href="#reportonly">-reportonly</a>
    </ul>
  <li><a href="#usage">Usage Notes</a>
  <li><a href="#transparency">Transparency</a>
  <li><a href="#imagetype">Input And Output Image Types</a>
  <li><a href="#methods">Methods Of Scaling</a>
    <ul>
    <li><a href="#mixing">Pixel Mixing</a>
    <li><a href="#sampling">Discrete Sampling</a>
    <li><a href="#resampling">Resampling</a>
    </ul>
  <li><a href="#linear">Linear vs Gamma-adjusted</a>
  <li><a href="#precision">Precision</a>
  </ul>
<li><a href="#options">OPTIONS</a>
<li><a href="#seealso">SEE ALSO</a>
<li><a href="#history">HISTORY</a>
</ul>

</body>
</html>