Please bookmark this page to avoid losing your image tool!

Photo Graflex Speed Graphic Filter Effect Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, contrast = 50, brightness = -10, grainAmount = 25, vignetteStrength = 0.4) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can hint the browser to optimize for frequent getImageData/putImageData calls.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Handle cases where image dimensions are not available or are zero.
    if (imgWidth === 0 || imgHeight === 0) {
        console.error("Image dimensions are zero. Image might not be loaded or is invalid.");
        // Ensure canvas has at least 1x1 dimension to be drawable.
        canvas.width = Math.max(1, imgWidth);
        canvas.height = Math.max(1, imgHeight);
        ctx.fillStyle = "#7f7f7f"; // Gray background for the placeholder
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // If dimensions were indeed 0,0, add a small text.
        if (imgWidth === 0 || imgHeight === 0) {
             ctx.fillStyle = "white";
             ctx.font = "bold 8px Arial";
             ctx.textAlign = "center";
             ctx.textBaseline = "middle";
             ctx.fillText("N/A", canvas.width / 2, canvas.height / 2);
        }
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    } catch (e) {
        // This can happen due to a tainted canvas (e.g., cross-origin image loaded without CORS headers)
        console.error("Could not get image data: ", e);
        // Fallback: draw an error message on the canvas.
        ctx.clearRect(0, 0, imgWidth, imgHeight); 
        ctx.fillStyle = "rgba(0,0,0,0.7)"; // Dark overlay
        ctx.fillRect(0, 0, imgWidth, imgHeight);
        ctx.fillStyle = "white";
        const fontSize = Math.max(12, Math.min(24, imgWidth / 20, imgHeight / 10)); // Adaptive font size
        ctx.font = `bold ${fontSize}px Arial`;
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText("Error: Could not process image.", imgWidth / 2, imgHeight / 2 - fontSize * 0.6);
        ctx.font = `${fontSize * 0.8}px Arial`;
        ctx.fillText("(May be a cross-origin image issue)", imgWidth / 2, imgHeight / 2 + fontSize * 0.6);
        return canvas;
    }
    
    const data = imageData.data;

    // Pre-calculate contrast factor.
    // The typical contrast formula: Factor = (259 * (level + 255)) / (255 * (259 - level))
    // 'contrast' parameter (e.g. -100 to 100) is used as 'level'.
    // A value of 0 means factor=1 (no change). Positive values increase contrast.
    const contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast));

    const centerX = imgWidth / 2;
    const centerY = imgHeight / 2;
    // Max distance from center to a corner, used for vignette normalization.
    const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);

    function clamp(value, min = 0, max = 255) {
        return Math.max(min, Math.min(max, value));
    }

    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        // Alpha (data[i+3]) is preserved.

        // 1. Convert to Grayscale (Luminosity method for perceptual accuracy)
        let gray = 0.299 * r + 0.587 * g + 0.114 * b;

        // 2. Apply Brightness adjustment
        gray += brightness;
        gray = clamp(gray); 
        
        // 3. Apply Contrast adjustment
        // Formula: NewColor = Factor * (OldColor - Midpoint) + Midpoint
        // Midpoint for 0-255 range is 128.
        gray = contrastFactor * (gray - 128) + 128;
        gray = clamp(gray); 
        
        // 4. Add Film Grain / Noise
        if (grainAmount > 0) {
            // Generate noise: a random value between -grainAmount and +grainAmount.
            const noise = (Math.random() * 2 - 1) * grainAmount;
            gray += noise;
            gray = clamp(gray); 
        }

        // 5. Apply Vignette effect
        // vignetteStrength: 0 means no vignette, 1.0 means edges are black.
        if (vignetteStrength > 0 && maxDist > 0) { // maxDist > 0 avoids division by zero for 1x1px or smaller.
            // Current pixel's coordinates
            const x = (i / 4) % imgWidth;
            const y = Math.floor((i / 4) / imgWidth);
            
            // Distance of current pixel from the center
            const dx = x - centerX;
            const dy = y - centerY;
            const dist = Math.sqrt(dx * dx + dy * dy);
            
            // Normalized distance (0 at center, typically 1 at corners)
            const normalizedDist = dist / maxDist; 
            
            // Vignette effect factor (0.0 to 1.0). Multiplied with pixel brightness.
            // Factor of 1.0 means no change; 0.0 means black.
            // (1.0 - normalizedDist * vignetteStrength):
            // - At center (normalizedDist=0), factor is 1.0.
            // - At maxDist (normalizedDist=1), factor is (1.0 - vignetteStrength).
            //   e.g., if vignetteStrength = 0.4, factor at edge is 0.6.
            const vignetteMultiplier = clamp(1.0 - (normalizedDist * vignetteStrength), 0.0, 1.0); 
            gray *= vignetteMultiplier;
            gray = clamp(gray); // Clamp again after vignette multiplication
        }
        
        // Update pixel data with the new grayscale value
        data[i] = gray;     // Red channel
        data[i + 1] = gray; // Green channel
        data[i + 2] = gray; // Blue channel
        // data[i+3] (alpha) remains unchanged.
    }

    ctx.putImageData(imageData, 0, 0);
    return canvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Photo Graflex Speed Graphic Filter Effect Tool allows users to apply a vintage film-like filter to their images. By adjusting parameters such as contrast, brightness, grain amount, and vignette strength, users can transform their photos to achieve a distinctive retro aesthetic reminiscent of classic photography styles. This tool is suitable for enhancing personal photographs, creating artistic images for social media, or adding a unique visual effect to digital artworks.

Leave a Reply

Your email address will not be published. Required fields are marked *

Other Image Tools:

Image Konica Hexar AF Filter Effect Application

Image Ricoh GR Film Camera Filter Effect Application

Image Kodak Disposable Camera Filter Effect

Image Hoya Pro ND Filter Effect Application

Image Wratten #12 Yellow Filter Effect Tool

Image AGFA APX 100 Film Filter Effect Tool

Image Singh-Ray Vari-ND Filter Effect Application

Image Rollei RPX 25 Film Filter Effect Tool

Image 35mm Half-frame Camera Filter Effect

Image Kodak Vision3 250D Motion Picture Film Effect Filter

Image 120 Film Format Filter Effect

Image Lens Whacking Filter Effect Tool

Image Black and White Red Filter Effect Tool

Image Lee Medium Stopper 6-Stop ND Filter Effect Tool

Image Nikon F3 Film Camera Render Effect Tool

Image Polaroid Spectra Filter Effect Tool

Image Contax T2/T3 Filter Effect Application

Image Bronica ETRS Medium Format Filter Effect Application

Image Soap Bubble Bokeh Effect Generator

Image Center Graduated ND Filter Effect Tool

Image Breakthrough Photography X4 ND Filter Effect

Photo Filter Effect Creator for Yashica T4 Point-and-Shoot

Image AGFA APX 25 Film Filter Effect Tool

Image Singh-Ray Gold-N-Blue Polarizer Effect Tool

Image Black and White Blue Filter Effect Tool

Image Pinhole Solargraphy Effect Creator

Image Kodak Vision3 500T Motion Picture Film Effect Simulator

Image Soft Focus Filter Effect for Nikon Nikkor

Image Bergger Pancro 400 Film Filter Effect Tool

Image Agfa Optima Filter Effect Application

Image Technicolor 3-Strip Process Filter Effect

Image Cyanotype Process Filter Effect

Image Black and White with Orange #21 Filter Effect Tool

Image Bleach Bypass Effect Filter

Image IMAX Camera Filter Effect Tool

Image Super 8 Film Filter Effect Tool

See All →