Transform any text into a visual "data fingerprint" by encoding characters as RGB pixels. Each group of three consecutive characters maps to one pixel via their ASCII values, producing a unique square PNG image for every piece of text.
- Introduction
- Architecture
- Installation
- Usage
- API Reference
- Algorithm Details
- Docker
- Development
- Troubleshooting
- Roadmap
- Digital Art — create unique artwork from quotes, poems, or stories.
- Data Visualisation — understand text structure and character distributions at a glance.
- Security — "visual hashing" for quick comparison of similar texts.
- Education — illustrate ASCII encoding, colour theory, and data representation.
Browser / API Client
│
│ POST /generate { text: "…" }
▼
Express server (Node.js + TypeScript)
│
├─► computeDimensions() → (width, height)
│
├─► textToPixels() → [(r,g,b), …]
│
└─► pngjs PNG.sync.write() → PNG bytes
│
│ 200 OK Content-Type: image/png
▼
Browser renders image inline
| Purpose | Library / Tool |
|---|---|
| Runtime | Node.js 22 LTS |
| Language | TypeScript 5 |
| HTTP framework | Express 4 |
| PNG generation | pngjs 7 |
| Testing | Jest + ts-jest |
| Containerisation | Docker / Docker Compose |
# Clone the repository
git clone <repository-url>
cd data-art
# Build and start the web application
docker compose up --buildThe app will be available at http://localhost:3000.
docker build -t data-art .
docker run --rm -p 3000:3000 data-art# Prerequisites: Node.js 22+
npm install
npm run dev # starts the server with ts-node at http://localhost:3000Open http://localhost:3000 in your browser, paste any text into the form, and click Generate Image. The resulting PNG is displayed inline and can be downloaded with the link below the image.
Accepts a JSON body with a text field and returns a PNG image.
curl -X POST http://localhost:3000/generate \
-H 'Content-Type: application/json' \
-d '{"text":"To be or not to be, that is the question."}' \
--output hamlet.pngLiveness probe for container orchestration.
curl http://localhost:3000/health
# → {"status":"ok"}The public TypeScript API lives in src/core.ts:
Compute the square image dimensions for a given text.
import { computeDimensions } from "./core";
const [w, h] = computeDimensions("Hello!"); // e.g. [1, 1] for short textConvert a text string to an array of [r, g, b] tuples.
import { textToPixels } from "./core";
const pixels = textToPixels("ABC");
// → [[65, 66, 67]]Full pipeline: convert text to a PNG and return it as a Node.js Buffer.
import { textToImageBuffer } from "./core";
const buf = textToImageBuffer("Hello, World!");
// buf is a valid PNG bufferThrows Error if text is empty.
num_pixels = len(text) // 3
side = isqrt(num_pixels) # integer square root → square image
A 300-character text produces 100 pixels and a 10 × 10 image.
Each group of three characters becomes one pixel:
(ord(text[i]), ord(text[i+1]), ord(text[i+2])) → (R, G, B)
The canvas is padded with black pixels (0, 0, 0) to fill any remainder.
| Range | Characters | Colour tendency |
|---|---|---|
| 32–47 | Spaces & symbols | Very dark |
| 48–57 | Digits 0–9 | Dark |
| 65–90 | A–Z | Medium |
| 97–122 | a–z | Medium–bright |
| 128–255 | Extended ASCII | Bright |
A multi-stage Dockerfile and a docker-compose.yml are included at the
repository root. The builder stage compiles TypeScript; the runtime stage
copies only the compiled JavaScript and production dependencies into a lean
Node.js 22 Alpine image.
# Build the image and start the service
docker compose up --build
# Run in the background
docker compose up -d --build
# Stop
docker compose down# Build
docker build -t data-art .
# Run
docker run --rm -p 3000:3000 data-art
# Custom port
docker run --rm -p 8080:8080 -e PORT=8080 data-artThe service exposes port 3000 by default and responds to a GET /health
health-check so it integrates cleanly with reverse proxies (e.g. Caddy,
nginx) or orchestrators like Docker Swarm.
npm installnpm testnpm run build # compiles TypeScript → dist/npm run dev # runs with ts-node (no build step required)data-art/
├── package.json # Node.js project metadata & scripts
├── tsconfig.json # TypeScript compiler configuration
├── Dockerfile # Multi-stage Node.js container build
├── docker-compose.yml # Compose file for deployment
├── .dockerignore
├── src/
│ ├── core.ts # Core text→image logic (TypeScript)
│ └── server.ts # Express web server
├── public/
│ └── index.html # Web UI
└── tests/
└── ts/
└── core.test.ts # Jest unit tests
- Fork the repository.
- Create a feature branch:
git checkout -b feature/my-feature. - Make your changes, add tests, and run
npm test. - Open a pull request — CI will run automatically.
| Problem | Cause | Fix |
|---|---|---|
Error: Input text must not be empty. |
Empty input | Provide non-empty text. |
Cannot find module 'pngjs' |
Dependencies not installed | Run npm install |
| Port already in use | Another process on port 3000 | Set PORT=3001 env variable |
| Docker build fails | Docker not running | Start Docker Desktop / Engine |
See ROADMAP.md for the full feature-extension plan including:
- v0.2 — NLP pipeline (stop words, lemmatisation, named-entity highlighting)
- v0.3 — PDF ingestion & web frontend (FastAPI + HTMX)
- v0.4 — Alternative colour schemes
- v1.0 — Stable API, PyPI release, Docker Hub image
- v2.0+ — 3-D voxels, animation, ML colour mapping, collaborative gallery