# Is there a way to rename images based on their dominant color?

I have a folder full of PNG files made up of a single color... Here are a few of them to give an idea of what I'm trying to do:

I want the name of the files to be their hex color codes. It would be really nice if there were some automated way of doing this.

I know there are ways to extract the color code from an image... theoretically it seems like it should be possible to rename each image with its resulting color code.

Just thought I'd see if someone here might have any ideas... I am on Windows

Anyone?

Thanks

• I believe you would need a script written specifically for this. As far as I am aware, PS has no way of doing this out of the box. – Alin Jun 1 '17 at 9:12
• Yes you can do this. – joojaa Jun 2 '17 at 5:10
• @joojaa Can you elaborate a little? Specifically HOW can I do this? – BANG Jun 2 '17 at 6:28

OK so after some considerable searching I've now found a solution to this 'dilemma' of mine... Yay! Saved me so much work

The main key to making all of this possible at all is the ridiculously powerful (and free) software known as ImageMagick

*Note: On Windows at least, for full functionality ImageMagick also requires that Ghostscript be installed as well.

Starting filenames do not matter because they are handled using "*" as wildcard... Here is what I was starting with:

Using ImageMagick via the Command Prompt I was able to sample and extract the color of the image, then rename each image according to RGB values, output to decimal format changing the names from (for the file at top-right in the image found in the original question for example) from "2015-09-03_223717.png" to "rgb(102,130,154).png".

This is done with the following command, run from within the folder:

magick *.png -set colorspace RGB -set filename:f "%[pixel:p]" %[filename:f].png


This makes a copy of each PNG file saved to the same folder, the originals can then be deleted. So that gets us one step closer. Some (ImageMagick users for instance) might find them more useful named this way... Here are the results:

Now we need to change the filenames from decimal color codes to hex color codes (in this case minus the preceding "#" symbol)...

On Windows this requires the addition of the *nix tool known as "sed", which I added using GOW (GNU On Windows), found here: https://github.com/bmatzelle/gow

So again from a Command Prompt within the folder enter:

for %I in ( *.png ) do ( magick %I -resize 1x1! txt: ^
| sed -e "s/^#.*$//g;s/^.* #$$.*$$ .*$/ren %I \1\.png/g" >> hexnames.bat )


This will create (in the same folder) a BAT file with the necessary rename commands for each file. Then all we need to do is double-click the resulting BAT file to run it.

Done. Files have now been renamed (for example) from "rgb(102,130,154).png" to "66829A.png". Final result:

• There is a danger that you wash out your color with scaling to 1x1 if the images have anything other than just color (such as borders). It is therefore better to use something like: convert image.png -crop 1x1+29+29 txt:- Ands sample one fixed pixel, or if you need crop isrt then scale. See average color is quite far away from predominant color. – joojaa Jun 5 '17 at 13:22
• @joojaa You're quite right. My example images all contained only one color so the resize worked out OK. Anyhow the solution has now changed.. See my new answer. – BANG Jun 5 '17 at 20:30
• Just out of curiosity, what is the purpose of having images with just one color? I mean wouldnt it be easier to generate them on the fly? Or are you getting these from some measurement? Anyway you allready got my +1 on both answer and question. – joojaa Jun 5 '17 at 20:42
• I've grabbed them over the years, just for inspiration... I liked the colors, and so I can use those individual colors as a base to build full color combinations. Thanks for the votes! – BANG Jun 5 '17 at 22:02
• Still, wouldnt it be easier to save the values. What practical benefit do you get for having them as individual files? I mean you can create the image on the fly in nearly any editor, including imagemagic. – joojaa Jun 6 '17 at 6:44

Because of my 'problem' I managed to inspire the creators of ImageMagick to add support for the 'hex' property for this output...

To do what I've done in the answer above now takes only the following:

magick *.png -depth 8 -set filename:f "%[hex:u.p{0,0}]" %[filename:f].png


So (for example) the image files will go from "generic-filename.png" to "#EA4858.png"

This leaves me with only a couple of issues now:

1. This operation makes a copy of the image (which I don't want)

2. The inclusion of the "#" symbol in the filename (also unwanted)

So here is my new solution based on the latest stable version of ImageMagick... which is 7.0.5-10 as of this writing), all accomplished from the Command Prompt on Windows (assuming you have ImageMagick installed).

First I want to rename all files, to give them a common prefix which I can reference later... This is the native Windows rename command:

REN "*.png" "temp_*.png"


That takes us from "generic-filename.png" to "temp_generic-filename.png"

I am starting out with images that are over 500px square. This is way bigger than I need them to be... The next line crops them down to a more manageable size using ImageMagick:

