← Photoshot · Guides & development↗Open editor
Photoshot / Development05

Building a Free Photoshop Alternative, Part 5: Exposure Code, AI Revisions and Compatibility

Exposure adds another calculation to the shared adjustment structure developed through earlier reference work. This entry follows the color conversion, EV math and version branching in Photoshot’s GitHub code. The record does not identify a specific third-party exposure implementation that was imported.

Sources checked · Revised October 16, 2026

Read the article ↓
Before · AI-generated example portrait
Before · AI-generated example portrait
Actual Photoshot editor · October 13, 2026
Actual Photoshot editor · October 13, 2026
BUILD LOG / 01

Start with the shared code we reused

Earlier entries consulted Konva and glfx.js. For exposure, the concrete reuse point is Photoshot’s compileAdjustment: exposure appears alongside brightness, levels and curves in the shared branch below.

We added the calculation to the existing layer, lookup-table and masking flow rather than building an independent editor for it. AI-assisted code extended the structure already in place.

Code excerpt · src/adjustments.ts · v0.16.0 · L493–493 ↗
if (['brightness', 'levels', 'curves', 'exposure', 'invert', 'posterize'].includes(t)) {
Code excerpt · src/adjustments.ts · v0.16.0 · L503–505 ↗
const tables = ['r', 'g', 'b'].map((channel) =>
  Float64Array.from({ length: 256 }, (_, i) => {
    let x = i / 255;
BUILD LOG / 02

The earlier path used sRGB conversion

Exposure is not simply an EV number added to stored display-channel values. The earlier path used linear to decode sRGB and srgb to encode it again.

These are excerpts from Photoshot expressing standard color-conversion formulas in TypeScript. The record does not establish that these lines were copied from a specific repository. Writing code with AI does not mean inventing the underlying mathematics.

Code excerpt · src/adjustments.ts · v0.16.0 · L482–483 ↗
const linear = (s: number) => (s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4);
const srgb = (s: number) => (s <= 0.0031308 ? 12.92 * s : 1.055 * s ** (1 / 2.4) - 0.055);
BUILD LOG / 03

Revising exposure, offset and gamma with AI

The key factor is 2 ** v.ev: +1 EV doubles the linear-domain value and −1 halves it, before offset and gamma processing. The conversion space and operation order affect the output.

After comparison, revision 2 uses the 2.2-power path. Older adjustments keep the linear/srgb path. The branch below preserves both implementations in the same function.

Code excerpt · src/adjustments.ts · v0.16.0 · L536–540 ↗
if (t === 'exposure')
  x =
    a.revision === 2
      ? clamp(x ** 2.2 * 2 ** v.ev + v.offset) ** (1 / (2.2 * v.gamma))
      : srgb(clamp(linear(x) * 2 ** v.ev + v.offset) ** (1 / v.gamma));
BUILD LOG / 04

Better math must not silently change old work

Changing a formula is easier than preserving the meaning of saved work. Applying new math while loading an old adjustment could change an image without the user editing anything.

The revision branch is a compatibility rule, continuing the approach used for curves. The AI-assisted change included how existing data selects a calculation, not just a new function.

BUILD LOG / 05

Exposure tests and the portrait result

The portrait example uses EV +0.35, offset −0.004 and gamma 1.05. Its source portrait is AI-generated; the screenshot and result are from Photoshot.

In the historical Photoshop chart comparison, +1 / 0 / 1 produced mean difference about 0.015 and maximum 2; −0.7 / 0.015 / 1.2 produced about 0.015 and maximum 1. These are two recorded test conditions, not a claim covering every HDR or color-management workflow.

Before · AI-generated example portrait
Before · AI-generated example portrait
After · Actual Photoshot output
After · Actual Photoshot output
BUILD LOG / 06

Parts 1–5: find, connect and revise code

The first five entries share a method: use actual dependencies such as React and early PixiJS; inspect implementations such as Konva and glfx.js; connect them with AI-assisted document, layer, calculation and UI code; then revise against measured output.

Exposure shows how that work becomes a foundation for another feature. The excerpts use public v0.16.0 code, with sources and test scope kept explicit so the reuse and new implementation remain traceable.

Implementation and references

All guides & development logs ↗↗Try the editor