Skip to content

ParsaBordbar/d2d-docsToDark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

36 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Docs To Dark (D2D)

image

Transform your PDFs and images into dark mode with a simple API! No more disconfort for your eyes when studying!

What is D2D?

D2D (Docs to Dark) is a FastAPI-based web service that inverts the colors of PDFs and images, converting them to dark mode. Perfect for reading documents at night or reducing eye strain!

✨ Features

  • πŸ“„ PDF Support: Convert entire PDF documents to dark mode
  • πŸ–ΌοΈ Image Support: PNG, JPG, JPEG, BMP, WEBP, TIFF, and GIF formats
  • 🎨 Themes: Pick how darkness looks β€” hue (color-preserving), invert (classic), dim, sepia, midnight
  • πŸš€ Fast Processing: Built on FastAPI; blocking conversion runs in a threadpool so the server stays responsive
  • πŸ“€ Multiple Upload Options: Upload single files, batches, or via URL
  • πŸ–₯️ CLI: Convert from the terminal with an interactive theme picker β€” no server needed 5904623981329846147
  • 🧹 Auto Cleanup: Background scheduler removes old files automatically
  • πŸ’Ύ Easy Downloads: Get your converted files instantly

Example

959f3251-0a6c-4b3b-8f8f-3f8d4d4a872e 6cd83707-5af6-4ae0-a5f0-2dbb5386cab8_959f3251-0a6c-4b3b-8f8f-3f8d4d4a872e_dark

🎨 Themes

Every conversion takes an optional theme (default: hue). Pure inversion turns colored content into its complement (red β†’ cyan); hue instead inverts only lightness, so colors stay recognizable in dark mode.

Theme What it does
hue Inverts lightness, preserves hue/saturation (default)
invert Classic negative, maximum contrast
dim Softer blacks/whites, easier on the eyes
sepia Warm-toned dark background
midnight Cool blue-tinted dark

GET /themes returns the live list and the default.

Prerequisites

  • Python 3.10 or higher (required by numpy)
  • pip or uv (Python package manager)
  • Poppler (for PDF processing)

Installing Poppler

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install poppler-utils

macOS:

brew install poppler

Windows: Download from poppler for Windows and add to PATH.

Installation

  1. Clone the repository:
git clone https://github.com/yourusername/D2D.git
cd D2D
  1. Set up the environment and install dependencies:

Using uv (fast, recommended):

cd server
uv venv
uv pip install -r requirements.txt

With uv, prefix run commands with uv run and skip manual activation.

Or classic venv + pip:

cd server
python -m venv venv
source venv/bin/activate          # Windows: venv\Scripts\activate
pip install -r requirements.txt

Dependencies (including numpy, used for the theme transforms) are pinned in server/requirements.txt. Poppler must still be installed system-wide (see above).

Running the Application

Start the server with:

cd server
uvicorn app:app --reload --host 0.0.0.0 --port 1313

The API will be available at http://localhost:1313

Or run with docker-compose!

cd server
docker compose up --build

πŸ–₯️ Command-line (no server)

Convert files straight from the terminal. Runs the same conversion engine as the API.

cd server
python cli.py document.pdf            # interactive theme picker (↑/↓, enter)
python cli.py photo.jpg -t sepia      # pick a theme, skip the picker
python cli.py photo.png -o out.png    # choose the output path
python cli.py *.png --theme dim       # batch convert

With uv: uv run python cli.py document.pdf.

When no -t/--theme is given and you're in a real terminal, an interactive picker appears (arrow keys or j/k, enter to select, q to quit). Piped/non-interactive runs fall back to the default theme. Output files get a _dark suffix unless -o is set.

Frontend (client)

A React + Vite UI lives in client/. It supports drag-and-drop, multi-file upload, URL upload, and a theme selector that applies to the next conversion.

cd client
npm install
npm run dev

