Please bookmark this page to avoid losing your image tool!

Image Palette Knife 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.
function processImage(originalImg, strokeSize = 20, strokeRatio = 0.4, strokeCountFactor = 10) {
    const canvas = document.createElement('canvas');
    const w = originalImg.width;
    const h = originalImg.height;

    // Handle cases where image might not be loaded or has zero dimensions
    if (w === 0 || h === 0) {
        canvas.width = w; // Potentially 0
        canvas.height = h; // Potentially 0
        // For a 0x0 canvas, nothing can be meaningfully drawn.
        return canvas;
    }
    
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');

    // Create a temporary canvas to get image data from the originalImg
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = w;
    tempCanvas.height = h;
    const tempCtx = tempCanvas.getContext('2d');
    tempCtx.drawImage(originalImg, 0, 0, w, h);
    
    let originalImageData;
    try {
        // This can throw a security error if the image is cross-origin and the canvas becomes tainted
        originalImageData = tempCtx.getImageData(0, 0, w, h);
    } catch (e) {
        console.error("Error getting image data (likely cross-origin issue): ", e);
        // Draw an error message on the canvas
        ctx.fillStyle = '#CCCCCC'; // Light grey background
        ctx.fillRect(0, 0, w, h);
        ctx.fillStyle = 'red';
        // Adjust font size based on canvas size for better visibility
        const fontSize = Math.max(12, Math.min(w, h) / 20); 
        ctx.font = `${fontSize}px Arial`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        const errorMessage1 = "Error processing image.";
        const errorMessage2 = e.name === 'SecurityError' ? "Image may be cross-origin." : "Details in console.";
        
        ctx.fillText(errorMessage1, w / 2, h / 2 - fontSize / 2);
        ctx.fillText(errorMessage2, w / 2, h / 2 + fontSize / 2 + 5); // +5 for line spacing
        return canvas;
    }
    
    const originalPixels = originalImageData.data;

    // Fill the canvas with white. Palette knife strokes are opaque and will cover this.
    // This ensures areas with few strokes still have a defined background.
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, w, h);

    // Sanitize input parameters to ensure they are reasonable
    const safeStrokeSize = Math.max(1, strokeSize);
    const safeStrokeRatio = Math.max(0.01, Math.min(10, strokeRatio)); // Ratio usually between 0.1 and 1
    const safeStrokeCountFactor = Math.max(0, strokeCountFactor);

    // Calculate the number of strokes to draw
    // Average area of a single stroke
    const avgStrokeActualLength = safeStrokeSize; // Using safeStrokeSize as the primary dimension reference
    const avgStrokeActualWidth = avgStrokeActualLength * safeStrokeRatio;
    const avgStrokeArea = avgStrokeActualLength * avgStrokeActualWidth;
    
    let numStrokes;
    if (avgStrokeArea <= 0) { // Should not happen with safe parameters, but as a fallback
        numStrokes = safeStrokeCountFactor > 0 ? 1 : 0;
    } else {
        const baseStrokesForFullCoverage = (w * h) / avgStrokeArea;
        numStrokes = Math.floor(baseStrokesForFullCoverage * safeStrokeCountFactor);
    }
    

    // If strokeCountFactor is positive but numStrokes calculation resulted in 0 (e.g., very large strokesize for small image),
    // ensure at least one stroke is drawn to show some effect.
    if (safeStrokeCountFactor > 0 && numStrokes === 0) {
        numStrokes = 1;
    }

    for (let i = 0; i < numStrokes; i++) {
        // Pick a random central point for the stroke
        const randX = Math.random() * w;
        const randY = Math.random() * h;

        // Determine the color for the stroke by sampling the original image at the stroke's center
        // Clamp coordinates to be within image bounds for pixel sampling
        const pickX = Math.min(Math.floor(randX), w - 1);
        const pickY = Math.min(Math.floor(randY), h - 1);
        
        const pixelIndex = (pickY * w + pickX) * 4; // Each pixel has 4 components (R,G,B,A)
        const r = originalPixels[pixelIndex];
        const g = originalPixels[pixelIndex + 1];
        const b = originalPixels[pixelIndex + 2];
        // Alpha component (originalPixels[pixelIndex + 3]) is ignored for opaque palette knife strokes
        const color = `rgb(${r}, ${g}, ${b})`;

        // Randomize stroke dimensions around the reference size and ratio
        // Length varies from 0.75x to 1.25x of safeStrokeSize
        const currentLength = safeStrokeSize * (0.75 + Math.random() * 0.5); 
        // Width is based on this length and strokeRatio, also with variation
        const currentWidth = currentLength * safeStrokeRatio * (0.75 + Math.random() * 0.5); 
        
        // Ensure minimum dimensions for visibility
        const finalLength = Math.max(1, currentLength);
        const finalWidth = Math.max(1, currentWidth);

        // Randomize stroke angle (0 to PI radians, as rectangles are symmetrical over 180 degrees)
        const angle = Math.random() * Math.PI;

        // Draw the stroke (a rotated rectangle)
        ctx.save(); // Save current canvas state
        ctx.translate(randX, randY); // Move canvas origin to the stroke's center
        ctx.rotate(angle); // Rotate the canvas for the stroke
        ctx.fillStyle = color; // Set the stroke color
        // Draw the rectangle centered around the (now translated and rotated) origin
        ctx.fillRect(-finalLength / 2, -finalWidth / 2, finalLength, finalWidth);
        ctx.restore(); // Restore canvas state to before this stroke
    }

    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 Image Palette Knife Filter Effect Tool allows users to apply a unique artistic effect to their images, simulating the appearance of palette knife strokes. This tool is particularly useful for artists, designers, and anyone looking to transform their digital images into stylized artworks. Typical use cases include creating visuals for social media, enhancing photos for creative projects, or generating unique textures for digital illustrations. Users can customize parameters such as stroke size, stroke ratio, and the number of strokes to tailor the effect to their liking, resulting in a diverse range of visual outcomes.

Leave a Reply

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