home.social

#thingumbrella — Public Fediverse posts

Live and recent posts from across the Fediverse tagged #thingumbrella, aggregated by home.social.

fetched live
  1. @kbob @djnavarro Back in 2015, I made an interactive gradient designer for IQ's cosine-based approach and have used the tool& gradients for a ton of projects since:

    dev.thi.ng/gradients/

    You can also find some useful gradient presets here:

    codeberg.org/thi.ng/umbrella/s

    Ps. I also tried it with HSV, but never found that it works as well as with RGB...

    #ThingUmbrella #Color #CosineGradient #Editor

  2. Here's a short code snippet I used to convert & chop the massive 44000 x 25000 pixel GeoTIFF DEM file into smaller PNG tiles for easier visualization:

    gist.github.com/postspectacula

    The tool uses the following #ThingUmbrella packages:

    #TypeScript #JavaScript #DEM #GIS #Tiles #Tool

  3. This time with video (hopefully)... I found a 5 meter resolution digital elevation model of a part of the Austrian Alps (Tyrol[1]) and quickly visualized the region around the aforementioned Hintereisferner glacier using my shadergraph.thi.ng/ editor. The glacier itself is visible in the bottom left corner of the cropped terrain. The picture I posted earlier[2] was taken just north-east of the valley confluence nearest to the glacier tongue. Neighboring Kesselwandferner and Gepatschferner (the largest of the remaining glaciers in the Eastern Alps) are visible too...

    If you want to try it with your own DEMs, just drag the image (as PNG) into the browser window, then create shader nodes: Normal map, Ambient Occlusion, Bump and Multiply (and set respective inputs for each node/pass)

    [1] tirol.gv.at/sicherheit/geoinfo

    [2] mastodon.thi.ng/@toxi/11705417

    #ThingUmbrella #WebGL #ShaderGraph #DEM #GIS #Terrain #Glacier #Tyrol

  4. Heads up for those who care: A flurry of #ThingUmbrella updates/additions incoming, incl. new nD spatial hash table (with 2D/3D optimizations), indexed mesh data structure, updates to thi.ng/vectors and thi.ng/webgl and other small fixes. More details in next day or so...

    New example project (#189) to demonstrate basic usage of the new mesh type (and conversion from imported OBJ model):

    Demo:
    demo.thi.ng/umbrella/webgl-mes

    Source code:
    codeberg.org/thi.ng/umbrella/s

    #ThingUmbrella #WebGL #Mesh #Geometry #TypeScript #JavaScript

  5. I somehow missed that the Go-rewrite of #TypeScript (v7.0.2) with supposedly 10x performance already had been released two weeks ago[1]. Of course, I immediately had to try it out with thi.ng/umbrella and see how this impacts build times. tl;dr It's very impressive and congrats to the team who pulled it off!

    For context, the current #ThingUmbrella codebase contains 328k lines of TypeScript source code, of which 218k lines are actual code, 87k lines comments, the rest blanks. There're 216 packages (aka individual libraries) and 188 example projects to demonstrate their usage.

    TS v6 build times:

    • from scratch (packages only): 5m 44s
    • rebuild (packages only): 2m 18s
    • examples: 1m 18s

    TS v7 build times:

    • from scratch (packages only): 1m 50s
    • rebuild (packages only): 29s 166ms
    • examples: 56s 193ms

    This is really cool and means a 3-5x speed up for (re)building all packages. The difference for example projects is much smaller, since there most of the time there is consumed by Vite (TypeScript is only used for type checking prior to building).

    Currently (for TS6), my package build steps are actually using esbuild for code generation and here tsc is also only used for type checking and outputting type declaration files. This was done because esbuild is much faster (even in incremental mode). But with the TS7 speedups, I don't need this extra build tool anymore...

    Notice for users: I've not yet officially switched to TS7, but will do so in the near future. I'm also grateful that there were only minor code changes (and fair ones) required for switching to the new version. For example, TS7 is catching obsolete generics, which previous versions didn't complain about...

    Actually very happy about this new release (usually more of a dread)!

    [1] devblogs.microsoft.com/typescr

    #ThingUmbrella #Build #Performance #Benchmark

  6. With Firefox 153 officially supporting WebAssembly.promising and its counterpart WebAssembly.Suspending[1], I've updated thi.ng/wasm-api to simplify the integration of hybrid JS/WASM async function calls, so you don't have to worry about manually creating these wrappers:

    • JavaScript async functions declared in a module's WASM imports will be auto-wrapped using WebAssembly.Suspending
    • WASM exports declared/listed via WasmModuleOpts.asyncExports will be auto-wrapped using WebAssembly.promising

    However, since that WASM feature isn't yet supported by Safari (no surprise there) and various mobile browsers, it's best to check for and selectively limit features relying on this mechanism...

    Happy coding! :)

    [1] developer.mozilla.org/en-US/do

    #ReleaseAnnouncement #ThingUmbrella #OpenSource #WASM #WebAssembly #TypeScript #JavaScript #Async

  7. Another #ThingUmbrella release cycle this AM:

    • fixed yesterday's thi.ng/geom-io-obj stream parser update to also support #Safari (aka the modern IE6-like browser problem child), which in the release notes for Safari v26.4 claims[1] that ReadableStream can (finally) be iterated via for await(...) syntax, but then turns out it's still only planned for v27 [2]... 🙄
    • added async versions of all timing & benchmarking functions in thi.ng/bench to support benchmarking async functions

    [1] webkit.org/blog/17862/webkit-f
    [2] developer.mozilla.org/en-US/do

    #OpenSource #ReleaseDay #TypeScript #JavaScript #Async

  8. New #ThingUmbrella release(s): Updated the thi.ng/geom-io-obj OBJ mesh parser to support stream parsing using async iterables. This allows direct piping fetch() responses to the parser.

    const response = await fetch(MODEL_URL);
    const objModel = await parseOBJFromStream(response.body);

    Also polished and published a related small example project for it (incl. arcball camera controller, which had an update too):

    Demo (Click & drag to rotate view, touchpad/mousewheel to zoom):
    demo.thi.ng/umbrella/webgl-obj/

    Source:
    codeberg.org/thi.ng/umbrella/s

    Alternatively to stream parsing, there's also a generator/co-routine based version. This can be used standalone or together with thi.ng/fibers to better control the time slicing behavior when parsing large model files (tens or hundreds of MB) and so gives fine-grained control to avoid blocking the main UI thread:

    import { timeSlice } from "@thi.ng/fibers";

    const response = await fetch(MODEL_URL);
    const src = await response.text();
    // parse in 10 millisecond time slices
    const model = await timeSlice(parseOBJGenerator(src), 10).run().promise();

    More background info & discussion for those interested:
    codeberg.org/thi.ng/umbrella/p

    #OpenSource #Stream #Mesh #OBJ #WebGL #TypeScript #JavaScript

  9. Some weeks ago I got a cheap and fast TTArtisan 50mm/f1.2 prime lens to take better indoor pictures and close ups. Since it's fixed length and manual focus only, it's a very different kind of taking pictures, selecting/framing motifs, and often feels like a throwback to my first camera in the 1980s. I love it!

    Since the lens has quite noticeable vignetting, I found it interesting how that effect is showing up as curve in the image waveform...

    You can visualize your own images here:
    demo.thi.ng/umbrella/pixel-wav

    #TTArtisan #ThingUmbrella #DataViz #Photography

  10. Remembering dear Roman Verostko, who died this month two years ago, aged 94. An highly influential figure, not just for algorithmic art in general, but also for younger me personally, after meeting him during a panel discussion at the Victoria & Albert Museum in London and then corresponding for several years after...

    Living as a monk and ordained priest in the 1950/60s, he absolutely cherished his limited computer time which he had first access to as student. The more he learned about automata, automatic drawing, algorithms, rule-based methods, natural processes etc. the more his belief in religion (vs. spirituality) and in an omniscient creator was fundamentally challenged, causing years of deep internal turmoil and eventually leading him to leave the monastery to lead a secular life dedicated to making art as means to finding/reconciling answers.

    Even though both of our lives (and works) couldn't have been more different, we quickly found a kindred spirit and shared an awe of nature as primary source of inspiration. I'm sad we never met again in person, but his story and insights have stayed with me...

    (Remembering him today as I'm sorting through older pieces of mine, and it was him who originally encouraged me to investigate more plotter-based art forms/techniques, an advice I only heeded over a decade later... 🫶)

    RIP 🖤

    #TextureTuesday #AlgorithmicArt #PlotterArt #PenPlotter #Axidraw #ThingUmbrella

  11. CW: Fundraising for Open Source work & maintenance

    I don't do these often (only once or twice a year, if at all), but since I just lost the main sponsor of my open source work (forever grateful for their long & major support!), I urgently need to reach out to other people (especially users) for financial help with the continued development, documentation and maintenance efforts (incl. hosting costs) of the primarily 215 TypeScript libraries and 185 example projects in thi.ng/umbrella, but also other existing & still unreleased work/projects/tools (also Zig, Clojure)... The breadth and depth of the larger project is impossible to summarize (see project readme for an overview)

    I'm regularly posting updates related to these projects (and examples) using the #ThingUmbrella and #HowToThing hashtags.

    Being between roles, these donations are my only income at current, so every little helps! The projects have been in active long term development (some of them since 2016). In a typical irony of the universe kind of event, just yesterday the projects were featured on the frontpage of Hacker News[1] for over 12 hours and here's what some people had to say:

    "this is a absolutely remarkable set of libraries covering all kinds of nooks and cranies. It's worth putting on everyones list."

    "thi.ng is great and should really get more attention. The packages have a very clean and atomic structure, you can easily pick one or more and use them in your project."

    "This has been around for a long time and I've always been so surprised it has had seemingly so little traction outside of the author's own projects. The love and care and thoughtfulness of every library has always been so great to explore."

    If you have any questions, please reach out here (or via DM) or the issue tracker on Codeberg:

    codeberg.org/thi.ng/umbrella/i

    (I'm not always able to help [esp. when there are super detailed long requests/questions], but I'm doing my best to be helpful...)

    Deep gratitude and thank you to all my other supporters for your ongoing help and new ones for your consideration. Possible ways of funding are listed here (i.e. Liberapay, Stripe, Github Sponsors, Patreon):

    codeberg.org/thi.ng/umbrella/s

    🙏🫶

    Happy coding!

    [1] mastodon.thi.ng/@toxi/11672061

    #OpenSource #ThingUmbrella #Fundraising

  12. Since it seems to come up every single time thi.ng is mentioned on HN or Reddit: Here's another partial clarification why and when the transition from originally mostly Clojure/ClojureScript to mostly TypeScript occurred:

    news.ycombinator.com/item?id=4

    It's not a comprehensive answer, but thi.ng always was a polyglot project. There're also parts written in (and for):

    There are infrastructure packages to simplify creation of ad hoc DSLs, their transpilation or interpretation, but also interop with WASM (so far mostly geared towards & tested with Zig), for example:

    In general, thi.ng projects range from super high level computational design concepts to low-level primitives like memory allocators and memory/data layout management (e.g. thi.ng/tinyalloc, thi.ng/malloc, thi.ng/simd, thi.ng/soa) and a huge spectrum of other things in between...

    #ThingUmbrella

  13. Recently, at the library...

    "Have you got their new book 'Silk switch system problem'?"
    "No. Is that the sequel to 'Equiconnected nanosky oasis'?"
    "What's that?"
    "Oh, you've never read the 'Magnetic haze cycle' series? That's just too bad. It's full of cool ideas like the ultra-iridescent opcode sentinel, infraconnected division boundary, or even beige frontier mirror..."
    "Dude!"
    "Yeah, it's real porcelain ultra-peak! Absolutely life changing epoch omnicurve vision!"
    "I did like 'Supraviolet ring department'..."
    "Well, in that case, I'd recommend 'Macroluminous shimmer facet' instead. It's a good intro to all the abundant assembly craft."

    In preparation for some name/passphrase generator and LLM-poisoning projects/tools, I updated my online procedural text editor to be able to export generator specs/recipes directly as TypeScript source code for easy integration into your own projects...

    The above generator is here (the entire recipe is part of this super long URL):

    demo.thi.ng/umbrella/procedura

    More project & syntax info here:
    thi.ng/proctext

    #Microfiction #ProcGen #ProceduralText #ThingUmbrella #DSL #TypeScript #LLMPoisoning #NoAI

  14. PSA: Not that it was ambiguous beforehand, but these are times for stating things more clearly...

    All #ThingUmbrella package readme files are now clearly stating that these projects are "LLM-free, human-made and cared for software, maintained as part of the thi.ng/umbrella ecosystem and anti-framework" 🫡

    I cared for and tended this garden of hundreds of projects almost daily for close to 10 years[1] (even if the commit heatmap doesn't always show it). It's a testament to the things I've learned, built, explored and tried to share with the world, things which helped numerous people and companies (big & small) to realize their unique projects/products/services. I'm not gonna sacrifice this body of work and all this cohesion by watering/poisoning it with slopicides[2] and/or making it dependent on the great planetary token machine...

    In The Handmaid's Tale, I always found the moment about "freedom from" vs "freedom to" very poignant, albeit in a different/inverted sense to how it was used there: Traditionally, Open Source licenses have granted freedoms "to" certain things, especially unconstrained uses. But if licenses still have any meaning at all (highly debatable in this climate/age), we increasingly need alternative licenses/mechanisms to also grant our creations freedoms "from" certain uses/practices/people/orgs...

    [1] ...only the TypeScript/Umbrella parts counted here. Many other thi.ng projects are much older...
    [2] Have I just coined a new word?!

    #ThingUmbrella #OpenSource #NoAI

  15. #ReleaseFriday Triggered by a recent feature proposal[1], I went ahead and polished & published a closely related, already work-in-progress (but still private) feature in thi.ng/rdom to support something I call "bare lists"[2]. I've started working on this for another project last year, but needed to do more testing (which I think have sufficiently done by now).

    These "bare" lists are managed reactive control components which attach items directly to the list's parent DOM element instead of first creating a wrapper/container element for the items and so avoid introducing additional nesting.

    There're many use cases where this additional nesting was a real problem with the earlier approach, e.g. in containers with CSS grid or flex layout, tables, or generally situations where we want to have static & reactive list items as true siblings...

    The new version of thi.ng/rdom is technically a breaking change (sorry!), but the actual changes required (for you) are tiny and purely limited to the $list() and $klist() component function calls, which are now accepting a parameter object instead of positional args for the different possible behaviors. Of course, lists with item wrapper elements can still be created too, just as before (but via new args).

    I've updated & tested all existing examples impacted by this change and also created a new fully commented example project (example #187) to illustrate these "bare" lists in situ (check the DOM inspector to see the shallow structure and how updates are applied):

    Demo:
    demo.thi.ng/umbrella/rdom-bare

    Source code:
    codeberg.org/thi.ng/umbrella/s

    [1] github.com/thi-ng/umbrella/discussions/562
    [2] My use of "list" here is generic, not limited to <ul> or <ol>...

    #ThingUmbrella #Reactive #UI #OpenSource #TypeScript #JavaScript #WebDev

  16. #ReleaseSaturday 🚀 — Just pushed the new version of thi.ng/hiccup-carbon-icons (now a much larger collection of 2200+ icons, mentioned yesterday[1]) and some other smaller updates/additions to other packages...

    This is the last release before switching all packages to the recently released TypeScript 6.0, support for which will likely require some restructuring & refactoring and hopefully will be less painful than it might look so far (I'm also waiting for some dependencies to update their TS type definitions, which are currently breaking, e.g. github.com/serialport/node-ser, used for thi.ng/axidraw)

    I also added some new async operators for thi.ng/transducers-async to simplify some stream processing tasks (e.g. collecting and/or consuming stdout/stderr of a child process by rechunking the stream for line-based processing), for example:

    ```
    import { rechunk } from "@thi.ng/transducers-async";
    import { spawn } from "child_process";

    // launch child process
    const child = spawn("ls", ["-l"]);

    // split child's stdout into single lines
    for await(let line of rechunk(/\r?\n/g, child.stdout)) {
    console.log("output", line);
    }
    ```

    [1] mastodon.thi.ng/@toxi/11642201

    #ThingUmbrella #OpenSource #Maintenance #TypeScript #JavaScript #Transducers #Async #Icons

  17. It's been 4.5 years since I last updated the thi.ng/hiccup-carbon-icons collection and synced it with the upstream repo, i.e. IBM's Carbon design system. Spent a few hours today updating the icons to the current version, filtering out a hundred unnecessary ones (e.g. obsolete brand logos, IBM product/service related icons etc.) and updated the converter & code generator[1] to produce more concise outputs, then manually cleaned up the structure for dozens of them (in addition to optimizing/minimizing the SVG sources via the `svgo` CLI).

    The new set has exactly 2222 icons in thi.ng/hiccup format (SVG expressed as nested JS arrays). These icons can be used in any context where thi.ng/hiccup format is supported, i.e. both for static HTML/SVG generation and/or interactive scenarios.

    A contact sheet of the full collection (the attached image only shows a tiny selection of this):
    demo.thi.ng/umbrella/hiccup-ca

    For tree-shaking purposes each icon is defined in its own source file, e.g. the Mastodon logo can be then imported like so:

    `import { MASTODON } from "@thi.ng/hiccup-carbon-icons"`

    Example icon definition:
    codeberg.org/thi.ng/umbrella/s

    The new version is still unreleased, but the readme already contains up-to-date information and small usage examples (incl. links to live example projects to see usage in situ).

    [1] Converter/codegen tool: codeberg.org/thi.ng/umbrella/s

    #ThingUmbrella #UI #Design #SVG #Icons #OpenSource

  18. Added, updated & simplified the growing collection of darkroom-related calculators and super happy how elegant and concise the code has turned out, making it super easy to add more of them in the future.

    I think it's also another great, if minimal, example to illustrate how otherwise completely separate thi.ng/umbrella packages can seamlessly compose/combine to enable a reactive dataflow UI, all without the need for any virtual DOMs and/or completely over-the-top frameworks like React & co. It's also doing so via mostly JS-native data structures for declaring the UI (plain objects/arrays/iterables) and various constructs directly managing the reactive value streams, thus providing a lot more finegrained control over UI updates/timing/throttling). Any value changes done by the user only trigger specific, pin-point calculations which then result in equally specific UI updates to show new results. Any user action only ever triggers the minimum amount of work needed to reflect the new state.

    Calculators:
    demo.thi.ng/umbrella/darkroom-

    Source code:
    codeberg.org/thi.ng/umbrella/s

    The attached images show the source code of the entire main app (UI root) and one of the calculators...

    Ps. Please let me know if you'd like to see more of these posts in the future. I'm tempted to launch season 2 of #HowToThing (see link below for 30 previous mini projects/tutorials) — but since this is very time consuming to produce & document these projects/examples, and because there has been _very little feedback_ to these previous projects/posts, I first need to gauge interest... Thank you! 🫶

    codeberg.org/thi.ng/umbrella#h

    #ThingUmbrella #Darkroom #Calculator #Tool #Reactive #UI #WebDev #TypeScript #JavaScript #OpenSource

  19. tl;dr Using thi.ng/column-store to accelerate tag intersection queries by a factor of 880x...

    Working on the static website generator/export plugin for my personal knowledge tool has been one of the main projects this past month. A key part of this setup is tagging, not just simple flat keywords/categories, but actually treating tags as sets. The system doesn't just allow browsing content by a single tag, but also supports adding (or removing) tags to narrow or widen the current topic. E.g. The combination of "3d + geometry + typescript" would select only works which have all of these three tags...

    In the local version of my tool there's no limit to the number of tags (and it also supports tag negation), but for the static site generation I have to limit the set size (due to combinatoric explosion) and pre-compute all possible permutations, then create HTML documents for each these individual combinations which actually produce results.

    So far I'm having ~400 unique tags in use, meaning if I want to aim for a max set size of 3, there're theoretically ~64,000,000 possibilities to check[1]! For the roughly 3500 content items used for testing, a naive JS approach to filter the result array and only retain items matching the entire current permutation is so extremely slow, that I stopped the process after 3.5 minutes just for the first 250k (aka 0.4%) of the 64 million permutations, i.e. at that rate the full process would have taken ~15 hours, pretty slow for a SSG... :)

    Naive approach 🫣:

    ```
    permutation = ["3d", "geometry", "typescript"]
    results.filter(item => permutation.every(tag => item.tags.includes(tag)))
    ```

    But since I'm using thi.ng/column-store as my database, such queries can be optimized by a few magnitudes, since here these intersection queries are applied only to bitfields (explained in the pkg readme). This results in all 64+ million permutations being processed in just 62 seconds (1+ million per second). Quite the difference, i.e. ~880x faster than the above approach!

    Also, of these 64 million initial possibilities, there're fewer unique ones (excluding duplicates and ignoring ordering), and currently only ~24,000 are actually producing a result. Still, that's 24,000 index pages to generate & host and it's, of course, far, far too much!

    So I will have to also spend more effort curating and severely reducing the tag vocabulary, at least the subset used for the website. On the other hand, I think this system will really help with browsing this large body/archive of work much more meaningfully than the boring single-tag/category approach most websites are offering. And it will do so without any backend (other than file hosting)...

    [1] Permutations = 400 + 400^2 + 400^3

    #ThingUmbrella #Tagging #Intersection #Query #Bitfield #WebDev #JavaScript #TypeScript #Optimization

  20. It's Friday, spring is here (a bit too early) — it feels like a good day to share another minute recording of a variation of my Actiniaria piece which I worked on last spring and think also captures that much needed #BloomScrolling spirit...

    See #Actiniaria for more context...

    (Note: Sadly Firefox still doesn't respect the Rec2020 color profile in the video, please download the video or use Chrome or Safari for full viewing pleasure...)

    #GenerativeArt #AlgorithmicArt #NoAI #ThingUmbrella #GenArtAPI #Boids #Color #Video #Animation #TypeScript #WebGL

  21. Latest harvest of "Light Streaks" — generative photography (see start of thread for context and an explanation of the technique...)

    Again, all of these variations are still from the exact same system and choice of five randomly chosen functions. The only variable between them is the initial random seed number. Exposure here is between 5-10 billion iterations... I'm amazed by just how varied the outcomes are, still regularly encountering directions I haven't seen before...

    #Monochrome #Light #Simulation #LongExposure #Fractal #IFS #GenerativePhotography #GenerativeArt #AlgorithmicArt #ThingUmbrella #TypeScript

  22. More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

    All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number.

    #Monochrome #Light #Simulation #LongExposure #Fractal #IFS #GenerativePhotography #GenerativeArt #AlgorithmicArt #ThingUmbrella #TypeScript

  23. More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

    All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number. There seem to be several families of outcomes produced, in this post a selection of textures & sparklers...

    The sub-atomic fabric of space time?

    #Monochrome #Light #Simulation #LongExposure #Fractal #IFS #GenerativePhotography #GenerativeArt #AlgorithmicArt #ThingUmbrella #TypeScript

  24. More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

    All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number. There seem to be several families of outcomes produced, in this post a selection of "auroras"...

    Each image is the result of around 2-4 billion iterations of light capture. Original resolution is 5120x5120 pixels. I will post a fullsize image later...

    #Monochrome #Light #Simulation #LongExposure #Fractal #IFS #GenerativePhotography #GenerativeArt #AlgorithmicArt #ThingUmbrella #TypeScript

  25. Light Streaks — generative photography

    A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems), a family of very oldskool primitive/trivial fractal functions, but which can produce a fairly wide variety of outcomes. Each image is the result of billions of iterations of a single particle being iteratively transformed (meaning the particle's current position is used as the input for computing its next position etc.) For each iteration & position a tiny amount of light is being captured, slowly revealing an image, just like a negative does in analog film photography.

    Some of these images have been "exposed" (aka computed) for up to 30 mins. The smaller the amount of light captured per iteration, the smoother (less grainy) the outcome...

    (For the more technical: This is one of these projects where a floating point pixel buffer _really_ makes all the difference! My exposure rate is only 0.001 per pixel per frame, some of the images use even weaker settings... That means for a pixel to become fully white is has to be visited at least 1000 times [or more])

    Made with thi.ng/matrices (matrix transformations) and thi.ng/pixel ("film" capture)...

    #MonochromeMonday #Photography #Light #Simulation #LongExposure #Fractal #IFS #GenerativeArt #AlgorithmicArt #ThingUmbrella #TypeScript

  26. @zefu ...and as for algorithmic means to create color themes, let me point you to some alternative approaches (other than image based):

    Picking & mixing from color range presets

    github.com/thi-ng/umbrella/tre

    This allows you to create probabilistic themes based on one or more weighted base colors which are then manipulated/constrained via these available color range presets. That allows you to say something like: One third soft rose, two thirds cool cyan, 10% warm gray (see code examples and visualizations)

    Cosine gradients

    github.com/thi-ng/umbrella/tre

    This approach was invented by IQ (Inigo Quilez) and uses cosines curves (one per color channel) to create gradients (from which you could just sample a few colors to create a theme). The nature of cosines means you naturally get some form of harmony (unless you're going crazy with the curve coefficients).

    Ten years ago I made a visual editor for creating these gradients (incl. lots of presets):

    dev.thi.ng/gradients/

    You can take the coefficients from this tool and then also use them with the thi.ng/color library as described in the linked readme section above...

    #ThingUmbrella #Color #Procedural #ProcGen #Gradients #AlgorithmicArt

  27. @zefu I find the tool works best for images with a decent contrast and/or color hue range. I also recommend not choosing more than 5-8 colors to avoid too many similar ones. Also bear in mind that k-means clustering relies on random initializations and so running the process multiple times for the same image can lead to slightly different results (just press "update" a few times and see if there're any decent changes)...

    Another tip: I personally like having palettes which also include some desaturated colors, so try reducing the "min chroma" slider value (a change will recompute automatically). If you only want more rich colors, then bump up the value, but it all really very much depends on the image... The two variations attached here use min chroma 5 and 0...

    demo.thi.ng/umbrella/dominant-

    #ThingUmbrella #DominantColors #KMeans

  28. @bit101 @jonathanhogg Exactly! Since it's all so nonintuitive, some years ago I made this visualization to help me make sense of it and map out this funky max chroma boundary based on hue and luminance... The viz is for LCH, but Oklch looks very similar

    Just the other day I also found this amazing color picker at oklch.com which has interactive versions of the same (plus a 3D viz too)...

    #ThingUmbrella #Color #LCH

  29. @zefu I should update the readme to explain how these palettes were created. They're a manually curated selection of running hundreds of images through this tool (doesn't look like much, but it's been super helpful over the years) and then handpicking my favorites:

    demo.thi.ng/umbrella/dominant-

    This uses k-means clustering for segmentation, also available as library:

    thi.ng/pixel-dominant-colors

    #ThingUmbrella #Color #KMeans #Tool

  30. #ReleaseThursday 🎉 Just pushed a new version of the thi.ng/column-store database and query engine which adds support for new column types (fixed-size n-dimensional int/uint/float vectors) and RLE (run-length encoding) compression support for more column types. I also updated/extended the readme and started adding/porting more tests...

    Related to these changes is that thi.ng/rle-pack now also offers the `encodeSimple()`/`decodeSimple()` functions which work for arrays of any type. This is in addition to the more advanced bitwise RLE packing offered so far (but only available for integer arrays). The readme for that package also has more code examples now...

    Happy Coding! :)

    #ThingUmbrella #OpenSource #TypeScript #JavaScript