The client reads the API base URL from VITE_API_BASE_URL (client/.env, defaults to http://localhost:1313).

Configuration (server env vars)

Variable Default Purpose
ALLOWED_ORIGINS * Comma-separated CORS origins
CLEANUP_INTERVAL_SECONDS 900 How often the cleanup scheduler runs
FILE_MAX_AGE_SECONDS 3600 Age after which uploaded/converted files are deleted

πŸ“– API Documentation

Once the server is running, visit:

  • Interactive API Docs: http://localhost:1313/docs
  • Alternative Docs: http://localhost:1313/redoc

Supported formats: PDF, and images PNG, JPG, JPEG, BMP, WEBP, TIFF, GIF.

πŸ”Œ API Endpoints

1. Root Endpoint

GET /

Returns service information.

Themes

GET /themes

Returns the available themes and the default:

{ "themes": ["invert", "hue", "dim", "sepia", "midnight"], "default": "hue" }

2. Upload File

POST /upload/

Upload a single PDF or image file for conversion. Optional theme form field (default hue); an unknown theme returns 400.

Example using curl:

curl -X POST "http://localhost:1313/upload/" \
  -H "accept: application/json" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/your/document.pdf" \
  -F "theme=sepia"

Response:

{
  "download_url": "/download/filename_dark.pdf"
}

3. Batch Upload

POST /batch/

Convert multiple files in one request. Returns a per-file result list (each item is a success with download_url or an error). Optional theme form field applies to all files.

Example using curl:

curl -X POST "http://localhost:1313/batch/" \
  -F "files=@/path/to/a.pdf" \
  -F "files=@/path/to/b.png" \
  -F "theme=midnight"

Response:

{
  "results": [
    { "filename": "a.pdf", "download_url": "/download/..._dark.pdf" },
    { "filename": "b.png", "download_url": "/download/..._dark.png" }
  ]
}

4. Upload from URL

POST /upload-url/?file=<url>&theme=<theme>

Provide a URL (as the file query parameter) to a PDF or image for conversion. Optional theme query parameter (default hue).

Example:

curl -X POST "http://localhost:1313/upload-url/?file=https://example.com/document.pdf&theme=dim"

5. Download File

GET /download/{filename}

Download your converted dark mode file.

Example:

curl -O "http://localhost:1313/download/filename_dark.pdf"

Usage Example

Python Example:

import requests

# Upload a file
with open('document.pdf', 'rb') as f:
    files = {'file': f}
    response = requests.post('http://localhost:1313/upload/', files=files)
    download_url = response.json()['download_url']

# Download the converted file
converted = requests.get(f'http://localhost:1313{download_url}')
with open('document_dark.pdf', 'wb') as f:
    f.write(converted.content)

JavaScript/Node.js Example:

const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');

const form = new FormData();
form.append('file', fs.createReadStream('document.pdf'));

axios.post('http://localhost:1313/upload/', form, {
    headers: form.getHeaders()
})
.then(response => {
    console.log('Download URL:', response.data.download_url);
})
.catch(error => {
    console.error('Error:', error);
});

Project Structure

D2D/
β”œβ”€β”€ server/                 # FastAPI backend
β”‚   β”œβ”€β”€ app.py              # routes + orchestration
β”‚   β”œβ”€β”€ invertor.py         # image/PDF processing + theme registry
β”‚   β”œβ”€β”€ helpers.py          # extension/mime helpers
β”‚   β”œβ”€β”€ cli.py              # terminal version (interactive theme picker)
β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── uploads/            # ephemeral, auto-cleaned (gitignored)
└── client/                 # React + Vite + Tailwind frontend
    └── src/
        β”œβ”€β”€ components/Uploader/   # drag-and-drop UI + theme selector
        β”œβ”€β”€ hooks/useUpload.ts     # upload state + conversion
        └── api/upload.ts          # network layer

Notes To Consider

  • Uploaded files are stored temporarily in the uploads/ directory
  • A background scheduler deletes files older than FILE_MAX_AGE_SECONDS (default 1 hour); tune via env vars
  • Large PDFs may take longer to process
  • Ensure adequate disk space for temporary file storage

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is open source and available under the MIT License.

Troubleshooting

Issue: "Poppler not found"

  • Make sure Poppler is installed and accessible in your system PATH

Issue: "Module not found"

  • Ensure all dependencies are installed: pip install -r requirements.txt

Issue: "Permission denied on uploads/"

  • Check folder permissions: chmod 755 uploads/

πŸ’‘ Future Enhancements

  • Batch processing support
  • Support for more file formats
  • File cleanup scheduler
  • Theme presets (hue-preserving, sepia, dim, midnight)
  • Command-line interface
  • Adjustable brightness/contrast knobs
  • Async jobs + progress for very large PDFs
  • Preview before download

Contact

For questions or support, please open an issue on GitHub.


Made with ❀️ for flow students and readers! Have fun!

About

Transform your PDFs and images into dark modeI! No more discomfort for your eyes when studying!

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages