FROSTxHASH BETA v0.61
Layer-based fxhash project builder.
Generative still PNGs and animated GIFs.
Created by frostbitten. Help and more available in the official CLXN•ART Discord
Features
- Build it 100% here in the browser without installation.
- NEW! fxhash gif thumbnail support.
- 99% compatibility with projects created with PureSpider Template - please report any missing features to me!
- Duplicate file handling: no worries about duplicate frames increasing project size.
- Layers within Layers - Variations can have multiple sub-layers (folders) with a mixture of static and animated elements.
- Sound Layers - Layer audio loops to create a generative soundtrack. Pause/Play with space bar.
- Animation support - Frame-by-frame animation is here! It accepts a series of frames or even sub layers each with their own frames and fps. (See the Flamingo example folder below)
- GIF export (for animated Canvas projects). Automatic perfect looping or manually clipable.
- Export with G or X or D — Each does the same thing. Stands for "Gif", "eXport", and "Download," respectively.
- Multiple render engine options depending on needs: HTML and/or Canvas.
- Features/Traits are updated to work with the new fxhash update (from April 2023)
- ??? Open to feature requests, just send me a message (@frostbitten) or drop into the discord.
Project Considerations
FPS/Frame delays
The GIF format is limited to a maximum fps of 50fps. Frames can only be shown for multiples of 1/100th of a second (a centisecond). This means certain FPS are not possible, such as 30fps since that would require 3.333/100ths of a second. However you can specify the exact frame delay you'd like in order to achive a similar speed. Setting a frame delay of 3 centiseconds would give you 33.333 frames per second, the closest possible value. For a handy chart of possible frame times and FPS see below.
Frame Time/Delay (Centiseconds) | FPS |
---|---|
2 | 50 |
3 | 33.333 |
4 | 25 |
5 | 20 |
6 | 16.667 |
7 | 14.286 |
8 | 12.5 |
9 | 11.111 |
10 | 10 |
20 | 5 |
If you do choose a FPS that isn't in this chart (or can't be defined in whole centiseconds) the closest possible value will be substituted.
Final output size
Most social media limits the size of certain uploads. At the time of writing Twitter has a limit of 15MB.
Your final output size will depend on a few factors:
- Artwork dimensions. Bigger dimensions = bigger output file size
- Is it pixel art? Pixel art is automatically scaled to cover a minimum of the "share-size" in pixels. (configurable in project.yaml)
- Number of frames in animation. Caused by too long of an animation and/or too high of a FPS.
- Multiple layers with different FPS or # of frames has the potential to take more frames to render a perfect loop. (Ex: a 3-frame loop and a 4-frame loop would require 12 frames to make a perfectly synced loop). If your FPS is consistent you can calculate how long different combinations will take by taking the # of frames for each element in a combo and finding the "least common multiple."
Sound Layers
Achieving gapless audio loops in browser playback
Lossy audio formats like mp3 add silent padding to the begining and end of clips. When played back in the browser this becomes noticeable jumps. To avoid this issue it's best to export your audio in the lossless .WAV format.
For more information on gapless playback, see this wikipedia article: https://en.wikipedia.org/wiki/Gapless_playback#Compression_artifacts.
Folder Prep
For the most part you can drop a project folder meant for the PureSpider template right into here and it'll work.
However, you really should provide a configuration file named project.yaml and define a title for your project.
Your project title will show up in the exported GIFs/PNGs. Otherwise, they will all get the generic name Project-2025-06-07
.
A very basic configuration file you can edit can be downloaded here:
⬇️project.yaml
When it comes to editing the configuration file any plain text editor will work. But, if you're on Windows I highly suggest using Notepad++ (Download from notepad-plus-plus.org). It makes editing a lot easier for non-coders by simply providing some color coding.
For a more advanced example project file you can copy and paste below. Note that anything after a # hash mark on a line is considered a "comment" and gets ignored when the config gets loaded:
Folder Organization
Example Project Folder (hypothetical)- my awesome project
- project.yaml
- layers
- 010-My Background
- This feature has specific rarities defined for each variation. "400" is 4x more common than "100." They add up to 1000.
- 100-Rainbow.png
- 400-Night.png
- 400-Sunny Sky.png
- 100-Rain
- frame01.png
- frame02.png
- frame03.png
- 020-Far Landscape
- This feature has no specific rarities defined so each has an equal chance.
- Mountains.png
- Ridge.png
- Valley.png
- 030-Middle Ground
- This feature has specific rarities but they only add up to 150. The builder accounts for this. Given they are each "50" the final rarity will be split evenly.
- 50-Thick Forest.png
- 50-Thin Forest.png
- 50-Grass.png
- 040-Foreground
- Deer.png
- Hedgehog
- This feature element is made up of a single animated layer.
- frame01.png
- frame02.png
- frame03.png
- Flamingo
- This feature element is made up of multiple layers, each with a unique framerate.
- 01-Legs-2fps
- frame01.png
- frame02.png
- frame03.png
- 02-Torso-static
- torso.png
- 03-Head-8fps
- frame01.png
- frame02.png
- frame03.png
- 100-Filter Effect-(blend-color-dodge)
- Fire.png
- Ice.png
- This feature is blended with a "Color Dodge" blend mode. For a comprehensive list of blend modes see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
- 010-My Background
- sounds
- This example project uses audio layers to create a generative soundtrack.
- Bass
- Rhythm1.mp3
- Rhythm2.mp3
- Percussion
- This feature has specific rarities defined. Beat2 has a 90% chance and Beat1 has a 10% chance.
- 10-Beat1.mp3
- 90-Beat2.mp3
- Drone
- Low Tones.mp3
- High Tones.mp3
Working Examples
Download these working example projects to see how all the features work:
- demo-frostxhash-basic-test-project.zip
A very basic test to see how well the automatic loop exporter works. - demo-frostxhash-face-project.zip
A rather complicated test that utilizes varying framerates and other things to push this tool to the limit.
Terms of Service
This project was built to allow all sorts of creative non-coders to publish generative works on fxhash. It is made available free of charge under the following terms and conditions:
- You give credit in both the project description and minted work:
- You split the primary royalties with me: tz1NoYMQaZa9Pz6Hwfx6B2x1TaGU3fSiBbW8 (frostbitten.tez)
The % of royalty to share is a suggested progressive rate. The more established the artist the larger the suggested %:- Charitable work (you take no cut): 0%
- Absolute minimum: 10%
- Popular, established artists: 50%
- Optional: use keyword/tag: frostxhash
- Warranty: No warranty! While I have put in a great effort to cover most edge cases and devices I cannot guarantee projects generated with this tool will work everywhere forever. It's also possible for the tool to have occasional bugs as new features are added or simply as old ones are updated. By using this tool to create and publish work you accept these limitations and the responsibility to test in the environments and on the devices you expect the work to be shown, and to report any issues to @frostbitten or in the discord.
- For more info or help check the Discord: https://discord.gg/neDHQXuXan
FAQ
Where am I uploading to? Is my data private?
You're not actually uploading your data anywhere online, just to your web browser. This website doesn't track any data. All processing happens locally on your computer from image compression to project zip generation.
Publishing Config
When you get to Configure capture you'll want to use these settings:
If STATIC (not animated)
- Trigger: Fixed delay
- Time before capture is taken: Depends on how quickly your token loads but 4s should be safe.
- Target: From <canvas>
- Canvas CSS selector: canvas#display
Or, if static Pixel Art
- Trigger: Fixed delay
- Time before capture is taken: Depends on how quickly your token loads but 4s should be safe.
- Target: Viewport capture
- Capture resolution: Scale the resolution of your pixel art by an integer to fit within 2048x2048. For instance, if your artwork is 400x300 you'll want to set the Capture resolution to 2000 x 1500 (scaled up by 5x).
If ANIMATED
Handles both pixel and high resolution
- Trigger: Programatic trigger useing $fx.preview()
- Target: From <canvas>...
- Canvas CSS selector:
#output-canvas
- GPU support: Shouldn't be needed, Disabled
- GIF Capture: Enabled
- Capture Interval: 1.0s (or define your own
capture-spacing
, in milliseconds, in the project.yaml file) - Frame Count: Depends on how long your animations are.
- Playback FPS: This is the FPS you want the GIF to play at.
Pre-config
You must choose a compression method before uploading your files.
Environment Tests
- App version v0.33
- macOS 10.13.6
- Safari 13.1.2
✔️ Works almost perfectly*
(* Safari automatically uses backup HTML renderer instead of Canvas if filters are needed. In such case no gif/png export.)
- Safari 13.1.2
- iOS 14.6 (iPad 7th Gen)
- Safari 14
✔️ Works fairly well*
(*⚠️ HTML renderer can be a bit slower. Canvas performs well.)
- Safari 14
- macOS 10.13.6
- App version v0.29
- Windows 10 (v10.0.19044 Build 19044)
- Google Chrome 109.0.5414.120 (64bit)
✔️ Works as expected
- Google Chrome 109.0.5414.120 (64bit)
- macOS 10.13.6
- Safari 13.1.2
⚠️ Works mostly*
(*Safari does not support filters in Canvas projects) - Firefox 109.0.1 - 64bit
✔️ Works as expected - Opera 95.0.4635.25 (x86_64)
✔️ Works as expected - Google Chrome 109.0.5414.119 (x86_64)
✔️ Works as expected
- Safari 13.1.2
- iOS 14.6 (iPad 7th Gen)
- Safari 14
⚠️ Works partially*
(*⚠️ Safari does not support filters in Canvas projects. HTML renderer has coding bug at this time.)
- Safari 14
- Windows 10 (v10.0.19044 Build 19044)
Update Log
- May 8, 2025
- fxhash gif thumbnail support! 🎉
Currently:- Consistent frame time is needed. (Duplicate frames at higher fps can be a workaround)
- Consistent frame count is needed.
- GIFs can be maxiumum of 50 frames.
- Maxiumum fps is 20fps.
Use these capture settings:
- Trigger: Programatic trigger useing $fx.preview()
- Target: From <canvas>...
- Canvas CSS selector: #output-canvas
- GPU support: Shouldn't be needed, Disabled
- GIF Capture: Enabled
- Capture Interval: 1.0s
- Frame Count: Depends on how long your animations are.
- Playback FPS: This is the FPS you want the GIF to play at.
- fxhash gif thumbnail support! 🎉
- February 14, 2025
- Transparency in gif export support.
- February 12, 2024
- Make
project.yaml
totally optional. Now users can drop the "layers" folder and it will work.
- Make
- December 31, 2023
- Sort assets by name, don't rely on them being pre-sorted.
- December 20, 2023
- Update to latest fxhash.js api.
- June 10, 2023
- Update audio handling. The previous update broke audio layers that have more than one variant.
- April 30, 2023
- Update features format to work with the new fxhash update (from April 2023)
- April 29, 2023
- Minor documentation updates
- Update
gradient-map
filter to take agradient-map-type
option. Default istable
for smooth gradients and what was used previously. Now we can also use thediscrete
type to ensure there is no blending between colors.
- April 27, 2023
- Minor documentation updates
- March 10, 2023
- Update
transformation
filter to work in html renderer. - Add new option to filter 'override-if'. Allows overriding a filter's feature value based on a layer. Helpful for overriding useless features for layers that use a "None" (blank or invisible) variant.
- type: gradient-map name: "Color Filter" override-if: - feature: Layer 1 value: None override: N/A
- Some code optimization.
- Update
- March 9, 2023
- Add info about achieving perfect gapless audio loops.
- Replace dash (-) and underscore (_) in feature names and values. You can disable this with the config option:
fake-space-replace: false
. - Change default dither-mode to just "Atkinson" since "Atkinson-serpentine" was creating an edge on the left side of the gif.
- Add new undocumented filter for transforming a layer (canvas only)
- Fix some output rendering handling. Needs revision still. Currently if a view-size is smaller than artwork the output will also be that view-size. It should be an option to use reduced or original size in output.
- Change remaining canvas-based asset cache to
createImageBitmap
.
- March 8, 2023
- Utilize a customized version of gif.js to allow for more export compression options.
netsize: 16
Between 1-256. Default is 256. Defined as "number of colours used" by the algorithm creator. Reducing this will lower gif file size. However I've found the output color palette size remains 256.gif-quality: 1
Between 1-30 where 30 is a faster render time / lower quality and 1 is slowest but best. Low quality doesn't seem to reduce file size.
- Utilize a customized version of gif.js to allow for more export compression options.
- March 7, 2023
- Animated gradient map / color cycle now considered when calculating loop length. This ensures a full color cycle!
- Also in gradient maps: Fixed sharp color edge between end and restart of color cycle when using "smooth" animation transition.
- Fix bug in ticker when recording gif. Previous it was incorrectly ticking by 2 centiseconds (cs). Now it ticks by 1cs. But if the gif frame ends up only 1cs long it is saved as 2cs to preserve speed.
- Update frame delay calculation to round to nearest centisecond. Add extra parentheses to calculations for clarity and surety.
- March 6, 2023
- Canvas renderer performance updates.
- Render to offscreen canvas to build up layers before drawing final render to display canvas. (No use of workers yet)
- Use
createImageBitmap
for resized assets. - When resizing assets only store the resized version.
- Canvas renderer performance updates.
- Feb 13, 2023
- Fix a bug where oversized animated variations wouldn't generate small version of assets.
- Feb 11, 2023
- Add language to terms allowing charitable sales without revenue sharing
- Feb 9, 2023
- Add "Publishing Config" section
- Feb 7, 2023
- Update export tool for touch devices: double-tap to open an export screen. Various screens throughout export process now have buttons to compliment the keyboard shortcuts as well.
- Feb 6, 2023
- Redo perfect loop calculator. Now we calculate the loop length for each layer then find the lowest common multiple.
- Add [i] shortcut key to toggle an information panel about the loop length.
- Update demo project "face"
- Absolute minimum of primary royalty split changed to 10% for launch. Plan is to decrease over time, never increase.
- Backup render engine automatically deploys in certain environments for projects using advanced features.
- Feb 4, 2023
- Standardize sort order of layer variations across browsers. Fixes issue of different browsers producing different generative results. Tested and verified consistency across macOS safari, firefox, chrome, opera and Windows 10 chrome and firefox.
- Feb 3, 2023
- Special features which don't work in all browsers now get a warning and require acknowledgment. Specifically svg filters.
- Added createImageBitmap polyfill to allow older safari browsers to work.
- Ensure each library file has proper license included.
- Jan 28, 2023
- Terms and conditions are now required to be accepted before zip export.
- Jan 26, 2023
- Undocumented feature updated: "Color cycle," "palette shift," or "gradient map" whatever you want to call it—has been updated to allow arbitrary numbers when defining the filter "transition," not just "smooth." No transition is the default which mimics the old school color cycle technique.
- Jan 24, 2023
- Found and fixed a problem with the handling of jpeg images. Zipping would fail to identify jpeg images and crash.
- Trim occasional extra "-" and "_" off beginning and end of names.
- Maximum display size now an option and enforced via "view-size" (in pixels) config. For people who are generating print-quality work to be also viewable on a normal device. Default is 1920.
- Found and fixed a problem when rebuilding canvas scene (during export). "updateFns" array, which runs with every frame and updates each layer, was not always cleared before rebuilding.
- Jan 22, 2023
- Export with "g" or "x" or "d" (for "Gif", "eXport", and "Download").
- Exporter detects if iteration is animated or not and then generates appropriate format (GIF vs PNG)
- Exported filename now uses project title followed by the first two and last two characters from iteration hash, followed by CRC32 hash of the iteration hash.
- Animated palette shift was found to be broken and was fixed.
🤓 Tech notes: The process that builds this website had automatically renamed some necessary functions and variables. To account for this we now reference them as properties in a Tools object. Any tool that references another tool needs to be "built" by wrapping it in a function where we can inject the Tools without worry about the actual "Tools" object variable name (since that gets renamed too).
- Dec 3, 2022
- Mostly working. Compatibility with PureSpider template seemingly achieved - Capable of building and testing projects, not production ready.
Help
Here's some useful info to share when asking for help:
Browser: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/137.0.0.0 Safari/537.36 Prerender (+https://github.com/prerender/prerender)
Errors: None