Copy link to clipboard
Copied
Hi Everyone,
I work in mainly pixel art and with a fixed pallette of ~150 colors but use 15-30 colors in a typical file and need to iclude a written color key in the note. Is it possible to list the hex values of each of the colors used in a document? It is time consuming for me to go through each document and match the colors in the document to the corresponding swatch library of my fixed pallette.
I have done a lot of searching online and have started scripting and plugin development but haven't found a solution. Index Mode has the closest to what I want with it's color table but there seems to be no way to export the color table as plain text or access the values of the colors without going through each individually. If I could just have a list of the hex codes from the color table I could run a script that matches the colors with their names in my fixed pallette and generate the text for my key.
Any advice would be much appreciated! I am so tired of going through this manual process!
This code allows you to save all the unique colors from the document as a csv file with hex codes:
const DE_CIE76 = 0; //color difference: 0-255
const THRESHOLD = 0; //color pixels threshold
var s2t = stringIDToTypeID,
t2s = typeIDToStringID,
colorsObj = {},
colorsArr = [];
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('mode'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'RGBColor')
...
Copy link to clipboard
Copied
Did you try to export a color lookup table?
Select Fill > Export > Color Lookup Tables
It may help.
Copy link to clipboard
Copied
Hi Omar! How does a color lookup table help? From what I can tell it's for saving adjustment layer settings so it doesn't save the colors in a document but the changes made to them.
I tried to use it on an example file and got an error
I really appreciate your reply and any further advice you could offer 🙂
Copy link to clipboard
Copied
If you save the Color Table (.act file) you can then import the file into the Swatches panel (Import swatches), set the view to List and see the Hex Codes.
Copy link to clipboard
Copied
@Jeff Arola This is closer to what I'm looking for, but it's too bad I have to export and re-import the act file. I also am not able to copy the list of hex codes into the note on the document once I have done this. @Stephen_A_Marsh s answer allows me to copy the list of hex codes from an excel file, but requires use of the codepen file reader so I still have to export the act file and then import it somewhere else. Is there really no way to do this locally within photoshop (without creating more files)?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
This code allows you to save all the unique colors from the document as a csv file with hex codes:
const DE_CIE76 = 0; //color difference: 0-255
const THRESHOLD = 0; //color pixels threshold
var s2t = stringIDToTypeID,
t2s = typeIDToStringID,
colorsObj = {},
colorsArr = [];
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('mode'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'RGBColor') {
var f = new File(Folder.temp + '/colors.raw');
(d = new ActionDescriptor()).putBoolean(s2t("channelsInterleaved"), true);
d.putBoolean(s2t('copy'), true);
(d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("rawFormat"), d);
d1.putPath(s2t("in"), f);
executeAction(s2t("save"), d1, DialogModes.NO);
f.open('r');
f.encoding = "BINARY";
doForcedProgress('Reading colors', 'readColors(f.read(), colorsObj)');
f.close();
f.remove();
for (var a in colorsObj) if (colorsObj[a] > THRESHOLD) colorsArr.push({ pixels: colorsObj[a], hex: a });
if (DE_CIE76) doForcedProgress('Filtering colors by dE = ' + DE_CIE76, 'filterByDE(colorsArr)');
var f = File(Folder.desktop.fsName + "/" + activeDocument.name.replace(/\.[0-9a-z]+$/i, '') + '.csv');
f = f.saveDlg('Save file', '*.csv,*.htm');
if (f) {
if (f.open('w')) {
if (f.fsName.match(/\.[0-9a-z]+$/i)[0] == '.csv') {
f.writeln('HEX;PixelCount')
for (var i = 0; i < colorsArr.length; i++) {
if (!colorsArr[i]) continue;
f.writeln('#' + colorsArr[i].hex + ';' + colorsArr[i].pixels)
}
} else {
f.write('<table>\n<tbody>\n<tr>\n<th>HEX</th>\n<th>Color</th>\n<th>Pixel count</th>\n</tr>')
for (var i = 0; i < colorsArr.length; i++) {
if (!colorsArr[i]) continue;
f.writeln('<tr>\n<td>#' + colorsArr[i].hex + '</td>\n<td style="background-color: #' + colorsArr[i].hex + ';"></td>\n<td>' + colorsArr[i].pixels + '</td>\n</tr>')
}
f.write('</tbody>\n</table>')
}
f.close()
} else { alert(decodeURI(f) + '\nFile access error') }
}
}
function readColors(s, colorsObj) {
for (var i = 0; i < s.length; i += 3) {
var cur = toHex(s, i, 3)
updateProgress(i, s.length)
if (colorsObj[cur]) colorsObj[cur]++; else colorsObj[cur] = 1;
}
}
function filterByDE(c) {
for (var i = 0; i < c.length; i++) {
updateProgress(i, c.length)
if (c[i] == null) continue;
var cA = new SolidColor;
cA.rgb.hexValue = c[i].hex;
for (var x = i + 1; x < c.length; x++) {
if (c[x] == null || c[i] == null) continue;
var cB = new SolidColor;
cB.rgb.hexValue = c[x].hex;
if (deltaE(cA, cB) <= 10) {
if (c[i].pixels > c[x].pixels) {
c[i].pixels += c[x].pixels
c[x] = null
} else {
c[x].pixels += c[i].pixels
c[i] = null
}
}
}
}
}
function toHex(s, from, bits) {
var h = '';
for (var i = from; i < from + bits; i++) h += (('0' + s.charCodeAt(i).toString(16)).slice(-2));
return h
}
function deltaE(a, b) {
return Math.sqrt(Math.pow(b.lab.l - a.lab.l, 2) + Math.pow(b.lab.a - a.lab.a, 2) + Math.pow(b.lab.b - a.lab.b, 2))
}
UPD:
I have updated the code. Added the ability to filter by the degree of color difference (using the delta E CIE76 formula) to filter out very close shades*, as well as the ability to set a threshold by the number of pixels so that it is possible to exclude random values (it may be necessary if the files are stored in jpg or fills with dithering are used), added optional .csv and .htm report
Zero values for each of the constants means that this filter does not work.
const DE_CIE76 = 0; //color difference: 0-255
const THRESHOLD = 0; //color pixels threshold
* note that color difference analysis is quite resource intensive, so filtering by degree of color difference can take a long time on images with many different shades.
Copy link to clipboard
Copied
Wow @jazz-y I just ran your code and this is great! with a few tweaks this will work perfectly for what I need. I really appreciate the time you took to help me out. 🙂