/233 Solutions | Calgary, Alberta
Sunny Bhuller

Build log | from the studio

Sunny Bhuller.

Software since 1995, mostly the production side — embedded firmware in the early years, GPS systems, then a long stretch of SaaS and enterprise web. 233 Solutions is the studio I run on the side, and chitra.art is what I'm building here: platform, capture rigs, and image pipelines, all from one place. This log is where the work shows up.

Entries

  1. Color Correction Belongs Before Stitching, Not After

    Per-tile RAW correction keeps seam blending honest. Pipeline order, why post-stitch CCM breaks down, and the concrete artifacts from doing it wrong.

  2. Affine vs Homography: Stop Using the Wrong Transform for Flat Artwork

    A controlled gantry over flat artwork doesn't need full homography. The math difference, when similarity is enough, and when full perspective actually matters.

  3. Manual Correspondence Points Beat SIFT for Known Grid Captures

    SIFT fails on low-feature painted regions. 8–10 manual points are faster and more reliable when the capture grid is known, with a fallback path.

  4. Crop Aggressively Between Stitches to Kill Black-Border Propagation

    Black-border artifacts cascade through sequential stitch operations. Margin math, the loss tradeoff, and a before/after on a real capture.

  5. Building a 3×3 CCM from a SpyderCHECKR 48 in OpenCV

    Reference vs measured values, why 3×3 is the right complexity, per-illuminant matrices, and validating against unseen patches.

  6. Flat-Field Correction: Calibration Procedure and Common Gotchas

    The illumination gradient problem with continuous lights. White-card capture, multiplicative correction math, and how it composes with CCM and tone curve.

  7. Registering Two-Pass Captures: 35mm Photometric Stereo to 100mm Macro Mosaic

    Different focal lengths, same target. Why encoder positions alone don't give sub-pixel registration, when SIFT actually does work, and resampling the normal map up.

  8. Photometric Stereo Height Maps: From Gradients to Surface via Frankot-Chellappa

    Why normals alone aren't enough — the integrability problem, Fourier-domain integration in plain terms, and what the height map reveals on a real painted surface.

  9. Generating Deep Zoom Image Pyramids from Stitched RAW Mosaics

    Tile size and overlap, JPEG quality vs storage across pyramid levels, color profile preservation, and the Azure serving strategy.

  10. Blurred-Fill for Aspect Ratio Handling: No-Crop Image Display

    Uniform grid tiles without cropping artwork. Blurred-background technique, CSS vs server-side pre-generation, and the edge cases.

  11. Deep zoom pyramids and the browser

    From a single composite to a DZI tile pyramid: why levels are sized the way they are, what OpenSeadragon expects, and how storage layout affects perceived load.

  12. Cross-Polarization for Painted Surfaces: The Rosco #7300 + B+W Stack

    Killing specular highlights on varnish and impasto with a linear-on-source / circular-on-lens polarizer stack — alignment, where it works, and where pigments defeat it.

  13. Closed-Loop Steppers on a Raspberry Pi 5: CL57Y + NEMA 23 + Encoders

    Open-loop steppers drift over a 1m+ scan path. CL57Y drivers and encoders on a Pi 5 — driver selection, wiring, and the real-time limits.

  14. Why a Custom Igus Drylin Gantry Beat Generic Linear-Motion Kits

    Stiffness and repeatability requirements push past what generic copy stands deliver. ZLW dual-vertical plus horizontal X on Misumi extrusion, with a cost comparison.

  15. DMX-Controlled Photometric Stereo with Godox + Enttec

    A 4-azimuth × 2-elevation hemisphere driven by DMX. Why programmatic light control beats manual sequencing, where coplanar lighting fails, and session-to-session calibration.

  16. Two-Lens Capture: 90mm Macro for Tiles, 35mm for Photometric Stereo

    One lens can't cover both jobs. Macro tile resolution math, full-frame coverage for normal reconstruction, and the workflow handoff between the two passes.

  17. Mounting a Camera on a Vertical Gantry: Counterweighting, Drift, and Cable Management

    A 2kg+ payload on a vertical slider. Why dual ZLW stages share the load, cable management without binding the slide, and microdrift during long settling.

  18. Stainless Hardware for a Contamination-Controlled Capture Environment

    The case for stainless when art is in the room. Galvanic-corrosion gotchas at aluminum-extrusion contacts, the cost delta vs zinc-plated, and outgassing during sessions.

  19. The Misumi 4040/4080 Easel: Stiffness Without a Machine Shop

    Extrusion sizing, joint design and gusseting, leveling and squaring during assembly, and a cost comparison vs Kaiser or Cambo copy stands.

  20. Redis Write-Behind View Counters with Distributed Locking

    Why write-through to SQL Server fails on hot writes. Lock-then-flush, avoiding double-count during the flush window, and the failure modes that bite.

  21. Entra ID + MSAL Across a .NET 10 / Next.js Split Stack

    Auth flow for a public site with an authenticated admin surface. Token handling across the split, Container Apps gotchas, and local-dev/prod parity.

  22. A Claude Code Workflow That Actually Ships: HTML Mockup + Markdown Spec

    The handoff format that makes agent-assisted work land. Discovery phase, numbered implementation steps with review pauses, and where the workflow doesn't fit.

  23. Parallel Claude CLI Instances for Independent Components

    When parallelism pays vs serial work. Coordination patterns to avoid merge pain, token cost modeling, and the failure modes at scale.

  24. Task Tool Sub-Agent Parallelism: Power and the Token Bill

    What sub-agents actually do under the hood, when broad search wins, when sequential reasoning loses, and practical cost modeling.

  25. VS Code Remote-SSH onto the Gantry Pi 5: Hardware-in-the-Loop Debugging

    Editing on the Pi rather than rsync. Performance tuning, workflow for live-hardware testing, and the reload, USB, and port-forward pitfalls.

  26. Hard budget caps and the public-key problem

    Azure ships a real spending cap. AWS and Google don't. What that means when you put a Google API key in plain HTML, and the small Cloud Function I wrote to fake the missing feature.

  27. Self-hosting an Azure DevOps agent in WSL2

    Microsoft-hosted parallels are $40 a month, self-hosted are $15, ADO Server is free. A walkthrough of getting a home workstation to act as a proper Linux build agent — including the Windows-host detour I'd skip if I were starting again.

  28. Parallel builds on the Azure DevOps free tier

    Six pipelines, one agent, a queue that never seemed to empty. How chitra.art's CI moved from ~30-minute sequential waits to ~90-second deploys — without paying for a second parallel slot.

  29. Why Azure over Google/AWS and other cloud providers

    Placeholder — to be filled in.

  30. SDK generation and typed clients

    Generating a versioned TypeScript SDK from a .NET OpenAPI surface, publishing it to a private feed, and consuming it from a Next.js frontend without breaking on every release.