Quick Start
Relevant source files
The following files were used as context for generating this wiki page:This document provides a technical overview and setup guide for the hdrify application. hdrify is a web-based tool designed to convert Standard Dynamic Range (SDR) images into High Dynamic Range (HDR) images with an adjustable intensity. The application features a modern, minimalist user interface and is powered by a Rust backend that utilizes ImageMagick for image processing.
This guide covers the system architecture, installation procedures for both Docker and local environments, and a detailed breakdown of the frontend and backend components.
Sources: README.md:3-5, static/index.html:12-16
System Architecture
The hdrify application is composed of a vanilla HTML/CSS/JS frontend and a Rust backend built with the warp web server framework. The core image processing is not handled within the Rust application itself but is delegated to the ImageMagick command-line tool.
Sources: README.md:47-51, src/main.rs:4, src/main.rs:88-99
The following diagram illustrates the high-level architecture of the system:
This diagram shows the interaction between the frontend client, the Rust backend server, and the external ImageMagick process.
Sources: README.md:47-51, src/main.rs:172-183, static/script.js:275-282
Setup and Installation
You can run hdrify using either Docker for a containerized setup or by running it locally.
Sources: README.md:31-32
Prerequisites
Local Environment
- Rust: The backend is written in Rust and requires
cargoto build and run. - ImageMagick: This must be installed on the system for the image processing to work.
brew install imagemagick # macOS # or apt-get install imagemagick # Debian/Ubuntu
Sources: README.md:36-37, src/main.rs:88
Docker
- Docker: A working Docker installation is required to build and run the container.
Sources: README.md:32-33
Dependencies
The Rust backend relies on several key crates for its functionality.
| Crate | Version | Purpose |
|---|---|---|
warp | 0.3 | Core web server framework. |
tokio | 1.0 | Asynchronous runtime. |
serde | 1.0 | Serialization/deserialization of data structures. |
base64 | 0.21 | Encoding/decoding of image data. |
tempfile | 3.0 | Creating temporary files for image processing. |
Sources: Cargo.toml:7-14
Running the Application
With Docker
- Build the Docker image:
docker build -t hdrify . - Run the container, mapping port 3000:
docker run -p 3000:3000 hdrify
Sources: README.md:33-34
Locally
- Run the application using Cargo:
cargo run
The server will start and be accessible at http://localhost:3000.
Sources: README.md:37, src/main.rs:184-185
Backend API
The backend exposes a single HTTP endpoint to handle image processing. It is built using warp and serves both the static frontend files and the processing API.
Sources: src/main.rs:172-183
Endpoint: POST /upload
This endpoint accepts a form-urlencoded request containing the image data and the desired HDR intensity. Note that the README.md incorrectly lists this endpoint as /api/process; the actual implementation uses /upload.
- Path:
/upload - Method:
POST - Request Body:
application/x-www-form-urlencoded
| Parameter | Type | Description |
|---|---|---|
image | String | Base64-encoded image data (without the data:image/...;base64, prefix). |
hdr_value | Float | The HDR intensity level, ranging from 0.5 to 3.0. Defaults to 1.5. |
Sources: src/main.rs:174-177, src/main.rs:19-23, static/script.js:276-278
Response Body
The server responds with a JSON object indicating the outcome of the operation.
// src/main.rs:6-11
#[derive(Debug, Serialize)]
struct ProcessResponse {
success: bool,
message: String,
image_data: Option<String>, // base64 encoded HDR image
}
Processing Flow
The handle_upload function in src/main.rs orchestrates the entire backend process.
This flowchart details the logic inside the handle_upload function, from request validation to returning the processed image.
Sources: src/main.rs:18-154
Image Processing Pipeline
The core of the application is the ImageMagick command pipeline, which applies a series of transformations to achieve the HDR effect. This pipeline is executed by the Rust backend.
The command is constructed as follows:
magick <input> \
-define quantum:format=floating-point \
-colorspace RGB \
-auto-gamma \
-evaluate Multiply <hdr_value> \
-evaluate Pow 0.9 \
-colorspace sRGB \
-depth 16 \
-profile 2020_profile.icc \
<output>
Pipeline Steps:
- Floating-point Conversion:
-define quantum:format=floating-point -colorspace RGBconverts the image to a high-precision RGB colorspace to prevent clipping during brightness adjustments. - Gamma Correction:
-auto-gammaadjusts the image gamma. - Brightness Multiplication:
-evaluate Multiply <hdr_value>multiplies the brightness by the user-selected HDR value. - Power Curve Adjustment:
-evaluate Pow 0.9applies a power curve adjustment. - sRGB Conversion:
-colorspace sRGB -depth 16converts the image back to the sRGB colorspace with a 16-bit depth. - Profile Application:
-profile 2020_profile.iccapplies the Rec. 2020 color profile required for HDR display.
Sources: README.md:24-30, src/main.rs:88-105
Frontend
The frontend is a single-page application built with vanilla HTML, CSS, and JavaScript. It manages the user interface, handles file uploads, and communicates with the backend API.
Sources: README.md:48, static/index.html, static/script.js
UI Components
The main UI components are defined in static/index.html and styled in static/style.css.
| Element ID | Description |
|---|---|
uploadArea | The drag-and-drop area for uploading images. |
imageInput | The hidden file input field. |
imageDisplay | Container for the processed image. |
resultImage | The <img> tag that displays the original and processed images. |
processingOverlay | A spinner overlay shown during processing. |
controls | The section containing the slider and buttons, visible after upload. |
hdrSlider | The range input for adjusting the HDR intensity (0.5 to 3.0). |
resetButton | Button to reset the interface to its initial state. |
downloadButton | A link to download the processed image. |
Sources: static/index.html:22-51, static/style.css:61-200
Client-Side Logic (HDRify class)
All frontend logic is encapsulated within the HDRify class in static/script.js.
Key Responsibilities:
- Event Handling: Manages click, drag-and-drop, and keyboard events for file uploads and controls.
- State Management: Transitions the UI between the initial upload view, the processing state, and the final result view.
- API Communication: Sends the image data to the
/uploadendpoint usingfetch. - Client-Side Caching: Stores processed images in a
Map(this.imageCache) to avoid re-processing when the slider is adjusted to a previously used value. This provides an instant preview.
Sources: static/script.js:1-389
The following sequence diagram shows the flow from file upload to displaying the processed image.
This diagram illustrates the user interaction flow, from uploading a file to receiving and displaying the HDR-processed image, including the client-side state transitions.
Sources: static/script.js:151-300