I edited an image with a curves adjustment on all the channels (RGB, red, green and blue). Now I want to know how those curves looked like, so I can use them again/edit them. But I made this edit a long time ago so I dont remember.

I have tried simply copying the original edit and managed to get it pretty similar. But not similar enough. The curves were very complex and that together with that I used all 4 channels, makes it very hard to get right.

I thought I had cracked it when I tried to split up the image in its red, green and blue channels. My idea was that it would be easier to copy if I focused on doing one channel at a time in black and white. Then I could save them as preset in Photoshop, and apply them combined to the original. But Ive just spent more than 2 hours getting not close enough on the red channel.

Im not very knowledgeable with curves. Do anyone have an idea on how to pull this off in practice? Could it be possible to "reverse engineer" it somehow?

  • If you do not have the original image, and the processed one it is impossible. Do you have both? - And what do you mean you processed 4 channels if you are working in RGB?
    – Rafael
    Commented Nov 25, 2016 at 17:09
  • I have both the original and the edit. Red channel + green channel + blue channel + the master RBG channel. Thats 4.
    – ismathme
    Commented Nov 26, 2016 at 17:58

3 Answers 3


If anyone i still looking for other implementations, then here is one using Python with OpenCV, Numpy and Matplotlib.

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread(r'input.png')
ref_img = cv2.imread(r'reference.png')
cv2.imshow('Unedited', img)
cv2.imshow('Edited', ref_img)

b = np.ndarray.flatten(img[:,:,0])
g = np.ndarray.flatten(img[:,:,1])
r = np.ndarray.flatten(img[:,:,2])

bRef = np.ndarray.flatten(ref_img[:,:,0])
gRef = np.ndarray.flatten(ref_img[:,:,1])
rRef = np.ndarray.flatten(ref_img[:,:,2])

bTrans = np.transpose((b, bRef))
gTrans = np.transpose((g, gRef))
rTrans = np.transpose((r, rRef))

plt.title("Curves adjustment")
plt.scatter(bTrans[:,0],bTrans[:,1], color=[0.,0.,1.], s=5)
plt.scatter(gTrans[:,0],gTrans[:,1], color=[0.,1.,0.], s=5)
plt.scatter(rTrans[:,0],rTrans[:,1], color=[1.,0.,0.], s=5)

Example images

Example images

Output curves Example curves Hope this helps!


If you'd have used a single curve per channel, and you have your input and output images, you could derive the curves back using some image processing.

But since you used both the RGB curve and the individual R, G and B curves, that is (I think) impossible (or exceedingly hard), since you won't be able to tell how much the RGB curve or the individual curves each contributed to the output.

  • Since he has both the original and the adjusted one then no this is not at all hard just plot the value difference in a graph and your done with it
    – joojaa
    Commented Mar 6, 2018 at 12:15
  • Since the poster mentioned they adjusted both the RGB curve and the R/G/B curves, it's harder (but assume not impossible?) to get back the original curves (since each channel will have been affected by both the RGB curve and the individual channel curve), but I assume you could get back something useful from the plot, yes. Commented Mar 6, 2018 at 12:47
  • 1
    Well it really depends on what tools you have at your disposal i tried to do this in mathematica and i have allready a solution that works fine
    – joojaa
    Commented Mar 6, 2018 at 12:51
  • added an answer on the subject while i was testing this.
    – joojaa
    Commented Mar 6, 2018 at 13:55
  • Cool! Does it work with changing both the RGB channel and the individual R/G/B channels? That's the part I was trying to clarify: I can't intuit how'd you extract the original curves if there are two curves per channel that affect the output. Commented Mar 6, 2018 at 14:02

Yes you can do this. However it really depends on many factors. First of you can just simply use some scientific plotting tool to plot each value in 2D where x is original value and y is new pictures value.

I am using mathematica for this, quick and dirty mathematica code looks as follows (but you could choose any other tool):

src = ColorSeparate[Import["c:\\temp\\test.png"]];
srcAdj = ColorSeparate[Import["c:\\temp\\testadj.png"]];
r = Flatten[ImageData [src[[1]]]];
r2 = Flatten[ImageData [srcAdj[[1]]]];
rtp = Transpose[{r, r2}];
g = Flatten[ImageData [src[[2]]]];
g2 = Flatten[ImageData [srcAdj[[2]]]];
gtp = Transpose[{g, g2}];
b = Flatten[ImageData [src[[3]]]];
b2 = Flatten[ImageData [srcAdj[[3]]]];
btp = Transpose[{b, b2}];
Show[ListPlot[rtp, AspectRatio -> 1, PlotStyle -> Red], 
 ListPlot[gtp, AspectRatio -> 1, PlotStyle -> Green], 
 ListPlot[btp, AspectRatio -> 1, PlotStyle -> Blue]]

So for test ive used following curves as the adjusted image (image used):

enter image description here

And mathematica gives me:

enter image description here

Which is pretty close, or possibly exactly the same value. Making a curves adjustment file out of this wouldn't be too hard*. However a word of warning! If your images are lossy, like jpeg compressed, then this will not work. Example with jpegs:

enter image description here

Now the plot points are all over the place and youd have to try to filter the data somehow. So the take here is that if the image has something other than just a curves adjustment then the thing just blows up.

* If the data was read in with the code above then the curves export is:

file = FileNameJoin[{ "C:\\temp", "out.amp"}];
  file, (SortBy[DeleteDuplicates[rtp], First] // Transpose // 
      Last) *255 // IntegerPart];
  file, (SortBy[DeleteDuplicates[gtp], First] // Transpose // 
      Last) *255 // IntegerPart];
  file, (SortBy[DeleteDuplicates[btp], First] // Transpose // 
      Last) *255 // IntegerPart];

the amp file can then be read to a photoshop curves layer for example. And it produces same image in my test case. The code is not really performace oriented but it works.

  • @dan Hey, thanks guys! But to be honest i dont even remember what image it was i wanted to do this with haha. I read your answers and it was interesting though. I dont really have a way to test it, but should i mark joojaa's answer as a solution anyways?
    – ismathme
    Commented Mar 9, 2018 at 13:33
  • @ismathme its your question. BUt out of curiosty what tools do you have. Theres no reason why this couldnt be ported to say python and numpy/scipy for example
    – joojaa
    Commented Mar 9, 2018 at 20:16
  • Well i dont really have any tools other than photoshop. I do have a little programming knowledge, so i was able to follow your code in broad strokes. But no, i dont really have a way to actually execute this lol
    – ismathme
    Commented Mar 10, 2018 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.