From b69e6fe233e5114027556fef05d6d13ef9f30398 Mon Sep 17 00:00:00 2001 From: cbiering Date: Fri, 16 Oct 2026 11:13:14 +0200 Subject: [PATCH] docs: gallery of generated gradients in the README scripts/gallery.mjs renders names and presets with the CPU renderer to docs/gallery/*.png, with a small built-in PNG encoder so it needs no dependencies. The README links them by absolute URL so they also show on npmjs.com. Co-Authored-By: Claude Opus 5.5 --- README.md | 10 +++++ docs/gallery/ada.png | Bin 0 -> 3490 bytes docs/gallery/ember.png | Bin 0 -> 3843 bytes docs/gallery/grace.png | Bin 0 -> 4320 bytes docs/gallery/lagoon.png | Bin 0 -> 4545 bytes docs/gallery/linus.png | Bin 0 -> 3743 bytes docs/gallery/margaret.png | Bin 0 -> 4217 bytes docs/gallery/newsprint.png | Bin 0 -> 2050 bytes docs/gallery/prism.png | Bin 0 -> 4841 bytes scripts/gallery.mjs | 79 +++++++++++++++++++++++++++++++++++++ 10 files changed, 89 insertions(+) create mode 100644 docs/gallery/ada.png create mode 100644 docs/gallery/ember.png create mode 100644 docs/gallery/grace.png create mode 100644 docs/gallery/lagoon.png create mode 100644 docs/gallery/linus.png create mode 100644 docs/gallery/margaret.png create mode 100644 docs/gallery/newsprint.png create mode 100644 docs/gallery/prism.png create mode 100644 scripts/gallery.mjs diff --git a/README.md b/README.md index eb9c3b1..e61a037 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,16 @@ import { DitherGradient } from 'ditherdance/react' ``` +## Gallery + +Every tile is one string or preset, rendered by `scripts/gallery.mjs`. + +| ada | grace | linus | margaret | +|:-:|:-:|:-:|:-:| +| `name="ada@example.com"` | `name="grace"` | `name="linus"` | `name="margaret"` | +| ember | lagoon | prism | newsprint | +| `preset="ember"` | `preset="lagoon"` | `preset="prism"` | `preset="newsprint"` | + ## Images Try every method on your own picture at [dither.dance/image](https://dither.dance/image). diff --git a/docs/gallery/ada.png b/docs/gallery/ada.png new file mode 100644 index 0000000000000000000000000000000000000000..2eaaa1da4ab441e4817ae0818d074209da1f3c99 GIT binary patch literal 3490 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

|d+F_H%Y zuDnB{!-s#z2hnb4OWFwT%2_kG41!7M;dPaf{dBQ~HtTYjZv4TMJ z9+`-I`3dor{D`DRB@;0;{}Xh6y|HnclBz@nZcbsl3ao+%q-(3Xp)iw2e1>M1`7Z?A z`J5pfE5$`B8@0_d4B1Tq@r;=sT87WtSM0U!ogOZpJ*m?!lR+0@H#1Lh&BNR1LQEJy z7d4;(gUZ1bZID}}-gA#9ORB(|Y`d#z2_fZ7 z{wS-CN98z7rKhc^iDPk04U8C^yQ>Il&u(Y1)W%90YiLHw>h$S19mFatoz^>%+Ik~5 znP9)kysPWV+=y2^poDm?Ev3l^I^iw9Ej{eNs(Pe)BSHYQF=VqXrYS_5=T1st$$KmL z^HL9`cA4W@wc8ou6EhLBNfp6L1l-uWKjHKpi>VXjG$|^cl=LD&4}b#jX>TeO2FGhv9Tvw8+Q;(zz~8-*!UTi*zbsEtg*HUO%Wrt{6AW}h$!I6} zABL!vlJ;bk3q-MHviw0>N(s>0~^5>$D=`Z_s{ zhmYef5J3?@oyyGN?$ffj1NO*t5w{JvXy$_RMl(sAqSSU)MZC(!Dur>pgqOw(bAsFC zv`UWFgSP@6?goA4@40e*A<%p#yqhi*Ne`kbyC(yIP5sX(!|xegI$-4*F-Y^eL8x3s z@$4E{C#O(*U1@>}DirXMZ@4CT2shnf`<~f4zm4J z9P-mQx1^z0#?DD_T{q|J-jPDPX3^lmPXGy`iJF$LND6!q*Hs=^9}dWlH?ANkf=4kf z;ng2LF|;JjpixE`k3Pa6r^P@_-xhhwyGNP(hvh}9RhmpKkRf)|ODjjGB>p&eox^&NjK_u1FIp`*%dCx&bM((0xx@bUY! z7w4#Y;JpJO=l>7WP9;PD literal 0 HcmV?d00001 diff --git a/docs/gallery/lagoon.png b/docs/gallery/lagoon.png new file mode 100644 index 0000000000000000000000000000000000000000..1f88f5d3ff7c2a7ff65d2d9c827533c369ef2640 GIT binary patch literal 4545 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/margaret.png b/docs/gallery/margaret.png new file mode 100644 index 0000000000000000000000000000000000000000..82bc4dedd780beef81804561a7db1c36066644cf GIT binary patch literal 4217 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 dp;$13aHa}oc5ikD{=zaq?ZO09_ { + let c = n + for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1 + return c >>> 0 +}) +const crc32 = (buf) => { + let c = 0xffffffff + for (const b of buf) c = crcTable[(c ^ b) & 0xff] ^ (c >>> 8) + return (c ^ 0xffffffff) >>> 0 +} +const chunk = (type, data) => { + const out = Buffer.alloc(12 + data.length) + out.writeUInt32BE(data.length, 0) + out.write(type, 4, 'ascii') + data.copy(out, 8) + out.writeUInt32BE(crc32(out.subarray(4, 8 + data.length)), 8 + data.length) + return out +} + +function png(rgba, width, height) { + const ihdr = Buffer.alloc(13) + ihdr.writeUInt32BE(width, 0) + ihdr.writeUInt32BE(height, 4) + ihdr.set([8, 6, 0, 0, 0], 8) // 8-bit RGBA + const raw = Buffer.alloc((width * 4 + 1) * height) + for (let y = 0; y < height; y++) { + raw[y * (width * 4 + 1)] = 0 // no filter + rgba.copy(raw, y * (width * 4 + 1) + 1, y * width * 4, (y + 1) * width * 4) + } + return Buffer.concat([ + Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), + chunk('IHDR', ihdr), + chunk('IDAT', deflateSync(raw, { level: 9 })), + chunk('IEND', Buffer.alloc(0)), + ]) +} + +function upscale(cells, cols, rows, scale) { + const w = cols * scale + const out = Buffer.alloc(w * rows * scale * 4) + for (let y = 0; y < rows * scale; y++) { + for (let x = 0; x < w; x++) { + const src = (((y / scale) | 0) * cols + ((x / scale) | 0)) * 4 + out.set(cells.subarray(src, src + 4), (y * w + x) * 4) + } + } + return out +} + +const dir = new URL('../docs/gallery/', import.meta.url) +mkdirSync(dir, { recursive: true }) +for (const { file, options } of TILES) { + const cells = renderPixels(normalize(options), COLS, ROWS) + const image = upscale(cells, COLS, ROWS, CELL) + writeFileSync(new URL(`${file}.png`, dir), png(image, COLS * CELL, ROWS * CELL)) + console.log(`docs/gallery/${file}.png`) +}