- Notifications
You must be signed in to change notification settings - Fork8
🎨 Read/write all color palette file formats ❤🧡💛💚💙💜
License
1j01/anypalette.js
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
There are a LOT of different types of palette files.Like, way too many.But we can solve this.
One library to rule them all, one library to find them,One library to load them all and in the browser bind them.
AnyPalette.js has a single interface for all formats, so you can load any of the supported file types with one call,and it'll choose an appropriate parser to use automatically.
It can even load from files that aren't intended specifically as palettes, but that have CSS-style color values in them (.css, .html, .svg, .js, etc.)
Works in Node.js and in the browser.
Supported palette formats:
File Extension | Name | Programs | Read | Write |
---|---|---|---|---|
.pal | RIFF Palette | MS Paint for Windows 95 and Windows NT 4.0 | ✅ | ✅ |
.gpl | GIMP Palette | Gimp,Inkscape,Krita,KolourPaint,Scribus,CinePaint,MyPaint | ✅ | ✅ |
.aco | Adobe Color Swatch | AdobePhotoshop | ✅ | ✅ |
.ase | Adobe Swatch Exchange | AdobePhotoshop,InDesign, andIllustrator | ✅ | ✅ |
.txt | Paint.NET Palette | Paint.NET | ✅ | ✅ |
.act | Adobe Color Table | AdobePhotoshop andIllustrator | ✅* | ✅ |
.pal, .psppalette | Paint Shop Pro Palette | Paint Shop Pro (Jasc Software / Corel) | ✅ | ✅ |
.hpl | Homesite Palette | AllaireHomesite / MacromediaColdFusion | ✅ | ✅ |
.cs | ColorSchemer | ColorSchemer Studio | ✅* | |
.pal | Starcraft Palette | Starcraft | ✅ | ✅ |
.wpe | Starcraft Terrain Palette | Starcraft | ✅ | ✅ |
.sketchpalette | Sketch Palette | Sketch | ✅ | ✅ |
.spl | Skencil Palette | Skencil (formerly called Sketch) | ✅ | ✅ |
.soc | StarOffice Colors | StarOffice,OpenOffice,LibreOffice | ✅ | ✅ |
.colors | KolourPaint Color Collection | KolourPaint | ✅ | ✅ |
.colors | Plasma Desktop Color Scheme | KDE Plasma Desktop | ✅ | |
.theme | Windows Theme | Windows Desktop | ✅ | |
.themepack | Windows Theme | Windows Desktop | ✅ | |
.css, .scss, .styl | Cascading StyleSheets | Web browsers / web pages | ✅ | ✅ |
.html, .svg, .js | any text files with CSS colors | Web browsers / web pages | ✅ |
*The ColorSchemer file parser is only enabled when the file extension is known to be.cs
,provided by passing aFile
object, oroptions.fileName
, oroptions.fileExt
, oroptions.filePath
.The Adobe Color Table loader is only enabled when the file extension is known to be.act
OR the file is exactly 768 or 772 bytes long.
UNSUPPORTED palette formats (for now):
File Extension | Name | Programs | Read | Write |
---|---|---|---|---|
.gpa | Gpick Palette | Gpick | ||
.acb | Adobe Color Book | AdobeInDesign andIllustrator | ✅** | |
.acbl | Adobe Color Book Library / Legacy | AdobeInDesign andIllustrator (?) |
**None of the color spaces are supported (CMYK, CIELAB, CIEXYZ). The code is mostly all there! But I think probablyICC profiles are needed for correct-looking colors.
Picking colors from an image can be done by other libraries, likevibrant.js/node-vibrant
MIT-licensed, seeLICENSE
For Node.js / Webpack / Parcel / Rollup / Browserify, install with:
npm i anypalette --save# oryarn add anypalette
Then access the library with:
constAnyPalette=require("anypalette");
Alternatively, downloadbuild/anypalette-0.7.0.js
and include it as a script:
<scriptsrc="anypalette-0.7.0.js"></script>
This will create a globalAnyPalette
This library uses UMD, so you can also load it with AMD or CommonJS (in which case it won't create a global).
See thechangelog for upgrading.Properties and methods not documented here may break without notice.
Load a palette from a palette file.You can pass in the file data in a few different ways.
Knowing the file extension means AnyPalette.js can often pick the correct palette loader right away, which can improve the load speed, and also a few loaders are only enabled if their specific file extension matches because they can't determine if the file is actually in that format or not (for raw data formats without headers).
options.file
- the palette file to load, as aFile
options.data
- the palette file data to load, as a binary string orArrayBuffer
or Node.jsBuffer
orUint8Array
(butnot any otherTypedArray
orDataView
). In the case of a binary string, Unicode names for colors do not work, so anArrayBuffer
is preferred.options.filePath
- a path to a palette file, for Node.js usageoptions.fileName
(optional) - the file name, if you have it, including the file extension - can be obtained automatically fromoptions.file
oroptions.filePath
options.fileExt
(optional) - the file extension, if you have it, with or without the dot, e.g."pal"
- can be obtained automatically fromoptions.fileName
oroptions.file
oroptions.filePath
callback(error, palette, formatUsed, matchedFileExtension)
(required) - called when palette loading is finished, either with an error (in the first argument) or with the remaining arguments in the case of success:
Note: The callback is actually executed synchronously if you pass data directly. It's in an asynchronous style to allow for file loading, but all the palette parsing is currently synchronous. TODO:
setImmediate
at least.
Shortcut to load from aFile
object, equivalent to passing{file: file}
foroptions
.
Shortcut to load from a file path in Node.js, equivalent to passing{filePath: filePath}
foroptions
.
Returns string (for text-based formats) orArrayBuffer
(for binary formats) of the content of a file, in the givenFormat
.
To save a palette as a GPL file, sending a download in a browser:
varformat=AnyPalette.formats.GIMP_PALETTE;varfile_content=AnyPalette.writePalette(palette,format);varfile=newFile([file_content],"Saved Colors.gpl");varurl=URL.createObjectURL(file);vara=document.createElement("a");a.href=url;a.download=file.name;document.body.appendChild(a);a.click();// Note: this must happen during a user gesture to workdocument.body.removeChild(a);
If you don't know what format to export as, useGIMP_PALETTE
(.gpl
), as it's supported by a wide range of software.
Some palette formats are commonly made variable size by just leaving unused slots a certain colorsuch as#000
or#00F
.You can get aPalette
with only unique colors like so:
varwithoutDuplicates=AnyPalette.uniqueColors(palette);
(Accessible asAnyPalette.Palette
)
Stores a list ofColor
s, and some metadata.
BecausePalette
is a subclass ofArray
, you can useforEach
,map
,join
and other methods,or access the colors via indexing e.g.palette[0]
and loop over them usingpalette.length
Note: I think this was a bad design decision because
map
unintuitively returns an instance of the subclassPalette
, andPalette
is only intended to holdColor
s.I plan to change it to simply use acolors
field.
I could make it an array-like object, but that might introduce other confusions. I don't know, jQuery does it. And a bunch of browser-native objects are array-like instead of proper arrays. Maybe that's the way to go.
palette.numberOfColumns
may contain a number of columns for the palette to fit into (with the number of rows being implicit).
You should ignore anumberOfColumns
of zero orundefined
, and MAY want to ignore this property entirely.Inkscape, for example, ignores the number of columns specified in a palette.
palette.name
may contain a name for the palette (as a string), or elseundefined
.
This isnot populated with the filename, it's only available for palette formats that allow defining a namewithin the file.
palette.description
may contain a description for the palette (as a string), or elseundefined
.
(Accessible asAnyPalette.Color
)
Color
has atoString
method that returns a CSS color, which means you canpass a Color object directly to an element's style or a canvas's context.
varcolor=palette[0];div.style.background=color;ctx.fillStyle=color;
SeeUsing JavaScript's 'toString' Method, which incidentally uses aColor
class as an example.
In some cases you may need to calltoString()
explicitly to get a string, for example:
varshortenedColorString=color.toString().replace(/\s/g,"");
Color
objects also havered
,green
,blue
properties, anddepending on how they were loaded, might havehue
,saturation
,lightness
, and/oralpha
.
color.name
may contain a name for the color (as a string), or elseundefined
.
Not all palette formats support named colors.
Determines whether two colors are equal in value, or nearly equal.
varfirstTwoColorsExactlyEqual=AnyPalette.Color.is(palette[0],palette[1],0);varfirstTwoColorsBasicallyEqual=AnyPalette.Color.is(palette[0],palette[1],0.001);varfirstTwoColorsSimilar=AnyPalette.Color.is(palette[0],palette[1],20);
Note: If you want to find perceptually similar colors, it's better to use CIELAB color space instead of RGB.This function compares in RGB space and is really only meant for finding duplicates.
This class represents a loader and/or writer.
name
: A friendly name for the format, e.g."Paint Shop Pro palette"
fileExtensions
: An array of associated file extensions, without the dot, e.g.["pal", "psppalette"]
fileExtensionsPretty
: A textual representation of the file extensions, including the dots, e.g.".pal, .psppalette"
readFromText
: This exists on text-based readers. Don't use it directly, useAnyPalette.loadPalette
instead.read
: This exists on binary readers. Don't use it directly, useAnyPalette.loadPalette
instead.write
: This exists on writers. Don't use it directly, useAnyPalette.writePalette
instead.
This is an object that containsFormat
objects, keyed by format IDs.
To get an array of formats:
constformats=Object.values(AnyPalette.formats);
To get just writers:
constwriteFormats=Object.values(AnyPalette.formats).filter((format)=>format.write);
To get just readers:
constreadFormats=Object.values(AnyPalette.formats).filter((format)=>format.read||format.readFromText);
Loadall the palettes!
- Magica Voxel Palette (
.png
) - seeMagicaVoxelPalettes for examples - macOS Color Palette (
.clr
) - Gpick Palette (
.gpa
) - Low priority
- ASCII Color Format (
.acf
) - Binary Color Format (
.bcf
) - Alias/WaveFront Material (
.mtl
) - XML-based:
- Adobe Color Book Legacy (
.acbl
) - AutoCAD Color Book (
.acb
) - QuarkXPress Color Library (
.qcl
) - Scribus (
.xml
) - sK1 (
.skpx
/.skp
)
- Adobe Color Book Legacy (
- ASCII Color Format (
- Magica Voxel Palette (
Guess palette geometries?
More stuff (I have an external TODO list)
Install Node.js, if you don't already have it. (It comes with
npm
)Fork and clone the repository
The repo has a git submodule, so in the repository folder run
git submodule update --init
Install dependencies with
npm install
npm start
will start a server and open a page in your default browser;it'll rebuild the library when changes to the source files are detected, and it'll auto-reload the page
Runnpm test
to update aregression-data
folder, and then view any changes with git.
- If the changes are good/positive, great! Commit the changes along with the source code, or in a separate "Accept" commit.
- If the changes are bad/negative, try to fix the regression.
*.out.2.*
files are for files that are saved differently when loading a saved file. Ideally we want none of these.- If many files are deleted, check the console output. There are some test cases where it will exit early.
UpdateCHANGELOG.md's [Unreleased] section with any notable changes,following theKeep a Changelog format.Include any information someone upgrading the library might need to know.
When pulling changes (e.g. syncing a fork) you may need tonpm install
again to update the dependencies.
The process is currently something like this:
- InCHANGELOG.md, replace the [Unreleased] section with the next version.
- Make sure all the numbers are right. There's five version numbers and a date to update.
(TODO: useupdate-changelog (altho it doesn't support links to commit ranges...this does, but it's for a different ecosystem))
npm run buildnpm testgit diff tests/ # there shouldn't be changes to the test data at this point, that should ideally happen in earlier commitsgit add -A && git commit -m "Update for release"npm version minor # or major or patch or a specific version numbergit push --follow-tags # better than --tags!npm publish
About
🎨 Read/write all color palette file formats ❤🧡💛💚💙💜