Example: Rescale a Raster Image

This topic shows how to rescale pixel values from one raster image, using a given range of values such as 8-bit unsigned integers, into a new raster image using a different range of values such as 16-bit unsigned integers, so that the relative distribution of pixel values, that is, the histogram, does not change.   

 

We call the 8-bit raster we start with the original raster.   We call the new 16-bit raster that is created the rescaled raster.  

 

The arithmetic for computing the rescaling from original raster values to rescaled raster values is simple, and is based on the minimum and maximum values in the original raster image as on the minimum and maximum values in the rescaled raster image.  

 

<mini original raster value> - the lowest value that can appear in the original raster.  For an 8-bit unsigned raster the minimum value is 0.

 

<max original raster value> - the highest value that can appear in the original raster.  For an 8-bit unsigned raster the maximum value is 255.

 

<min rescaled raster value> - the lowest value that can appear in the rescaled raster.  For a 16-bit unsigned raster the minimum value is 0.

 

<max rescaled raster value> - the highest value that can appear in the rescaled raster.  For a 16-bit unsigned raster the maximum value is 65535.

 

Let

 

ratio = (<max rescaled raster value> - <min rescaled raster value>)

            / (<max original raster value> - <min original raster value>)

 

 

Using the above nomenclature the equation for values in the rescaled raster is simple:

 

rescaled raster value = (<original raster> - <min original raster value>) * ratio

                           + <min rescaled raster value>

 

Example: Rescale from uint8 to uint16

We start with raster data that uses 8-bit unsigned integers, allowing values from 0 to 255, and we rescale the values in that data set into 16-bit unsigned integers, which allow a range from 0 to 65535.   

 

For our example raster, we will use an unsigned 8-bit, grayscale image of the portrait of Ginevra de' Benci, by Leonardo da Vinci.  See the Example: Change the Contrast of an Image topic for notes on the portrait and on Leonardo.

 

 

With the focus on the ginevra8 image window, we take a look at the Info pane and at the Style pane.

 

 

The Info pane tells us the image uses uint8 data type, that is, unsigned 8-bit integers for the value of pixels.   The Info pane also tells us this image uses Pseudo-Mercator projection, which is a default frequently used for raster and vector data that is not spatial.

 

The Style pane shows default ranges for unsigned 8-bit images of 0 to 255.

 

With the focus on the ginevra8 image window, in the Transform pane we choose the Tile field, and then we double-click the Expression template to launch it.

 

 

In the Expression template, we click the Edit Expression button to launch the Expression dialog, which allows us to enter expressions.

 

 

We enter the following expression, which is the formula introduced at the beginning of this topic:

 

(([Tile] - 0) * (65535 - 0) / (255 - 0))

   + 0

 

Press OK.

 

Back in the Expression template, we chose New Table for the Result destination.

 

 

In the pull down menu for Channel type, we choose uint16, for unsigned 16-bit integers.     We enter a name for the new image in the New image box, and an analogous name for the new image's table.

 

The default table name created automatically as we enter a name for the New image ends in ...Table.  This topic uses a table name that ends in ...Tiles, which is how some users prefer to name tables for images.  Others prefer to have all of their tables, both for drawings and images, end in ...Table.  We can adjust the name automatically created for the table however we like.

 

We can use whatever names we like, but it makes sense to specify names that remind us of what the new image is supposed to be.

 

Press Transform.

 

A new image and its table called ginevra16 appear in the Project pane.

 

 

Popping open the new image, we see that by default it is displayed with slightly higher contrast than the original image.    

 

With the focus on the ginevra16 window, we take a look at the Info pane and the Style pane.

 

 

The Info pane tells us the image uses uint16 data type, that is, unsigned 16-bit integers for the value of pixels.   The Style pane with 16-bit data shows the actual, full range of data in the image, in this case, pixel values ranging from 3628 to 57262.   That is different than the 8-bit default settings, because 16-bit data often uses only a small range of the possible 0 to 65535 range, so using the full range by default tends to produce less legible images in many cases.

 

We can easily tell the Style pane to use the full range.

 

 

We Ctrl-click each of the R, G and B channel rows and then change the range to 0 to 65535.    Press Update Style.

 

 

Immediately, the contrast in the image changes so it looks exactly like the original ginevra8 image.

Example: Rescale from uint8, 0 to 255 to uint8, 100 to 200

In the example above, we rescaled pixel data from the small range allowed by unsigned 8-bit integers into the much larger range allowed by unsigned 16-bit integers.   If we like, we could go the other way, from 16-bit ranges to 8-bit ranges, or we could rescale data within the unsigned 8-bit range, from the 0 to 255 range into a 100 to 200 range.  

 

