4

I want to automatically generate a palette from an image.

Something like this, where the output is an image a single pixel tall, and 256 pixels wide, from all the colors of an input image.

enter image description here

I've tried Photoshop, where you can generate the palette, but it only supports exporting in .act and .pal files, which don't work for me.

The palette should be 256 colors, which the source image already is in.

I could do it manually, but it would take forever. Googling isn't helping me, but I thought there's bound to be someone that knows of a script or a way to do this.

I looked at this question, but the command doesn't work for me (Windows) and even if it did, I would still need a way to generate the actual png file from the text file it outputs.

Thanks in advance!

Also, I wasn't sure where to put this, so I hope this is the correct site. Feel free to delete it if it's not.

Edit: A way to convert an .act or .pal file to an actual image works as well. I couldn't find any way to do this either.

2
  • Discarding .act and .pal, what's the format you need?
    – user120647
    Commented Jul 10, 2018 at 8:29
  • Any sort of image works. I just need the output to be 1 pixel per color.
    – zirr
    Commented Jul 10, 2018 at 8:32

3 Answers 3

7

Some basic Python knowledge and a quick look at pyPNG Code Examples quickly lead to this:

import png
import sys

def makeRamp (input_name, output_name):
    source = png.Reader(input_name)
    width, height, pixels, metadata = source.read()

    if metadata['bitdepth'] == 8 and metadata['planes'] == 1 and 'palette' in metadata:
        print ('processing 8-bit indexed image')

        pal_img = open(output_name, 'wb')      # binary mode is important
        w = png.Writer(256, 1, palette=metadata['palette'])
        w.write(pal_img, [range(256)])
        pal_img.close()
    else:
        print ('this is not an 8-bit indexed image!')

if len(sys.argv) == 3:
    makeRamp (sys.argv[1], sys.argv[2])
else:
    print("please supply an input and a destination name")

All heavy lifting is done by the PNG library; as you see, it needs only minor knowledge of the (very intricate) internal file format of PNGs. (Stuff like, you have to know that you must check the color bit depth – this program will reject non-indexed color images!)

A test run on this 8-bit indexed image:

a sample PNG image taken from another question

python scratch.py 7vnEt.png ramp.png

yields the result

processing 8-bit indexed image

and a new image file "ramp.png" that looks like this:

color ramp for above image

Zoomed in x8 on the start:

zoomed in color ramp

3
  • Wow. Thank you so much. Works just as expected. I really appreciate it!
    – zirr
    Commented Jul 10, 2018 at 9:14
  • @zirr: you're welcome! If you have to process PNG files on a regular basis, Python and pyPNG are well worth looking in to. Writing this script took me a few minutes (although I did have the advantage I already knew what to watch out for).
    – Jongware
    Commented Jul 10, 2018 at 9:17
  • 1
    I already know a bit of python, but I had no idea it was this simple. Thanks for showing me this, it will be of great use. :)
    – zirr
    Commented Jul 10, 2018 at 9:19
1

You can use FFmpeg for this, it is a free tool. It should work for any image format. FFmpeg has 'palettegen' filter:
http://ffmpeg.org/ffmpeg-filters.html#palettegen-1

Say you have an image file input.png.

First run this command:

ffmpeg -i  input.png -vf palettegen=reserve_transparent=0 -pix_fmt rgb24 -f rawvideo  palette_binary.rgb

It will create the palette in binary format (palette_binary.rgb).

Then convert it to 1-pixel height PNG image:

ffmpeg -f rawvideo -pix_fmt rgb24 -s 256:1 -i palette_binary.rgb  palette.png

Two commands are needed here because you want 1-pixel height. FFmpeg by default creates 16x16 palette image, so we need to rearrange pixels.

To avoid creation of intermediate file you can combine above two commands in one command using pipe (tested on Windows):

ffmpeg -i input.png -vf palettegen=reserve_transparent=0 -pix_fmt rgb24 -f rawvideo - | ffmpeg -f rawvideo -pix_fmt rgb24 -s 256:1 -i - palette.png
0

I have already answered the question that you have linked and i have recommended to use this site: https://color.adobe.com/create/image/. Maybe is not the right solution to have all colors automatically but it could be the the easiest

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.