← Back to Work
Project · AI Image Processing

colorFluff — Photos to Coloring Pages, on the Phone and with AI

Turns a photo of a person, pet, or thing into a printable coloring page: free and offline on the phone, or redrawn by AI on a .NET 10 server that checks the page still looks like the photo.

Focus: on-device machine learning in Flutter, an image pipeline that only traces what is in the photo, bring-your-own-key AI image models, an automatic likeness check, and print-ready PDFs by download or email.

Mobile
Flutter (iOS & Android)
On device
ONNX Runtime + OpenCV
Back end
.NET 10 + React
Hosting
fly.io + Supabase

See the web app (beta) ↗

What it does

Take a picture or pick one from the gallery, and colorFluff gives back a clean black-and-white page you can print, color, or share as a PDF. It comes in two tiers on one account:

  • Phone page (free): made on the phone in a second or two, works offline, and costs nothing. Small line-art models trace the edges that are really in the photo, so nothing is invented.
  • AI page (beta members): the photo goes to an image model (Google Gemini, OpenAI, or fal.ai) on the member's own API key and comes back as a hand-drawn style page. The server checks that it still matches the photo, cleans up the lines, builds a US Letter or A4 PDF, files it in an album, and can email it.

Free users go straight from the photo to the phone page. Beta and admin members get the AI options sheet first, with style, detail, background, line weight, paper size, email, and album, and can still flip back to the phone page at any time.

The free page: machine learning on the phone

The phone runs three small open-source models through ONNX Runtime (CoreML on iOS, XNNPACK on Android): one finds the subject, one finds faces, and an Informative Drawings line-art model draws the contours. OpenCV does the rest in background isolates so the app never freezes.

The hard part was making it look like a coloring book rather than a scratchy edge map. Before the line model sees a photo, fur, grass, and fabric are smoothed out while faces and eyes are kept sharp. Afterwards the page builder separates subject from background, keeps, simplifies, or removes the background, thins and joins strokes so shapes close, fills pupils and noses solid black, and draws a bold outline around the subject. Busy photos are automatically re-drawn with less detail.

Every change is tuned in a Python reference first, then mirrored in Dart, and a parity test checks the phone draws exactly the same page.

The AI page and the likeness check

Image models are good at clean, appealing line art, but they redraw the photo and sometimes change it: a different face, an extra object, a missing pet. For a page meant as a gift for family, that is the one failure that matters, so every AI page is checked before it is accepted.

A vision model (Claude, Gemini, or OpenAI, on the member's key) compares the page with the photo and scores it, and the phone's own free page goes along as a reference tracing. If a page drifts, the server retries once with a stricter prompt, then falls back to the free page (or stops with a clear message on the web) rather than handing back something wrong. Each job runs through queued, drawing, checking, rendering, and emailing stages with live progress, and records the model, the likeness score, and the cost.

Members connect their own AI providers, so each person pays their provider directly, usually a few cents a page. Keys are encrypted on the server, never shown again, and never stored on the phone: the account marks one provider "Use on my phone" on the web, and the phone signs in with the same Supabase account.

Built on ScraperAI

The server started as a copy of ScraperAI, my LLM web-extraction platform, with the crawl pipeline swapped for an image pipeline. Accounts, sign-in, encrypted provider keys, rate limits and usage caps, the background job runner, live updates over SignalR, and transactional email all carried over. That reuse is why the AI tier went from design to a working web app and phone integration quickly.

Screenshots

Stage 1

The Phone App

Take a picture or pick one from the gallery. Beta and admin members choose the AI page options and get a drawn page back. Everyone gets the free phone page, made offline on the device. The original photo is one tab away for comparison.

Stage 2

Web App, Albums & Pages

The web app shows recent pages and usage, keeps pages in albums that print or email as one PDF (the whole album or just the pages you pick), and gives every page a detail view: the drawing with a Page / Photo switch, how it was made, the likeness score and which model judged it, and when it was emailed.

Stage 3

Bring Your Own AI Provider

Members add their own Google Gemini, OpenAI, fal.ai, Anthropic Claude, or OpenRouter keys. Keys are encrypted and only the last four characters are ever shown. One provider is marked to draw for the phone and one to check likeness, and each form explains where to get a key, what it costs, and which model is recommended.

Stack

Flutter app for iOS and Android with ONNX Runtime (Informative Drawings, U2-Net-p, and YuNet models) and OpenCV for the on-device pipeline. .NET 10 and ASP.NET Core API with a React web app in one Docker container on fly.io, Supabase for sign-in and PostgreSQL, SignalR for live job progress, SkiaSharp and QuestPDF for page cleanup and PDFs, and AWS SES for email. AI image models from Google Gemini, OpenAI, and fal.ai, with Claude, Gemini, or OpenAI as the likeness judge, all on the member's own keys.

Web app (beta, sign-in required): colorfluff.fly.dev