{"id":30327365,"url":"https://github.com/howbizarre/add-stamp","last_synced_at":"2026-04-11T05:35:55.192Z","repository":{"id":305856603,"uuid":"1024160607","full_name":"howbizarre/add-stamp","owner":"howbizarre","description":"A Nuxt 4 application that allows users to apply watermarks to bunch of images using WebAssembly (WASM) for high-performance image processing. And use Cloudlfare Worker as BaaS.","archived":false,"fork":false,"pushed_at":"2025-08-14T11:56:13.000Z","size":1166,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-14T12:30:30.139Z","etag":null,"topics":["baas","batch-processing","browser","cloudflare-workers","image-processing","images","nuxt","nuxt4","rust","stamp","tailwindcss","typescript","vue","vue3","wasn","watermark","webassembly","wrangler"],"latest_commit_sha":null,"homepage":"https://stamp.bizarre.how/","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/howbizarre.png","metadata":{"files":{"readme":"README-WASM.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-22T09:18:04.000Z","updated_at":"2025-08-14T11:56:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"c5de7bba-062a-4bac-98f3-b6e92c5e2ab8","html_url":"https://github.com/howbizarre/add-stamp","commit_stats":null,"previous_names":["howbizarre/add-stamp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/howbizarre/add-stamp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howbizarre%2Fadd-stamp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howbizarre%2Fadd-stamp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howbizarre%2Fadd-stamp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howbizarre%2Fadd-stamp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/howbizarre","download_url":"https://codeload.github.com/howbizarre/add-stamp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howbizarre%2Fadd-stamp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270928208,"owners_count":24669480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["baas","batch-processing","browser","cloudflare-workers","image-processing","images","nuxt","nuxt4","rust","stamp","tailwindcss","typescript","vue","vue3","wasn","watermark","webassembly","wrangler"],"created_at":"2025-08-18T00:36:02.882Z","updated_at":"2025-12-30T21:44:03.247Z","avatar_url":"https://github.com/howbizarre.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WASM Image Processing Module\n\nThis document covers the WebAssembly (WASM) module implementation for high-performance image watermarking using Rust. The WASM module provides the core image processing capabilities for the Image Watermarking App.\n\n## Overview\n\nThe WASM module is built with Rust and compiled to WebAssembly to provide near-native performance for image processing operations in the browser. It handles:\n\n- **Image Loading**: Support for PNG, JPEG, and WebP formats\n- **Watermark Processing**: PNG stamp application with transparency\n- **Text Rendering**: Font-based text watermarks with custom fonts\n- **Image Scaling**: Smart scaling algorithms with aspect ratio preservation\n- **Export**: WebP output with configurable quality settings\n\n## Rust Dependencies\n\nThe module uses several high-quality Rust crates for image processing:\n\n```toml\n[dependencies]\nwasm-bindgen = \"0.2\"           # WebAssembly bindings\nimage = \"0.24\"                 # Core image processing\nimageproc = \"0.23\"             # Advanced image operations\nrusttype = \"0.9\"               # Font rendering\nconsole_error_panic_hook = \"0.1\" # Error handling\nweb-sys = \"0.3\"                # Web API bindings\n```\n\n### Key Features\n\n- **`image` crate**: Handles multiple image formats (PNG, JPEG, WebP)\n- **`imageproc`**: Provides advanced drawing and text rendering\n- **`rusttype`**: TrueType font rendering for text watermarks\n- **`wasm-bindgen`**: Seamless Rust-JavaScript interoperability\n\n## Prerequisites for WASM Development\n\n### Required Tools\n\n1. **Rust Toolchain** (stable version recommended)\n   ```bash\n   # Install Rust using rustup\n   curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n   source ~/.cargo/env\n   ```\n\n2. **wasm-pack** (WebAssembly build tool)\n   ```bash\n   # Install wasm-pack\n   cargo install wasm-pack\n   ```\n\n3. **wasm32-unknown-unknown target**\n   ```bash\n   # Add WebAssembly target\n   rustup target add wasm32-unknown-unknown\n   ```\n\n### Verifying Installation\n\n```bash\n# Check Rust version\nrustc --version\n\n# Check Cargo version  \ncargo --version\n\n# Check wasm-pack version\nwasm-pack --version\n\n# Verify WebAssembly target\nrustup target list --installed | grep wasm32\n```\n\n## Building the WASM Module\n\n### Quick Build Commands\n\n```bash\n# Build WASM module for web target\nnpm run build:wasm\n\n# Clean previous build artifacts\nnpm run clean:wasm\n\n# Copy built files to public directory\nnpm run copy:wasm\n```\n\n### Manual Build Process\n\n```bash\n# Navigate to WASM directory\ncd wasm\n\n# Build with wasm-pack (web target)\nwasm-pack build --target web --out-dir pkg --out-name image_stamper\n\n# Copy to public directory (Windows)\nxcopy /Y /E pkg\\* ..\\public\\wasm\\\n\n# Copy to public directory (Unix/Linux/macOS)\ncp -r pkg/* ../public/wasm/\n```\n\n### Build Configuration\n\nThe `Cargo.toml` file is configured for WASM compilation:\n\n```toml\n[package]\nname = \"image-stamper\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]  # Dynamic library for WASM\n\n[dependencies]\n# Core WASM bindings\nwasm-bindgen = \"0.2\"\n\n# Image processing with optimized features\nimage = { \n    version = \"0.24\", \n    default-features = false, \n    features = [\"png\", \"jpeg\", \"webp\"] \n}\n\n# Advanced image operations\nimageproc = \"0.23\"\n\n# Font rendering\nrusttype = \"0.9\"\n\n# Error handling\nconsole_error_panic_hook = \"0.1\"\n\n# Web APIs\nweb-sys = { version = \"0.3\", features = [\"console\", \"File\", \"FileReader\", \"Blob\"] }\n```\n\n## WASM Module Architecture\n\n### Core Components\n\n#### ImageStamper Struct\nThe main WASM interface provides methods for image processing:\n\n```rust\n#[wasm_bindgen]\npub struct ImageStamper {\n    stamp_data: Vec\u003cu8\u003e,      // Cached stamp image data\n    stamp_width: u32,         // Stamp dimensions\n    stamp_height: u32,\n}\n```\n\n#### Key Methods\n\n1. **`new()`** - Initialize the ImageStamper instance\n2. **`set_stamp(stamp_bytes: \u0026[u8])`** - Load and cache watermark image\n3. **`process_image(image_bytes: \u0026[u8], opacity: f32)`** - Apply watermark to image\n4. **`add_text_watermark(...)`** - Add text-based watermarks\n\n### Processing Pipeline\n\n1. **Input Validation**: Verify image format and dimensions\n2. **Image Decoding**: Convert bytes to internal image representation\n3. **Stamp Processing**: Scale and position watermark appropriately\n4. **Composition**: Blend watermark with original image using opacity\n5. **Export**: Encode result as WebP with optimal compression\n\n### Performance Optimizations\n\n- **Memory Pooling**: Reuse allocated buffers for batch processing\n- **SIMD Operations**: Leverage vectorized instructions where available\n- **Minimal Allocations**: Direct buffer manipulation to reduce GC pressure\n- **Streaming**: Process large images in chunks to manage memory usage\n\n## Integration with JavaScript\n\n### Loading the WASM Module\n\n```javascript\nimport init, { ImageStamper } from './wasm/image_stamper.js';\n\n// Initialize WASM module\nawait init();\n\n// Create processor instance\nconst stamper = new ImageStamper();\n```\n\n### Processing Images\n\n```javascript\n// Set watermark once\nawait stamper.set_stamp(stampImageBytes);\n\n// Process multiple images\nfor (const imageFile of images) {\n    const imageBytes = new Uint8Array(await imageFile.arrayBuffer());\n    const result = stamper.process_image(imageBytes, 0.5); // 50% opacity\n    // result is Uint8Array containing WebP data\n}\n```\n\n## WASM Technical Implementation\n\n### Image Processing Algorithms\n\n#### Watermark Scaling Strategy\nThe module uses a \"contain\" scaling approach that:\n- Calculates optimal scale to fit watermark within image bounds\n- Maintains aspect ratio to prevent distortion\n- Applies padding to ensure proper positioning\n- Centers the watermark for balanced composition\n\n#### Opacity Blending\n```rust\n// Alpha blending formula implementation\nlet alpha = stamp_alpha * opacity;\nlet inv_alpha = 1.0 - alpha;\n\nresult_pixel = (original_pixel * inv_alpha) + (stamp_pixel * alpha);\n```\n\n#### Memory Management\n- **Stack Allocation**: Use stack memory for small buffers\n- **Heap Optimization**: Minimize heap allocations in hot paths\n- **Buffer Reuse**: Cache intermediate results for batch operations\n- **Zero-Copy**: Direct memory access where possible\n\n### Font System Integration\n\nThe module includes embedded Ubuntu font for consistent text rendering:\n\n```rust\n// Load embedded font data\nconst UBUNTU_FONT: \u0026[u8] = include_bytes!(\"Ubuntu-M.ttf\");\n\n// Dynamic font sizing based on image dimensions\nlet font_size = (image_width.min(image_height) as f32 * 0.05).max(12.0);\n```\n\n### Error Handling\n\nComprehensive error handling for production use:\n\n```rust\n#[wasm_bindgen]\npub fn process_image(\u0026self, image_bytes: \u0026[u8], opacity: f32) -\u003e Result\u003cVec\u003cu8\u003e, JsValue\u003e {\n    // Input validation\n    if image_bytes.is_empty() {\n        return Err(JsValue::from_str(\"Empty image data\"));\n    }\n    \n    if !(0.0..=1.0).contains(\u0026opacity) {\n        return Err(JsValue::from_str(\"Opacity must be between 0.0 and 1.0\"));\n    }\n    \n    // Processing with error propagation\n    let img = image::load_from_memory(image_bytes)\n        .map_err(|e| JsValue::from_str(\u0026format!(\"Image decode error: {}\", e)))?;\n    \n    // ... processing logic\n}\n```\n\n## WASM Module File Structure\n\n```\nwasm/\n├── Cargo.toml                 # Rust package configuration\n├── Cargo.lock                 # Dependency lock file\n├── Ubuntu-M.ttf              # Embedded font for text watermarks\n├── src/\n│   └── lib.rs                 # Main WASM module implementation\n├── pkg/                       # Generated WASM build output\n│   ├── image_stamper.js       # JavaScript bindings\n│   ├── image_stamper.d.ts     # TypeScript definitions\n│   ├── image_stamper_bg.wasm  # Compiled WebAssembly binary\n│   ├── image_stamper_bg.wasm.d.ts  # WASM type definitions\n│   └── package.json           # NPM package metadata\n└── target/                    # Rust build artifacts\n    ├── wasm32-unknown-unknown/  # WebAssembly target build\n    └── debug/                   # Debug build artifacts\n```\n\n### Generated Files\n\nAfter building, the following files are copied to `public/wasm/`:\n\n- **`image_stamper.js`** - ES module with WASM loader and bindings\n- **`image_stamper.d.ts`** - TypeScript type definitions\n- **`image_stamper_bg.wasm`** - Compiled WebAssembly binary\n- **`image_stamper_bg.wasm.d.ts`** - Additional type definitions\n- **`package.json`** - Package metadata for the generated module\n\n## Development Workflow\n\n### 1. Modify Rust Code\nEdit files in `wasm/src/` directory:\n```bash\n# Main implementation\nvim wasm/src/lib.rs\n```\n\n### 2. Build and Test\n```bash\n# Build WASM module\nnpm run build:wasm\n\n# Test in development\nnpm run dev\n```\n\n### 3. Debug WASM Issues\n```bash\n# Enable debug logging in Rust\nconsole_log!(\"Debug message: {}\", value);\n\n# Check browser console for WASM errors\n# Use browser dev tools to inspect WASM module\n```\n\n### 4. Performance Profiling\n- Use browser dev tools Performance tab\n- Monitor WASM memory usage\n- Profile JavaScript ↔ WASM boundary crossings\n- Optimize hot paths identified in profiling\n\n## Troubleshooting WASM Issues\n\n### Common Build Problems\n\n#### 1. wasm-pack Not Found\n```bash\n# Error: command not found: wasm-pack\n# Solution: Install wasm-pack\ncargo install wasm-pack\n```\n\n#### 2. Missing WebAssembly Target\n```bash\n# Error: target 'wasm32-unknown-unknown' not found\n# Solution: Add WebAssembly target\nrustup target add wasm32-unknown-unknown\n```\n\n#### 3. Build Fails with Dependency Errors\n```bash\n# Clean and rebuild\ncargo clean\nnpm run clean:wasm\nnpm run build:wasm\n```\n\n#### 4. WASM Files Not Found in Public Directory\n```bash\n# Ensure files are copied correctly\nnpm run copy:wasm\n\n# Check if files exist\nls public/wasm/\n```\n\n### Runtime Issues\n\n#### 1. WASM Module Failed to Load\n- Check browser console for detailed error messages\n- Verify WASM files are accessible via network tab\n- Ensure proper MIME type for `.wasm` files\n\n#### 2. Memory Allocation Errors\n```rust\n// Add panic hook for better error messages\n#[wasm_bindgen]\npub fn init_panic_hook() {\n    console_error_panic_hook::set_once();\n}\n```\n\n#### 3. Performance Issues\n- Profile using browser dev tools\n- Check for excessive memory allocations\n- Verify batch processing is working correctly\n\n### Debug Logging\n\nEnable detailed logging in the WASM module:\n\n```rust\n// Add debug output\nconsole_log!(\"Processing image: {}x{}\", width, height);\nconsole_log!(\"Stamp size: {}x{}\", stamp_width, stamp_height);\n```\n\n### Browser Compatibility\n\n- **Chrome/Edge**: Full support for WASM and File System Access API\n- **Firefox**: WASM support, limited File System Access API\n- **Safari**: WASM support, no File System Access API\n\n## Performance Benchmarks\n\nTypical processing times on modern hardware:\n\n- **1MP image**: ~50-100ms\n- **5MP image**: ~200-400ms  \n- **10MP image**: ~500-800ms\n\nMemory usage scales linearly with image size:\n- **1MP image**: ~4MB peak memory\n- **5MP image**: ~20MB peak memory\n- **10MP image**: ~40MB peak memory\n\n## Contributing to WASM Module\n\n### Code Style\n- Follow Rust standard formatting (`cargo fmt`)\n- Use `clippy` for linting (`cargo clippy`)\n- Add documentation for public APIs\n- Include error handling for all operations\n\n### Testing\n```bash\n# Run Rust tests\ncd wasm\ncargo test\n\n# Build and test integration\nnpm run build:wasm \u0026\u0026 npm run dev\n```\n\n### Adding New Features\n1. Implement in `wasm/src/lib.rs`\n2. Add appropriate `#[wasm_bindgen]` annotations\n3. Update TypeScript definitions if needed\n4. Test integration with frontend\n5. Update documentation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowbizarre%2Fadd-stamp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhowbizarre%2Fadd-stamp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowbizarre%2Fadd-stamp/lists"}