I've seen a number of scripts for converting Photoshop .asv .acv files to a GIMP friendly format. Does anyone know if such a tool exists to do the opposite, i.e. converting a GIMP curve file to .asv .acv? I'm interested in this for use in the ffmpeg curves filter. Thanks.

EDIT: It seems like the ffmpeg documentation is wrong: http://ffmpeg.org/ffmpeg-filters.html#curves. The curve files produced by Photoshop (at least on OSX) are not .asv but .acv.


3 Answers 3


I ran into the same issue, so I threw together a Python script (posted and linked at the bottom). It doesn't convert the GIMP curves present into a .acv. But it does convert it directly into an argument for an ffmpeg curves video filter. I had hardcoded the files into the script, but to make it a bit more user friendly I added some instructinos and commandline inputs for the file-in and file-out.

NB: If you are doing a simple -vf you can copy and paste it directly. If you are using a complex filter graph you still need to put the [in] and [out] arguements on either side.

Here's a usage example: I've bolded the parts that you would need to add and ellipsed the very long filter statement.

simple vf: ffmpeg -i videoin.mp4 -vf curves=master="0....1.000" videoout.mp4

part of complex filter that concatenates two videos, color corrects the product, and adds a separate audio track:

ffmpeg `
-i vid1.mp4 `
-ss 0:0:03.04 -i .\vid2.mp4 `
-i .\audio.m4a `
-filter_complex `
"[0:v][1:v] concat=n=2:v=1:a=0 [stitched]; `
[stitched] curves=master='0.0/0.000000 0.01171875/0.008608 `    
....0.99609375/1.000000' [stitchedcorrected]" `
-map '[stitchedcorrected]' -map 2:a:0 `
-vcodec libx264 -preset slow `

Hope this is helpful! Let me know if you need any help.


import re

#make generator
zerotoonestepped256gen = [lower + x*(upper-lower)/length for x in range(length)]

def formatForFFMPEG(values):
    serializedValues = values.split(' ')
    list = []
    for i in range (len(serializedValues)):
        if not list or zerotoonestepped256gen[i] - float(re.match(r"^[^////]*",list[-1]).group(0)) > 0.01:
            list.append('%s/%s' % (zerotoonestepped256gen[i], serializedValues[i]))
    return list

#print instructions
print('This is a tool to convert a color curves map from GIMP to a curves filter that can be inserted into the -complex_filter. Note that you still need to append the input and output streams onto either side of the command.')
#get filename
file = input('Please input the absolute path to the GIMP Color Curve Preset File: ')
out = input('Please enter the output file (file will be overwritten if it exists): ')

#Open the curves file
curvesfile = open(file,"r")
curvesString = curvesfile.read()
foundValues = re.findall(r'(?<=samples 256) [\d. ]*',curvesString)

masterValues = formatForFFMPEG(foundValues[0][1:])
redValues = formatForFFMPEG(foundValues[1][1:])
greenValues = formatForFFMPEG(foundValues[2][1:])
blueValues = formatForFFMPEG(foundValues[3][1:])
alphaValues = formatForFFMPEG(foundValues[4][1:])

commandPrelim = 'curves=master="'

command = commandPrelim + ' '.join(masterValues) + '":red="' + ' '.join(redValues) +'":green="' + ' '.join(greenValues) + '":blue="' + ' '.join(blueValues) + '"'

with open(out, 'w') as out:
    out.write("Final Command\n\n" + command + '\n\n')
    out.write("master\n\n" + ' '.join(masterValues) + '\n\n')
    out.write("red\n\n" + ' '.join(redValues) + '\n\n')
    out.write("green\n\n" + ' '.join(greenValues) + '\n\n')
    out.write("blue\n\n" + ' '.join(blueValues) + '\n\n')
    out.write("alpha\n\n" + ' '.join(alphaValues) + '\n\n')


Thanks for this script. It is the only one that works. I tried gimp2acv, which purportedly outputs an acv file directly, which is ideal because you only need use curves=psfile='<acv file>' , instead of a long string of points as with curves=master='0....1.000', but it is an old script written for python2 and has many errors with python3, which is the only version that comes with OS X Ventura. I tried converting it to python3 with 2to3 but still got some issues that I had to correct manually. When it finally worked, I got a 4 byte .acv file.

Your script works but it is inconvenient to use because you have to run it each time and manually enter file paths each time you run it. I am using ffmpeg from a bash script and would like to simply call this script with file path args and cat the file to a variable to avoid pasting all those points in each ffmpeg call (curves=master='$curves'). That's what I do manually now. Is it possible for you to add that functionality to this same script as an option? I tried to do it myself but found that reading arguments from the command line is no trivial task like it is with other languages.


I did some work on converting the gimp2acv python module at fehlfarbe/gimp2acv: Converts GIMP curves to Adobe ACV curves from python2 to python3 and it now does exactly what the OP asked for. I posted it at the issue I started: After converting gimp2acv.py to python3 and manually correcting a few string-related TypeErrors, got .acv file of 4 bytes · Issue #1 · fehlfarbe/gimp2acv

Here is a direct link to it: gimp2acv-master - python3.zip

Unzip it and cd to the directory 'gimp2acv-master - python3'.

Example: python3 ./gimp2acv.py -i GIMPcurves.gcv -o GIMPcurves.acv

I tested it with ffmpeg -i "input.jpg" -vf "curves=psfile=GIMPcurves.acv" "output.jpg" and got the expected output.


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.