Feature Overview
Relevant source files
The following files were used as context for generating this wiki page:HDRify is a minimalist web application designed to convert standard dynamic range (SDR) images into high dynamic range (HDR) images. The application provides a simple user interface for uploading an image and adjusting the HDR intensity in real-time. The core functionality is powered by a Rust backend that uses the ImageMagick command-line tool for image processing, based on the technique described on sharpletters.net.
The system is composed of a vanilla HTML/CSS/JS frontend and a warp-based Rust backend. It is designed to be fast, responsive, and intuitive, with features like drag-and-drop uploads, real-time previews, and smooth UI transitions. The primary use case is creating "eye-searing" images with enhanced brightness that stand out on HDR-compatible displays, such as for Slack emoji.
Sources: README.md:3-5, 36-38, static/index.html:11-17
System Architecture
The application follows a client-server architecture. The frontend is responsible for all user interactions and rendering, while the backend handles the computationally intensive image processing. An external dependency, ImageMagick, is orchestrated by the backend to perform the actual HDR conversion.
This diagram illustrates the high-level components and their interactions.
Sources: README.md:36-38, src/main.rs, static/script.js
Frontend
The frontend is built with vanilla HTML, CSS, and JavaScript, focusing on a modern, responsive user experience. It manages the UI state, user input, and communication with the backend.
Sources: README.md:37, static/index.html, static/script.js
UI Components
The user interface is defined in index.html and consists of several key interactive elements.
| Element ID | Tag | Description |
|---|---|---|
uploadArea | <div> | The main drag-and-drop area and click-to-upload button. |
imageInput | <input type=file> | The hidden file input triggered by the uploadArea. Accepts JPEG, PNG, and WebP formats. |
imageDisplay | <div> | Container for the processed image and the processing overlay. |
resultImage | <img> | Displays the original image preview and the final processed HDR image. |
processingOverlay | <div> | A visual indicator with a spinner shown during image processing. |
controls | <section> | A container for the HDR slider and action buttons that appears after an image is uploaded. |
hdrSlider | <input type=range> | A slider to control the HDR intensity from 0.5 to 3.0. |
hdrValue | <span> | Displays the current numerical value of the HDR slider. |
downloadButton | <a> | A button to download the processed HDR image. |
resetButton | <button> | A button to reset the interface to its initial state. |
error | <div> | A container to display error messages to the user. |
Sources: static/index.html:19-61
Client-Side Logic
All client-side logic is encapsulated within the HDRify class in script.js. This class manages the application's state, event listeners, and API interactions.
Key Features:
- File Handling: The
handleFilemethod validates the uploaded file's type and size (max 10MB). It then uses aFileReaderto read the image as a Base64-encoded data URL. - State Transitions: The UI smoothly transitions between the upload view and the image processing view using CSS opacity and display changes. The
transitionToImageViewmethod manages this. - Real-time Processing: An
inputevent listener on thehdrSlidertriggers theprocessImagemethod. A 250ms debounce (setTimeout) prevents excessive API calls while the user is dragging the slider. - API Communication: The
processImagemethod sends aPOSTrequest to the/uploadendpoint with the Base64 image data and the current HDR value asapplication/x-www-form-urlencodeddata. - Caching: A
MapnamedimageCachestores the results of processed images for each HDR value. This prevents re-processing when the user adjusts the slider back to a previously selected value, providing an instant preview. - Error Handling: The
showErrorandhideErrormethods display and hide a dedicated error area. Network errors and server-side errors are caught and displayed to the user.
The following diagram shows the sequence of events on the client side when a user uploads and adjusts an image.
Sources: static/script.js:1-360
Backend
The backend is a lightweight Rust application using the warp web server framework. Its sole purpose is to serve the static frontend files and provide a single API endpoint for image processing.
Sources: src/main.rs, Cargo.toml
API Endpoint: POST /upload
The backend exposes one endpoint to handle image processing requests. Note that the implementation in src/main.rs uses /upload, while the README.md refers to /api/process. The code-defined endpoint is authoritative.
- Method:
POST - Path:
/upload - Request Body:
application/x-www-form-urlencoded
| Parameter | Type | Description |
|---|---|---|
image | string | The Base64-encoded image data (without the prefix). |
hdr_value | float | The desired HDR intensity level (e.g., 1.5). |
- Response Body:
application/json
The server responds with a JSON object defined by the ProcessResponse struct.
// Source: src/main.rs:6-11
#[derive(Debug, Serialize)]
struct ProcessResponse {
success: bool,
message: String,
image_data: Option<String>, // base64 encoded HDR image
}
Request Handling Logic
The handle_upload async function in src/main.rs contains the core backend logic. The flow is as follows:
Sources: src/main.rs:13-143
Image Processing Pipeline
The backend uses std::process::Command to execute the ImageMagick magick command-line tool. The arguments are precisely ordered to achieve the desired HDR effect, applying a Rec. 2020 color profile.
The pipeline steps are:
- Set quantum format to
floating-point. - Convert colorspace to
RGB. - Apply
auto-gammacorrection. - Multiply brightness by the user-provided
hdr_value. - Apply a power curve adjustment of
0.9. - Convert colorspace back to
sRGB. - Set bit depth to
16. - Apply the
2020_profile.icccolor profile.
Sources: src/main.rs:90-107, README.md:25-31
Backend Dependencies
The project's dependencies are managed in Cargo.toml.
| Crate | Version | Purpose |
|---|---|---|
warp | 0.3 | Web server framework. |
tokio | 1.0 | Asynchronous runtime. |
serde | 1.0 | Serialization/deserialization framework. |
serde_json | 1.0 | JSON support for serde. |
base64 | 0.21 | Base64 encoding and decoding. |
tempfile | 3.0 | Creating temporary files for ImageMagick input/output. |
Sources: Cargo.toml:7-15
End-to-End Data Flow
This sequence diagram illustrates the complete process from a user uploading a file to receiving the processed HDR image.
Sources: static/script.js:230-276, src/main.rs:13-143
Conclusion
The hdrify application is a well-defined, single-purpose tool that demonstrates a modern web stack using a lightweight Rust backend and a dependency-free JavaScript frontend. It effectively orchestrates an external command-line tool (ImageMagick) to perform a complex image manipulation task, exposing it to the user through a simple and responsive web interface. The architecture is clean, with a clear separation of concerns between the client-side presentation layer and the server-side processing logic.
Sources: README.md, src/main.rs, static/script.js