https://github.com/lexluthor0304/negativeconverter
https://github.com/lexluthor0304/negativeconverter
film javascript linux macos negative photography tauri windows
Last synced: 12 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/lexluthor0304/negativeconverter
- Owner: lexluthor0304
- License: mit
- Created: 2025-03-26T08:14:47.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2026-05-27T01:54:53.000Z (27 days ago)
- Last Synced: 2026-05-27T03:23:22.646Z (27 days ago)
- Topics: film, javascript, linux, macos, negative, photography, tauri, windows
- Language: JavaScript
- Homepage: https://negative-converter.tokugai.com
- Size: 7.93 MB
- Stars: 33
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Film Negative โ Positive Converter
Negative Converter helps film photographers turn scanned or camera-digitized film into clean, natural-looking positives with a workflow made for everyday editing. It brings frame cleanup, film-aware conversion, roll consistency, finishing controls, and export into one focused workspace.
Whether you are reviewing a fresh roll, restoring family negatives, or preparing a consistent set for sharing, the app is designed to make film conversion feel fast, approachable, and dependable while keeping your photos private.
## ๐ Features
- ๐ท **Supports PNG/JPG file uploads** (including 16-bit PNGs via UPNG.js and .cr2, .nef, .arw, .dng, .raw, .rw2 raw files via LibRaw-Wasm)
- ๐ **Rotation correction** via slider or number input
- โ๏ธ **Visual cropping** with drag-and-drop overlay
- โ๏ธ **One-click white balance** by clicking a gray area in the image
- ๐๏ธ **Live controls** for:
- Temperature & Tint
- Vibrance & Saturation
- Cyan / Magenta / Yellow (CMY) channels
- ๐๏ธ **Film presets** for color negative, B&W negative, and positive slide stocks across Kodak / Fujifilm / Ilford
- ๐๏ธ **Data-driven preset system** loaded from `negative2positive/presets/film_presets.json` (supports alias fallback for older preset IDs)
- ๐ **Optional lens profile workflow**: search/select Lensfun profiles manually, or skip lens correction and continue
- ๐งท **Roll-level lens settings**: lens correction on/off and parameters can be applied to selected files or reused via roll reference
- ๐ก๏ธ **Privacy-friendly**: all image processing happens locally in your browser
- ๐พ **Flexible export**: PNG / JPEG / TIFF with selectable bit depth (8-bit, plus 16-bit for PNG/TIFF)
## ๐ How to Use
### Workflow (Step 1 โ 3)
1. **Step 1: Crop**
- Rotate / Auto Frame / Crop until only the film area remains
- Click **Next: Film Settings** (negatives) or **Next: Positive Mode** (slides)
2. **Step 2: Film Settings**
- Pick film type: **Color**, **B&W**, or **Positive**
- **Color negatives**: set the mask baseline (sample manually / auto-detect / roll reference)
- Click **Next: Convert and Continue**
3. **Step 3: Adjust & Export**
- White balance + sliders + curves to taste
- Export PNG / JPEG / TIFF
### Film type quickstart
- **Color negative**: Step 1 โ **Next: Film Settings** โ keep **Color** โ set mask โ **Next: Convert and Continue** โ Step 3
- **B&W negative**: Step 1 โ **Next: Film Settings** โ select **B&W** โ **Next: Convert and Continue** (no mask) โ Step 3
- **Positive slide**: Step 1 โ **Next: Positive Mode** (or select **Positive** in Step 2) โ **Next: Convert and Continue** โ Step 3
### Batch workflow (multiple files)
1. Click **Add** and choose multiple images (File List appears)
2. Process one frame fully to Step 3
3. Use **Save Settings** for the current frame, or **Apply to Selected** for roll-wide settings
4. (Optional) Use **Set Current as Reference** + **Apply Reference to Selected** for roll reference
5. Export via **Export All (ZIP)** or **Download All Individually**
### Guided Mode
- The Workflow panel includes a **Guide** toggle to show/hide in-app instructions (stored in localStorage)
## โ๏ธ Technical Highlights
- Uses [`UPNG.js`](https://github.com/photopea/UPNG.js) to decode 16-bit PNGs
- Uses a custom WebAssembly module based on [`LibRaw-Wasm`](https://github.com/ybouane/LibRaw-Wasm) to support `.cr2`, `.nef`, `.arw`, `.dng`, `.raw`, `.rw2` formats
- Uses UTIF.js + an in-app PNG encoder path to support TIFF export and 16-bit PNG/TIFF output options
- Includes a simplified AHD demosaicing algorithm for Bayer-pattern raw data
- Color adjustment logic is based on RGB โ HSL and RGB โ CMY conversions
- Film preset metadata is loaded from JSON and grouped dynamically by film type in the UI
- Optional lens correction uses [`@neoanaloglabkk/lensfun-wasm`](https://www.jsdelivr.com/package/npm/@neoanaloglabkk/lensfun-wasm) with **npm local assets first + CDN fallback**
- Auto frame detection uses [`@techstark/opencv-js`](https://www.npmjs.com/package/@techstark/opencv-js) loaded dynamically from the npm package asset URL
- Performance optimizations include:
- Cached DOM access
- Offscreen canvas reuse
- Throttled rendering with `requestAnimationFrame`
## Live Demo
[Film Negative โ Positive Converter](https://negative-converter.tokugai.com)
## ๐ฅ๏ธ Desktop App (Tauri)
This repo includes a Tauri wrapper to package the web app as an offline desktop application for Windows / macOS / Linux.
### Development
```bash
npm ci
npm run dev:web
```
### Vercel deployment (important)
This app must be deployed from the **Vite build output**, not by serving source files directly.
Required settings:
- Root Directory: repository root
- Install Command: `npm ci`
- Build Command: `npm run build:web`
- Output Directory: `dist`
`npm run build:web` generates `negative2positive/dist` (for local/Tauri) and also syncs it to root `dist` (for Vercel output pickup).
If Vercel serves `negative2positive/index.html` directly, module imports like `pako` / `utif` / `jszip` will not resolve in browser and upload buttons can stop working.
### Desktop dev (Tauri)
```bash
npm run tauri:dev
```
### Build installers
```bash
npm run tauri:build
```
Build outputs are placed under:
- `src-tauri/target/release/bundle/`
### macOS installation troubleshooting
If macOS shows **"Negative Converter is damaged and can't be opened"**, this is because the app is not yet notarized by Apple. Use one of these methods:
**Method 1 โ Terminal command (recommended):**
```bash
xattr -cr /Applications/Negative\ Converter.app
```
**Method 2 โ Right-click open:**
Right-click (or Control-click) the app โ select **Open** โ click **Open** in the confirmation dialog.
**Method 3 โ System Settings:**
Go to **System Settings โ Privacy & Security**, scroll down and click **Open Anyway** next to the blocked app message.
### Linux AppImage troubleshooting
- Run AppImage directly, not with `sudo`.
- The desktop app now applies AppImage-only runtime guards:
- isolates GIO module loading to avoid host `gvfs`/GLib ABI mismatches
- standard AppImage keeps DMABUF when render nodes are usable, and auto-falls back when not
- compatibility AppImage (`*_legacy-glibc235.AppImage`) defaults DMABUF off for startup stability
- Optional override for DMABUF behavior:
- force enable: `NEGATIVE_CONVERTER_DMABUF=on ./Negative\ Converter*.AppImage`
- force disable: `NEGATIVE_CONVERTER_DMABUF=off ./Negative\ Converter*.AppImage`
- If startup still fails on older distros, use the compatibility AppImage (`*_legacy-glibc235.AppImage`).
### Release (GitHub Actions)
1. Update versions:
- `src-tauri/tauri.conf.json`
- `src-tauri/Cargo.toml`
2. Merge to `main`
3. GitHub Actions automatically:
- creates a `vX.Y.Z` tag
- publishes a GitHub Release with the installers
- (optional) syncs installers to Cloudflare R2 under `negative-converter/release/vX.Y.Z/`
#### Cloudflare R2 sync (optional)
If you want the release workflow to upload installers to R2, add **one** of these GitHub Actions secret sets:
**Option A: R2 S3 API token**
- `R2_ACCESS_KEY_ID`
- `R2_SECRET_ACCESS_KEY`
- `R2_BUCKET`
- `R2_ENDPOINT` (e.g. `https://.r2.cloudflarestorage.com/`)
**Option B: Cloudflare API token (no S3 keys)**
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
- `R2_BUCKET`
## ๐ก Development & Contributions
Feel free to fork, open issues, or submit pull requests with ideas or improvements.
This tool is designed to be simple, fast, and modifiable.
## ๐ License
MIT License
## ๐ Acknowledgments
Special thanks to [LibRaw-Wasm by ybouane](https://github.com/ybouane/LibRaw-Wasm),
which made it possible to support various raw image formats such as `.cr2`, `.nef`, `.arw`, `.dng`, `.raw`, and `.rw2` directly in the browser via WebAssembly.
Your work was an essential reference and greatly accelerated development.