magick mogrify -gravity Center -crop 88x88+0+0 +repage *.png


The next step likewise utilizes ImageMagick to sample the color (at the top-left corner in this case) and outputs that information to the filename of the copy it makes in hex format:

magick *.png -depth 8 -set filename:f "%[hex:u.p{0,0}]" %[filename:f].png


Now we've gone from "temp_generic-filename.png" to (for example) "#EA4858.png"

Now I need to delete the original images since the copies have received the hex filenames. Again using Windows to delete all PNG images with the "temp_" prefix:

DEL "temp_*.png"


Last step I'm going to do is to remove the "#" symbol from my new filenames using 'rename' again:

REN "*.png" "/*.png"


The "/" in the last bit removes the first character. To remove 2 or more characters (from the beginning only) just add two or more forward-slashes.

All together now, and run from a Command Prompt within the image folder:

@ECHO OFF
FOR %a in (*.png) DO (
REN "*.png" "temp_*.png"
magick mogrify -gravity Center -crop 88x88+0+0 +repage *.png
magick *.png -depth 8 -set filename:f "%[hex:u.p{0,0}]" %[filename:f].png
DEL "temp_*.png"
REN "*.png" "/*.png"
)


Final files are now 88x88 and named according to their hex color code as follows: "EA4858.png"

(NOTE: It's a possibility (it's been suggested) that the next version of ImageMagic may leave out the "#" symbol in this output, which could then easily be manually added if so desired. If this happens then the last step will obviously be rendered unnecessary.)

Something I neglected to say in my original answer: Massive hat-tip to the crew over at ImageMagick for being so helpful!

• As I noted might likely happen – the newest stable version of ImageMagick leaves out the "#" symbol... This means the last line above (REN "*.png" "/*.png") is now no longer needed. – BANG Jun 20 '17 at 3:34
• If you want the symbol just add it to the beginning like so: "#%[hex:u.p{0,0}]" – BANG Jun 20 '17 at 3:42

Now that i have a bit of time to address the question, that is in generally better suited for Stack Overflow than here. Lets add some more possibilities. While I in general think that ImageMagick/GraphicsMagic is the way to go for quick and dirty batch operations, worth having it installed. Also it is platform agnostic so you can run it even on your phone. It is not always the best possible tool for the job, mainly because it has a bit of a cryptic syntax at times.

Also ImageMagick may not be the best tool if you have some exacting need to define what dominant means. In this case you do not need to find the dominant color as you can just sample one pixel (which is what ill demonstrate, cropping and resealing is also possible but I will leave it as a manual reading exercise). In the end general computing like text processing is easier outside batch files, and they are ultimately easier to extend.

So some alternate ways to handle this particular situation:

# Powershell

You can do this in powershell using inbuilt windows functions. The benefit of this approach is that it would work on a windows machine without having to install anything (it is in most windows 7 machines and in all newer). Making this approach suitable to even those that have very limited access to the computer administration facilities.

[Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”);

Get-ChildItem *.png | ForEach-Object {
$i = new-object System.Drawing.Bitmap($_.FullName);
$p =$i.GetPixel(0,0);
Rename-Item  $_.FullName ("{0:X2}{1:X2}{1:X2}.png" -f$p.R, $p.G,$p.B) -WhatIf;
}


Note: Remove -WhatIf from final production script, it is there for safe testing. It is a nifty feature of powershell

Secondary benefits of powershell include:

• Ability to access windows applications. So you can for example dump the results in indesign, photoshop, excel, word etc. directly.
• Process can be easily demonized to react to folder changes. So it can work on renaming files dropped on a folder
• Translating the powershell code into a managed C++, C# or VB.Net is trivial
• This is by far least involved option o get a real beginner to use since the powershell ISE that comes with windows is easy enough to use.

### Python

Now you can do this in python too. Python is usually mo goto guy for scripting needs. In this case the pythons script is pretty straightforward with say scipy.

from scipy.misc import imread
from os import rename
from glob import glob

for image_path in glob("*.png"):
newname = '%02X%02X%02X.png' % tuple(image[0,0,].tolist())
rename(image_path, newname)


note: Backup first!

### extendScript

You can also do this in extendScript, using say Photoshop. The downside is that it is horribly slow and horribly complicated. But then the benefit is that you can use all other Photoshop facilities.

#target photoshop

var outFolder = "C:/temp/output"

for(var a = 0 ;a < fileList.length; a++)
{
var fileName = fileList[a];
doc = app.open( new File( fileName ) );

doc.colorSamplers.removeAll();