|
Packit |
78deda |
|
|
Packit |
78deda |
<HTML><HEAD><TITLE>Pamscale User Manual</TITLE></HEAD>
|
|
Packit |
78deda |
<BODY>
|
|
Packit |
78deda |
pamscale
|
|
Packit |
78deda |
Updated: 29 December 2009
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Table Of Contents
|
|
Packit |
78deda |
|
|
Packit |
78deda |
NAME
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale - scale a Netpbm image
|
|
Packit |
78deda |
|
|
Packit |
78deda |
SYNOPSIS
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale
|
|
Packit |
78deda |
[
|
|
Packit |
78deda |
scale_factor
|
|
Packit |
78deda |
|
|
|
Packit |
78deda |
{-xyfit | -xyfill | -xysize} cols rows
|
|
Packit |
78deda |
|
|
|
Packit |
78deda |
-reduce reduction_factor
|
|
Packit |
78deda |
|
|
|
Packit |
78deda |
[-xsize=cols | -width=cols | -xscale=factor]
|
|
Packit |
78deda |
[-ysize=rows | -height=rows | -yscale=factor]
|
|
Packit |
78deda |
|
|
|
Packit |
78deda |
-pixels n
|
|
Packit |
78deda |
]
|
|
Packit |
78deda |
[
|
|
Packit |
78deda |
[-verbose]
|
|
Packit |
78deda |
[
|
|
Packit |
78deda |
-nomix
|
|
Packit |
78deda |
|
|
|
Packit |
78deda |
-filter=functionName [-window=functionName]
|
|
Packit |
78deda |
]
|
|
Packit |
78deda |
[-linear]
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
[pnmfile]
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Minimum unique abbreviation of option is acceptable. You may use
|
|
Packit |
78deda |
double hyphens instead of single hyphen to denote options. You may use
|
|
Packit |
78deda |
white space in place of the equals sign to separate an option name
|
|
Packit |
78deda |
from its value.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
DESCRIPTION
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This program is part of Netpbm.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale scales a Netpbm image by a specified factor, or
|
|
Packit |
78deda |
scales individually horizontally and vertically by specified factors.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
You can either enlarge (scale factor > 1) or reduce (scale factor
|
|
Packit |
78deda |
< 1).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale work on multi-image streams, scaling each one independently.
|
|
Packit |
78deda |
But before Netpbm 10.49 (December 2009), it scales only the first image and
|
|
Packit |
78deda |
ignores the rest of the stream.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Scale Factors
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The options -width, -height, -xsize, -ysize,
|
|
Packit |
78deda |
-xscale, -yscale, -xyfit, -xyfill, -reduce,
|
|
Packit |
78deda |
and -pixels control the amount of scaling. For backward compatibility,
|
|
Packit |
78deda |
there is also -xysize and the scale_factor argument, but you
|
|
Packit |
78deda |
shouldn't use those.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-width and -height specify the width and height in pixels
|
|
Packit |
78deda |
you want the resulting image to be. See below for rules when you specify
|
|
Packit |
78deda |
one and not the other.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-xsize and -ysize are synonyms for -width and
|
|
Packit |
78deda |
-height, respectively.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-xscale and -yscale tell the factor by which you want the
|
|
Packit |
78deda |
width and height of the image to change from source to result (e.g.
|
|
Packit |
78deda |
-xscale 2 means you want to double the width; -xscale .5
|
|
Packit |
78deda |
means you want to halve it). See below for rules when you specify one and
|
|
Packit |
78deda |
not the other.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
When you specify an absolute size or scale factor for both
|
|
Packit |
78deda |
dimensions, pamscale scales each dimension independently
|
|
Packit |
78deda |
without consideration of the aspect ratio.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If you specify one dimension as a pixel size and don't specify the
|
|
Packit |
78deda |
other dimension, pamscale scales the unspecified dimension to
|
|
Packit |
78deda |
preserve the aspect ratio.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If you specify one dimension as a scale factor and don't specify
|
|
Packit |
78deda |
the other dimension, pamscale leaves the unspecified dimension
|
|
Packit |
78deda |
unchanged from the input.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If you specify the scale_factor parameter instead of
|
|
Packit |
78deda |
dimension options, that is the scale factor for both dimensions. It
|
|
Packit |
78deda |
is equivalent to -xscale=scale_factor
|
|
Packit |
78deda |
-yscale=scale_factor.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Specifying the -reduce reduction_factor option is
|
|
Packit |
78deda |
equivalent to specifying the scale_factor parameter, where
|
|
Packit |
78deda |
scale_factor is the reciprocal of reduction_factor.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-xyfit specifies a bounding box. pamscale scales
|
|
Packit |
78deda |
the input image to the largest size that fits within the box, while
|
|
Packit |
78deda |
preserving its aspect ratio. -xysize is a synonym for this.
|
|
Packit |
78deda |
Before Netpbm 10.20 (January 2004), -xyfit did not exist, but
|
|
Packit |
78deda |
-xysize did.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-xyfill is similar, but pamscale scales the input image
|
|
Packit |
78deda |
to the smallest size that completely fills the box, while preserving
|
|
Packit |
78deda |
its aspect ratio. This option has existed since Netpbm 10.20 (January
|
|
Packit |
78deda |
2004).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
-pixels specifies a maximum total number of output pixels.
|
|
Packit |
78deda |
pamscale scales the image down to that number of pixels. If
|
|
Packit |
78deda |
the input image is already no more than that many pixels,
|
|
Packit |
78deda |
pamscale just copies it as output; pamscale does not
|
|
Packit |
78deda |
scale up with -pixels.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If you enlarge by a factor of 3 or more, you should probably add a
|
|
Packit |
78deda |
pnmsmooth step; otherwise, you can see the original pixels in
|
|
Packit |
78deda |
the resulting image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Usage Notes
|
|
Packit |
78deda |
|
|
Packit |
78deda |
A useful application of pamscale is to blur an image. Scale
|
|
Packit |
78deda |
it down (without -nomix) to discard some information, then
|
|
Packit |
78deda |
scale it back up using pamstretch.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Or scale it back up with pamscale and create a
|
|
Packit |
78deda |
"pixelized" image, which is sort of a computer-age version
|
|
Packit |
78deda |
of blurring.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Transparency
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale understands transparency and properly mixes pixels
|
|
Packit |
78deda |
considering the pixels' transparency.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Proper mixing does not mean just mixing the transparency
|
|
Packit |
78deda |
value and the color component values separately. In a PAM image, a
|
|
Packit |
78deda |
pixel which is not opaque represents a color that contains light of
|
|
Packit |
78deda |
the foreground color indicated explicitly in the PAM and light of a
|
|
Packit |
78deda |
background color to be named later. But the numerical scale of a
|
|
Packit |
78deda |
color component sample in a PAM is as if the pixel is opaque. So a
|
|
Packit |
78deda |
pixel that is supposed to contain half-strength red light for the
|
|
Packit |
78deda |
foreground plus some light from the background has a red color sample
|
|
Packit |
78deda |
that says full red and a transparency sample that says 50%
|
|
Packit |
78deda |
opaque. In order to mix pixels, you have to first convert the color
|
|
Packit |
78deda |
sample values to numbers that represent amount of light directly
|
|
Packit |
78deda |
(i.e. multiply by the opaqueness) and after mixing, convert back
|
|
Packit |
78deda |
(divide by the opaqueness).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Input And Output Image Types
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale produces output of the same type (and tuple type if
|
|
Packit |
78deda |
the type is PAM) as the input, except if the input is PBM. In that
|
|
Packit |
78deda |
case, the output is PGM with maxval 255. The purpose of this is to
|
|
Packit |
78deda |
allow meaningful pixel mixing. Note that there is no equivalent
|
|
Packit |
78deda |
exception when the input is PAM. If the PAM input tuple type is
|
|
Packit |
78deda |
BLACKANDWHITE, the PAM output tuple type is also BLACKANDWHITE, and
|
|
Packit |
78deda |
you get no meaningful pixel mixing.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If you want PBM output with PBM input, use pamditherbw to
|
|
Packit |
78deda |
convert pamscale's output to PBM. Also consider
|
|
Packit |
78deda |
pbmreduce.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale's function is essentially undefined for PAM input
|
|
Packit |
78deda |
images that are not of tuple type RGB, GRAYSCALE, BLACKANDWHITE, or
|
|
Packit |
78deda |
the _ALPHA variations of those. (By standard Netpbm backward compatibility,
|
|
Packit |
78deda |
this includes PBM, PGM, and PPM images).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
You might think it would have an obvious effect on other tuple
|
|
Packit |
78deda |
types, but remember that the aforementioned tuple types have
|
|
Packit |
78deda |
gamma-adjusted sample values, and pamscale uses that fact in
|
|
Packit |
78deda |
its calculations. And it treats a transparency plane different from any
|
|
Packit |
78deda |
other plane.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale does not simply reject unrecognized tuple types
|
|
Packit |
78deda |
because there's a possibility that just by coincidence you can get
|
|
Packit |
78deda |
useful function out of it with some other tuple type and the right
|
|
Packit |
78deda |
combination of options (consider -linear in particular).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Methods Of Scaling
|
|
Packit |
78deda |
|
|
Packit |
78deda |
There are numerous ways to scale an image. pamscale implements
|
|
Packit |
78deda |
a bunch of them; you select among them with invocation options.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Pixel Mixing
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Pamscale's default method is pixel mixing. To understand this, imagine the
|
|
Packit |
78deda |
source image as composed of square tiles. Each tile is a pixel and has
|
|
Packit |
78deda |
uniform color. The tiles are all the same size. Now take a transparent sheet
|
|
Packit |
78deda |
the size of the target image, marked with a square grid of tiles the same
|
|
Packit |
78deda |
size. Stretch or compress the source image to the size of the sheet and lay
|
|
Packit |
78deda |
the sheet over the source.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Each cell in the overlay grid stands for a pixel of the target
|
|
Packit |
78deda |
image. For example, if you are scaling a 100x200 image up by 1.5, the
|
|
Packit |
78deda |
source image is 100 x 200 tiles, and the transparent sheet is marked
|
|
Packit |
78deda |
off in 150 x 300 cells.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Each cell covers parts of multiple tiles. To make the target image,
|
|
Packit |
78deda |
just color in each cell with the color which is the average of the colors
|
|
Packit |
78deda |
the cell covers -- weighted by the amount of that color it covers. A
|
|
Packit |
78deda |
cell in our example might cover 4/9 of a blue tile, 2/9 of a red tile,
|
|
Packit |
78deda |
2/9 of a green tile, and 1/9 of a white tile. So the target pixel
|
|
Packit |
78deda |
would be somewhat unsaturated blue.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
When you are scaling up or down by an integer, the results are
|
|
Packit |
78deda |
simple. When scaling up, pixels get duplicated. When scaling down,
|
|
Packit |
78deda |
pixels get thrown away. In either case, the colors in the target
|
|
Packit |
78deda |
image are a subset of those in the source image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
When the scale factor is weirder than that, the target image can
|
|
Packit |
78deda |
have colors that didn't exist in the original. For example, a red
|
|
Packit |
78deda |
pixel next to a white pixel in the source might become a red pixel,
|
|
Packit |
78deda |
a pink pixel, and a white pixel in the target.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This method tends to replicate what the human eye does as it moves
|
|
Packit |
78deda |
closer to or further away from an image. It also tends to replicate
|
|
Packit |
78deda |
what the human eye sees, when far enough away to make the pixelization
|
|
Packit |
78deda |
disappear, if an image is not made of pixels and simply stretches
|
|
Packit |
78deda |
or shrinks.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Discrete Sampling
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Discrete sampling is basically the same thing as pixel mixing except
|
|
Packit |
78deda |
that, in the model described above, instead of averaging the colors of
|
|
Packit |
78deda |
the tiles the cell covers, you pick the one color that covers the most
|
|
Packit |
78deda |
area.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The result you see is that when you enlarge an image, pixels
|
|
Packit |
78deda |
get duplicated and when you reduce an image, some pixels get discarded.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The advantage of this is that you end up with an image made from the
|
|
Packit |
78deda |
same color palette as the original. Sometimes that's important.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The disadvantage is that it distorts the picture. If you scale up
|
|
Packit |
78deda |
by 1.5 horizontally, for example, the even numbered input pixels are
|
|
Packit |
78deda |
doubled in the output and the odd numbered ones are copied singly. If
|
|
Packit |
78deda |
you have a bunch of one pixel wide lines in the source, you may find
|
|
Packit |
78deda |
that some of them stretch to 2 pixels, others remain 1 pixel when you
|
|
Packit |
78deda |
enlarge. When you reduce, you may find that some of the lines
|
|
Packit |
78deda |
disappear completely.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
You select discrete sampling with pamscale's -nomix
|
|
Packit |
78deda |
option.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Actually, -nomix doesn't do exactly what I described above.
|
|
Packit |
78deda |
It does the scaling in two passes - first horizontal, then vertical.
|
|
Packit |
78deda |
This can produce slightly different results.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
There is one common case in which one often finds it burdensome to
|
|
Packit |
78deda |
have pamscale make up colors that weren't there originally:
|
|
Packit |
78deda |
Where one is working with an image format such as GIF that has a
|
|
Packit |
78deda |
limited number of possible colors per image. If you take a GIF with
|
|
Packit |
78deda |
256 colors, convert it to PPM, scale by .625, and convert back to GIF,
|
|
Packit |
78deda |
you will probably find that the reduced image has way more than 256
|
|
Packit |
78deda |
colors, and therefore cannot be converted to GIF. One way to solve
|
|
Packit |
78deda |
this problem is to do the reduction with discrete sampling instead of
|
|
Packit |
78deda |
pixel mixing. Probably a better way is to do the pixel mixing, but
|
|
Packit |
78deda |
then color quantize the result with pnmquant before converting
|
|
Packit |
78deda |
to GIF.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
When the scale factor is an integer (which means you're scaling
|
|
Packit |
78deda |
up), discrete sampling and pixel mixing are identical -- output pixels
|
|
Packit |
78deda |
are always just N copies of the input pixels. In this case, though,
|
|
Packit |
78deda |
consider using pamstretch instead of pamscale to get the
|
|
Packit |
78deda |
added pixels interpolated instead of just copied and thereby get a
|
|
Packit |
78deda |
smoother enlargement.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale's discrete sampling is faster than pixel mixing,
|
|
Packit |
78deda |
but pamenlarge is faster still. pamenlarge works only
|
|
Packit |
78deda |
on integer enlargements.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
discrete sampling (-nomix) was new in Netpbm 9.24 (January
|
|
Packit |
78deda |
2002).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Resampling
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Resampling assumes that the source image is a discrete sampling of some
|
|
Packit |
78deda |
original continuous image. That is, it assumes there is some non-pixelized
|
|
Packit |
78deda |
original image and each pixel of the source image is simply the color of
|
|
Packit |
78deda |
that image at a particular point. Those points, naturally, are the
|
|
Packit |
78deda |
intersections of a square grid.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The idea of resampling is just to compute that original image, then
|
|
Packit |
78deda |
sample it at a different frequency (a grid of a different scale).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The problem, of course, is that sampling necessarily throws away the
|
|
Packit |
78deda |
information you need to rebuild the original image. So we have to make
|
|
Packit |
78deda |
a bunch of assumptions about the makeup of the original image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
You tell pamscale to use the resampling method by specifying
|
|
Packit |
78deda |
the -filter option. The value of this option is the name of a
|
|
Packit |
78deda |
function, from the set listed below.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
To explain resampling, we are going to talk about a simple
|
|
Packit |
78deda |
one dimensional scaling -- scaling a single row of grayscale
|
|
Packit |
78deda |
pixels horizontally. If you can understand that, you can easily
|
|
Packit |
78deda |
understand how to do a whole image: Scale each of the rows of the
|
|
Packit |
78deda |
image, then scale each of the resulting columns. And scale each of the
|
|
Packit |
78deda |
color component planes separately.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
As a first step in resampling, pamscale converts the source
|
|
Packit |
78deda |
image, which is a set of discrete pixel values, into a continuous step
|
|
Packit |
78deda |
function. A step function is a function whose graph is a staircase-y
|
|
Packit |
78deda |
thing.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Now, we convolve the step function with a proper scaling of the
|
|
Packit |
78deda |
filter function that you identified with -filter. If you don't
|
|
Packit |
78deda |
know what the mathematical concept of convolution (convolving) is, you
|
|
Packit |
78deda |
are officially lost. You cannot understand this explanation. The
|
|
Packit |
78deda |
result of this convolution is the imaginary original continuous image
|
|
Packit |
78deda |
we've been talking about.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Finally, we make target pixels by picking values from that function.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
To understand what is going on, we use Fourier analysis:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The idea is that the only difference between our step function and
|
|
Packit |
78deda |
the original continuous function (remember that we constructed the
|
|
Packit |
78deda |
step function from the source image, which is itself a sampling of the
|
|
Packit |
78deda |
original continuous function) is that the step function has a bunch of
|
|
Packit |
78deda |
high frequency Fourier components added. If we could chop out all the
|
|
Packit |
78deda |
higher frequency components of the step function, and know that
|
|
Packit |
78deda |
they're all higher than any frequency in the original function, we'd
|
|
Packit |
78deda |
have the original function back.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The resampling method assumes that the original function
|
|
Packit |
78deda |
was sampled at a high enough frequency to form a perfect sampling. A
|
|
Packit |
78deda |
perfect sampling is one from which you can recover exactly the
|
|
Packit |
78deda |
original continuous function. The Nyquist theorem says that as long
|
|
Packit |
78deda |
as your sample rate is at least twice the highest frequency in your
|
|
Packit |
78deda |
original function, the sampling is perfect. So we assume
|
|
Packit |
78deda |
that the image is a sampling of something whose highest frequency is
|
|
Packit |
78deda |
half the sample rate (pixel resolution) or less. Given that, our
|
|
Packit |
78deda |
filtering does in fact recover the original continuous image from the
|
|
Packit |
78deda |
samples (pixels).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
To chop out all the components above a certain frequency, we just
|
|
Packit |
78deda |
multiply the Fourier transform of the step function by a rectangle
|
|
Packit |
78deda |
function.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
We could find the Fourier transform of the step function, multiply
|
|
Packit |
78deda |
it by a rectangle function, and then Fourier transform the result
|
|
Packit |
78deda |
back, but there's an easier way. Mathematicians tell us that
|
|
Packit |
78deda |
multiplying in the frequency domain is equivalent to convolving in the
|
|
Packit |
78deda |
time domain. That means multiplying the Fourier transform of F by a
|
|
Packit |
78deda |
rectangle function R is the same as convolving F with the Fourier
|
|
Packit |
78deda |
transform of R. It's a lot better to take the Fourier transform of
|
|
Packit |
78deda |
R, and build it into pamscale than to have pamscale
|
|
Packit |
78deda |
take the Fourier transform of the input image dynamically.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
That leaves only one question: What is the Fourier
|
|
Packit |
78deda |
transform of a rectangle function? Answer: sinc. Recall from
|
|
Packit |
78deda |
math that sinc is defined as sinc(x) = sin(PI*x)/PI*x.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Hence, when you specify -filter=sinc, you are effectively
|
|
Packit |
78deda |
passing the step function of the source image through a low pass
|
|
Packit |
78deda |
frequency filter and recovering a good approximation of the original
|
|
Packit |
78deda |
continuous image.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Refiltering
|
|
Packit |
78deda |
|
|
Packit |
78deda |
There's another twist: If you simply sample the reconstructed
|
|
Packit |
78deda |
original continuous image at the new sample rate, and that new sample
|
|
Packit |
78deda |
rate isn't at least twice the highest frequency in the original
|
|
Packit |
78deda |
continuous image, you won't get a perfect sampling. In fact, you'll
|
|
Packit |
78deda |
get something with ugly aliasing in it. Note that this can't be a
|
|
Packit |
78deda |
problem when you're scaling up (increasing the sample rate), because
|
|
Packit |
78deda |
the fact that the old sample rate was above the Nyquist level means so
|
|
Packit |
78deda |
is the new one. But when scaling down, it's a problem. Obviously,
|
|
Packit |
78deda |
you have to give up image quality when scaling down, but aliasing is
|
|
Packit |
78deda |
not the best way to do it. It's better just to remove high frequency
|
|
Packit |
78deda |
components from the original continuous image before sampling, and
|
|
Packit |
78deda |
then get a perfect sampling of that.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Therefore, pamscale filters out frequencies above half the
|
|
Packit |
78deda |
new sample rate before picking the new samples.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Approximations
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Unfortunately, pamscale doesn't do the convolution
|
|
Packit |
78deda |
precisely. Instead of evaluating the filter function at every point,
|
|
Packit |
78deda |
it samples it -- assumes that it doesn't change any more often than
|
|
Packit |
78deda |
the step function does. pamscale could actually do the true
|
|
Packit |
78deda |
integration fairly easily. Since the filter functions are built into
|
|
Packit |
78deda |
the program, the integrals of them could be too. Maybe someday it
|
|
Packit |
78deda |
will.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
There is one more complication with the Fourier analysis. sinc
|
|
Packit |
78deda |
has nonzero values on out to infinity and minus infinity. That makes
|
|
Packit |
78deda |
it hard to compute a convolution with it. So instead, there are
|
|
Packit |
78deda |
filter functions that approximate sinc but are nonzero only within a
|
|
Packit |
78deda |
manageable range. To get those, you multiply the sinc function by a
|
|
Packit |
78deda |
window function, which you select with the -window
|
|
Packit |
78deda |
option. The same holds for other filter functions that go on forever
|
|
Packit |
78deda |
like sinc. By default, for a filter that needs a window function,
|
|
Packit |
78deda |
the window function is the Blackman function.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Filter Functions Besides Sinc
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The math described above works only with sinc as the filter
|
|
Packit |
78deda |
function. pamscale offers many other filter functions, though.
|
|
Packit |
78deda |
Some of these approximate sinc and are faster to compute. For most of
|
|
Packit |
78deda |
them, I have no idea of the mathematical explanation for them, but
|
|
Packit |
78deda |
people do find they give pleasing results. They may not be based on
|
|
Packit |
78deda |
resampling at all, but just exploit the convolution that is
|
|
Packit |
78deda |
coincidentally part of a resampling calculation.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
For some filter functions, you can tell just by looking at the
|
|
Packit |
78deda |
convolution how they vary the resampling process from the perfect one
|
|
Packit |
78deda |
based on sinc:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The impulse filter assumes that the original continuous image is in
|
|
Packit |
78deda |
fact a step function -- the very one we computed as the first step in
|
|
Packit |
78deda |
the resampling. This is mathematically equivalent to the discrete
|
|
Packit |
78deda |
sampling method.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The box (rectangle) filter assumes the original image is a
|
|
Packit |
78deda |
piecewise linear function. Its graph just looks like straight lines
|
|
Packit |
78deda |
connecting the pixel values. This is mathematically equivalent to the
|
|
Packit |
78deda |
pixel mixing method (but mixing brightness, not light intensity, so
|
|
Packit |
78deda |
like pamscale -linear) when scaling down, and interpolation
|
|
Packit |
78deda |
(ala pamstretch) when scaling up.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Gamma
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale assumes the underlying continuous function is a
|
|
Packit |
78deda |
function of brightness (as opposed to light intensity), and therefore
|
|
Packit |
78deda |
does all this math using the gamma-adjusted numbers found in a PNM or
|
|
Packit |
78deda |
PAM image. The -linear option is not available with resampling
|
|
Packit |
78deda |
(it causes pamscale to fail), because it wouldn't be useful enough
|
|
Packit |
78deda |
to justify the implementation effort.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Resampling (-filter) was new in Netpbm 10.20 (January 2004).
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The filter functions
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Here is a list of the function names you can specify for the
|
|
Packit |
78deda |
-filter option. For most of them, you're on your own to figure
|
|
Packit |
78deda |
out just what the function is and what kind of scaling it does. These
|
|
Packit |
78deda |
are common functions from mathematics.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
point
|
|
Packit |
78deda |
The graph of this is a single point at X=0, Y=1.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
box
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The graph of this is a rectangle sitting on the X axis and centered
|
|
Packit |
78deda |
on the Y axis with height 1 and base 1.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
triangle
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The graph of this is an isosceles triangle sitting on the X axis
|
|
Packit |
78deda |
and centered on the Y axis with height 1 and base 2.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
quadratic
|
|
Packit |
78deda |
cubic
|
|
Packit |
78deda |
catrom
|
|
Packit |
78deda |
mitchell
|
|
Packit |
78deda |
gauss
|
|
Packit |
78deda |
sinc
|
|
Packit |
78deda |
bessel
|
|
Packit |
78deda |
hanning
|
|
Packit |
78deda |
hamming
|
|
Packit |
78deda |
blackman
|
|
Packit |
78deda |
kaiser
|
|
Packit |
78deda |
normal
|
|
Packit |
78deda |
hermite
|
|
Packit |
78deda |
lanczos
|
|
Packit |
78deda |
Not documented
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Linear vs Gamma-adjusted
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The pixel mixing scaling method described above involves intensities
|
|
Packit |
78deda |
of pixels (more precisely, it involves individual intensities of
|
|
Packit |
78deda |
primary color components of pixels). But the PNM and PNM-equivalent
|
|
Packit |
78deda |
PAM image formats represent intensities with gamma-adjusted numbers
|
|
Packit |
78deda |
that are not linearly proportional to intensity. So pamscale,
|
|
Packit |
78deda |
by default, performs a calculation on each sample read from its input
|
|
Packit |
78deda |
and each sample written to its output to convert between these
|
|
Packit |
78deda |
gamma-adjusted numbers and internal intensity-proportional numbers.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Sometimes you are not working with true PNM or PAM images, but
|
|
Packit |
78deda |
rather a variation in which the sample values are in fact directly
|
|
Packit |
78deda |
proportional to intensity. If so, use the -linear option to
|
|
Packit |
78deda |
tell pamscale this. pamscale then will skip the
|
|
Packit |
78deda |
conversions.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The conversion takes time. In one experiment, it increased by a factor of
|
|
Packit |
78deda |
10 the time required to reduce an image. And the difference between
|
|
Packit |
78deda |
intensity-proportional values and gamma-adjusted values may be small enough
|
|
Packit |
78deda |
that you would barely see a difference in the result if you just pretended
|
|
Packit |
78deda |
that the gamma-adjusted values were in fact intensity-proportional. So just
|
|
Packit |
78deda |
to save time, at the expense of some image quality, you can specify
|
|
Packit |
78deda |
-linear even when you have true PPM input and expect true PPM output.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
For the first 13 years of Netpbm's life, until Netpbm 10.20
|
|
Packit |
78deda |
(January 2004), pamscale's predecessor pnmscale always
|
|
Packit |
78deda |
treated the PPM samples as intensity-proportional even though they
|
|
Packit |
78deda |
were not, and drew few complaints. So using -linear as a lie
|
|
Packit |
78deda |
is a reasonable thing to do if speed is important to you. But if
|
|
Packit |
78deda |
speed is important, you also should consider the -nomix option
|
|
Packit |
78deda |
and pnmscalefixed.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Another technique to consider is to convert your PNM image to the
|
|
Packit |
78deda |
linear variation with pnmgamma, run pamscale on it and
|
|
Packit |
78deda |
other transformations that like linear PNM, and then convert it back
|
|
Packit |
78deda |
to true PNM with pnmgamma -ungamma. pnmgamma is often
|
|
Packit |
78deda |
faster than pamscale in doing the conversion.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
With -nomix, -linear has no effect. That's because
|
|
Packit |
78deda |
pamscale does not concern itself with the meaning of the sample
|
|
Packit |
78deda |
values in this method; pamscale just copies numbers from its
|
|
Packit |
78deda |
input to its output.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Precision
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale uses floating point arithmetic internally. There
|
|
Packit |
78deda |
is a speed cost associated with this. For some images, you can get
|
|
Packit |
78deda |
the acceptable results (in fact, sometimes identical results) faster
|
|
Packit |
78deda |
with pnmscalefixed, which uses fixed point arithmetic.
|
|
Packit |
78deda |
pnmscalefixed may, however, distort your image a little. See
|
|
Packit |
78deda |
the pnmscalefixed user manual for a complete discussion of the
|
|
Packit |
78deda |
difference.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
SEE ALSO
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnmscalefixed,
|
|
Packit |
78deda |
pamstretch,
|
|
Packit |
78deda |
pamditherbw,
|
|
Packit |
78deda |
pbmreduce,
|
|
Packit |
78deda |
pbmpscale,
|
|
Packit |
78deda |
pamenlarge,
|
|
Packit |
78deda |
pnmsmooth,
|
|
Packit |
78deda |
pamcut,
|
|
Packit |
78deda |
pnmgamma,
|
|
Packit |
78deda |
pnmscale,
|
|
Packit |
78deda |
pnm,
|
|
Packit |
78deda |
pam
|
|
Packit |
78deda |
|
|
Packit |
78deda |
HISTORY
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pamscale was new in Netpbm 10.20 (January 2004). It was
|
|
Packit |
78deda |
adapted from, and obsoleted, pnmscale. pamscale's
|
|
Packit |
78deda |
primary difference from pnmscale is that it handles the PAM
|
|
Packit |
78deda |
format and uses the "pam" facilities of the Netpbm programming
|
|
Packit |
78deda |
library. But it also added the resampling class of scaling method.
|
|
Packit |
78deda |
Furthermore, it properly does its pixel mixing arithmetic (by default)
|
|
Packit |
78deda |
using intensity-proportional values instead of the gamma-adjusted
|
|
Packit |
78deda |
values the pnmscale uses. To get the old pnmscale
|
|
Packit |
78deda |
arithmetic, you can specify the -linear option.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The intensity proportional stuff came out of suggestions by
|
|
Packit |
78deda |
href="mailto://amc+j5luho+@nicemice.net">Adam M Costello in January
|
|
Packit |
78deda |
2004.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The resampling algorithms are mostly taken from code contributed by
|
|
Packit |
78deda |
Michael Reinelt in December 2003.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The version of pnmscale from which pamscale was
|
|
Packit |
78deda |
derived, itself evolved out of the original Pbmplus version of
|
|
Packit |
78deda |
pnmscale by Jef Poskanzer (1989, 1991). But none of that
|
|
Packit |
78deda |
original code remains.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Table Of Contents
|
|
Packit |
78deda |
|
|
Packit |
78deda |
SYNOPSIS
|
|
Packit |
78deda |
DESCRIPTION
|
|
Packit |
78deda |
|
|
Packit |
78deda |
The Scale Factors
|
|
Packit |
78deda |
Usage Notes
|
|
Packit |
78deda |
Transparency
|
|
Packit |
78deda |
Input And Output Image Types
|
|
Packit |
78deda |
Methods Of Scaling
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Pixel Mixing
|
|
Packit |
78deda |
Discrete Sampling
|
|
Packit |
78deda |
Resampling
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Linear vs Gamma-adjusted
|
|
Packit |
78deda |
Precision
|
|
Packit |
78deda |
|
|
Packit |
78deda |
SEE ALSO
|
|
Packit |
78deda |
HISTORY
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
</BODY>
|
|
Packit |
78deda |
</HTML>
|