We start with raster data that uses 8-bit unsigned integers, allowing values from 0 to 255, and we rescale the values in that data set into 8-bit unsigned integers, but using a range from 100 to 200.

 

For our example raster, we will use the same, unsigned 8-bit, grayscale image used in the prior example.

 

 

As before, with the focus on the ginevra8 window, in the Transform pane we launch the Expression template, and then we click the Edit Expression button.

 

 

We enter the following expression, plugging the minimum, 100,  and maximum, 200, values for a rescaled raster range of 100 to 200 into the formula in the beginning of this topic.

 

(([Tile] - 0) * (200 - 100) / (255 - 0))

   + 100

 

Press OK.

 

 

We choose New Table as the Result destination, and uint8 as the Channel type.   We enter ginevra100_200 as the name for the new image and an analogous name for the new image's table.

 

Press Transform.

 

A new ginevra100_200 image and table appear in the Project pane.   We pop open the new ginevra100_200 image.

 

 

It appears with low contrast.    We take a look at the Info pane and the Style pane to see  why.

 

 

The info pane confirms that the image uses unsigned, 8-bit integers as the data type for pixels.    The Style pane shows that the display uses default 8-bit ranges of 0 to 255.

 

Spreading pixel values of 100 to 200 over a display range of 0 to 255 will reduce contrast.    If we would like contrast like the original image, we can adjust the range values in the Style rows to use 100 to 200.

 

 

We Ctrl-click each of the R, G and B channel rows and then change the range to 100 to 200.    Press Update Style.

 

 

Immediately, the contrast in the image changes so it looks exactly like the original ginevra8 image.

Comparison to Changing Range Values

Manifold allows us in the Style dialog to dynamically set range values over which the pixel values in the image will be interpreted for driving R, G, and B display outputs.   That is why altering the range values in the R, G and B channel rows in the Style pane changes contrast.  

 

However, changing range values in the Style dialog does not change pixel values in the image.  Alterations in the Style dialog only change how pixel values in the image are used..  Rescaling pixel values as done in the examples above does change pixel values in the image.   If we attempt to duplicate the effect of rescaling pixel values from 0 to 255 into a 100 to 200 range by changing R, G and B channel row ranges, the effect will be different.

 

 

Suppose we start with the unsigned, 8-bit grayscale image used in prior examples.

 

 

The Style dialog shows the default ranges for unsigned, 8-bit data, from 0 to 255.   Whatever are the actual values in the image (in this case, they range from 0 to 253), they will be stretched over a range of 0 to 255 for display purposes.

 

To use a smaller range for display, we Ctrl-click each of the R, G and B channel rows and then change the range to 100 to 200.    Press Update Style.

 

 

The result is a higher contrast image.   However, the data in the image has not changed.  It is the same data with the same values for each pixel, but simply being interpreted differently for display purposes.   If we change the Style dialog ranges back to 0 to 255 the image will look the same as it did originally.

 

The effect of changing R, G and B channel rows values to 100 to 200, while leaving the data itself unchanged in the 0 to 255 range, changes how pixel values from 0 to 255 are interpreted for display into a smaller range, so a higher contrast results.    However, when we rescale the data itself so that pixel values fall into the 100 to 200 range, then when we show those pixel values over a wider range, from 0 to 255, the result is lower contrast.   Displaying those pixel values over the same 100 to 200 range used for the data results in the same contrast effect as the original, where data that was in the range from 0 to 255 was displayed using a display range that also was from 0 to 255.

 

See the Style: Autocontrast topic for more on ranges and contrast.

 

See Also

Images

 

Style: Autocontrast

 

Example: Change the Pixel Size of a Terrain Elevation Image - Use the Reproject Component dialog to change the pixel size of a terrain elevation image, reducing the total number of pixels used.  This process is also called resampling.

 

Example: Merge Images - A step-by-step example using the Merge Images command showing how to merge dozens of images showing SRTM terrain elevation data into one image, with various tricks for faster workflow as an experienced Manifold user would do the job.  After creating the new image we style it with a palette and use hill shading to better show terrain elevation.

 

SQL Example: Re-tile an Image using a Different Tile Size - Starting with an image that uses a tile size of 128 x 128 pixels this SQL example creates a copy of the image using 500 x 500 pixel tiles.

 

Example: Resize an Image using Merge - We can change the size of an image while maintaining georegistration by using the Merge Images command.  This example shows how to take an image that is 3,038 x 4,334 pixels in size, using approximately 36 meter pixels, and to create a re-sampled image that is 1,115 x 1,590 pixels in size, using 100 meter pixels.