Photoshop Colour Preserving Stretch


Astro-images normally need to be stretched to bring out the very faint structures in the background of the image. A method frequently used is Photoshop "Curves". However, this has the side-effect of bleaching the colours in the the brighter parts of the image - for instance star colour. I will show how it is possible to stretch data in Photoshop without this bleaching.

The Problem with Photoshop Curves

It's very easy to see for yourself the problem caused the Photoshop curves. Place a colour sampler on a colourful area of the image somewhere in the mid-tones. and calculate the ratio of R:G:B. Now perform a typical "Curves" stretch on that image and re-calculate the resulting colour ratios. You will find the colour has bleached towards white. The more it is stretched, the more bleaching takes place. A typical suggested workaround is to iteratively apply a small amount of stretch followed by increasing the saturation, small stretch, increase saturation etc. until the desired result is obtained. But it's very fiddly to do and it's impossible to know that the final colour obtained is true to the original. What is required is a method of stretching the data whilst keeping the colour ratios fixed i.e. to increase the intensity without diluting the colour. This is the principle behind the colour preserving stretch.

Colour Preserving Stretch in Photoshop

To preserve the colour ratios, the RGB components of an individual pixel need to be multiplied by the same scalar. This can be achieved by multiplying the image by the stretched luminance divided by the unstretched luminance. That is the idea behind the method that now follows:

1) Open the image in Photoshop
2) In the Layers menu right click and Duplicate Layer. Name this new layer "Grey Multiply" as a helpful hint to the role it will play.
3) Click on the "Grey Multiply" layer and go to Image->Adjustments->Hue/Saturation Set the saturation slider to -100. This converts the layer to grey.
4) Right click the "Grey Multiply" layer and Duplicate Layer. Name this new layer "Grey Divide", again as a helpful hint to the role it will play.
5) For the "Grey Multiply" layer set the blend mode to "Multiply"
6) For the "Grey Divide" layer set the blend mode to "Divide". For early versions of Photoshop such as CS2, "Divide" doesn't exist as a blending mode so we use the mathematical trick that performing "Colour Dodge" on an inverted image does the same thing as Divide (trust me!). So in CS2 set the blend mode to "Colour Dodge" then select the "Grey Divide" layer and do Image->Adjustments->Invert

You should now have a layers menu that looks like this:

The main image window will not have changed. For instance, it may look something like this:


Now we need to stretch the "Grey Multiply" layer. Whatever stretch we apply ends up being applied to the original image whilst preserving the colour and saturation.

7) Select the "Grey Multiply" layer and go to Image->Adjustments->Curves.

Apply a curve something like this:


Make sure you are viewing your image with a scale of 66% or 100% otherwise you'll see a complete posterised mess instead. I wish Photoshop wouldn't behave like that. The result of applying that curve is here:


You can adjust the "Grey Multiply" layer with more and more curves until you achieve the desired result.

A Slight Variation

A slight variation on the technique is to create a "Group" to contain the grey layer and the various curves adjustment layers you apply.

In this case it is the blending mode of the group that must be set to multiply:


My advice is to record this as an "Action" so you won't have to remember all the details each time.

Arcsinh Stretch in Photoshop

You may or may not know that I wrote the ArcsinhStretch module in PixInsight: PixInsight ArcsinhStretch Documentation

For powerful stretches on linear data, the Arcsinh (hyperbolic arcsine) curve has an ideal shape. I always thought it was impossible to achieve this in Photoshop because Photoshop's curves are very limiting - they allow only 16 (x,y) points which must be integers in the range 0-255 and x-points cannot be closer than 4 units apart. There simply isn't the granularity to accurately define a powerful stretch curve such as Arcsinh. Then I hit upon a solution - it is possible to define a curve that when applied twice gives the correct Arcsinh shape - i.e. what's mathematically known as the functional square root (not to be confused with the square root function). So I designed and built a set of these curves using a spreadsheet.

Here's an example:


For the avoidance of doubt, the above curve is not an Arcsinh curve but will give an Arcsinh curve (in this example with a stretch factor of 300) when applied twice in succession. Every single point on the curve has been carefully calculated in a spreadsheet.

I have calculated and built a set of five curves: Arcsinh10, Arcsinh30, Arcsinh100, Arcsinh300, Arcsinh1000 which give stretch factors of 10x, 30x, 100x, 300x, 1000x. Arcsinh100 is probably the most useful one in general. You would use the same Arcsinh100 curve in both layers to achieve a stretch of 100x. It is quite possible to "mix and match" them - for instance using Arcsinh100 in one layer and Arcsinh300 in the other layer would give a stretch somewhere between 100x and 300x.

If you want to use these curves I'm making them freely available here:

You need to unzip them into the relevant Photoshop folder. For instance, on my Windows machine that is C:\Users\Mark\AppData\Roaming\Adobe\Adobe Photoshop CC 2015\Presets\Curves but if you don't know where your own folder is, you can try saving any arbitrary curve and take notice of which folder Photoshop is using.

To use them, simply select one of these predefined curves when adding the Curves adjustment layers:


The linear image you start off with should be a 16-bit linear (i.e. unstretched) image (e.g. from DeepSkyStacker) which has the correct white balance and has had the background skyglow carefully subtracted. An 8-bit image is too limiting and 24-bit image cannot use Curves in Photoshop. Use Photoshop Levels to adjust the Black Point as far as it will go without clipping the data and also set the White Level.

If you want a practice image you can download this one of NGC7000: Google Drive NGC7000 Example

This is how it will look when you first open it:


This is what you should see after using Arcsinh300 for a 300x stretch:


You can see that my background subtraction in this example was not perfect - the dark areas are a bit green. But this was only a quick example.

Again, it is possible that what you see on your screen may be a complete posterized mess. This is that annoying "feature" of Photoshop. Try viewing it at a scale of 66% or above to make it appear correctly. Alternatively, to make images appear without posterization at all zoom scales do Edit->Preferences->Performance and set Cache Levels to 1. Close and restart Photoshop for the change to take effect. Unfortunately now when you perform operations such as curves etc you'll notice a slight delay in the image updating because setting Cache to 1 slows down the screen redraw. But at least now what you see is what you get. Unfortunately for Photoshop CC 2018 (which is what I use) it seems to be impossible to set Cache Levels to 1 because on re-opening Photoshop it always gets reset to Cache Levels = 2.


I hope you find this useful. If my description of the technique(s) is confusing then please let me know and I'll try to improve it for future visitors.