Please bookmark this page to avoid losing your image tool!

Image Compression 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, qualityStr = "0.7", mimeType = "image/jpeg", maxWidthStr = "", maxHeightStr = "") {
    // 1. Validating originalImg
    // An Image object must be fully loaded (originalImg.complete === true) and have valid dimensions
    // (naturalWidth > 0) before it can be reliably used for drawing or dimension calculations.
    if (!originalImg || typeof originalImg.naturalWidth === "undefined" || !originalImg.complete || originalImg.naturalWidth === 0) {
        console.error("Original image is not loaded, invalid, or has zero dimensions.");
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 1; 
        errorCanvas.height = 1;
        const ctx_err = errorCanvas.getContext('2d');
        if (ctx_err) {
             ctx_err.fillStyle = '#FF0000'; // Red
             ctx_err.fillRect(0, 0, 1, 1);
        }
        return errorCanvas;
    }

    // 2. Parameter parsing
    let qualitySetting = parseFloat(qualityStr);
    if (isNaN(qualitySetting) || qualitySetting < 0 || qualitySetting > 1) {
        // Default quality if input is invalid
        qualitySetting = 0.7;
    }

    // mimeType is passed as a string with a default value ("image/jpeg"). No special parsing needed for it.

    let maxWidthConstraint = originalImg.naturalWidth; // Default to original image width
    if (maxWidthStr !== "") {
        const parsedMaxWidth = parseInt(maxWidthStr, 10);
        if (!isNaN(parsedMaxWidth) && parsedMaxWidth > 0) {
            maxWidthConstraint = parsedMaxWidth;
        }
    }

    let maxHeightConstraint = originalImg.naturalHeight; // Default to original image height
    if (maxHeightStr !== "") {
        const parsedMaxHeight = parseInt(maxHeightStr, 10);
        if (!isNaN(parsedMaxHeight) && parsedMaxHeight > 0) {
            maxHeightConstraint = parsedMaxHeight;
        }
    }

    // 3. Calculate scaled dimensions (maintaining aspect ratio, fitting into constraints)
    // Start with original dimensions
    let scaledWidth = originalImg.naturalWidth;
    let scaledHeight = originalImg.naturalHeight;
    const aspectRatio = originalImg.naturalWidth / originalImg.naturalHeight;

    // Apply maxWidthConstraint
    if (scaledWidth > maxWidthConstraint) {
        scaledWidth = maxWidthConstraint;
        scaledHeight = scaledWidth / aspectRatio;
    }

    // Apply maxHeightConstraint (to potentially already scaled dimensions)
    if (scaledHeight > maxHeightConstraint) {
        scaledHeight = maxHeightConstraint;
        scaledWidth = scaledHeight * aspectRatio;
    }
    
    // Dimensions must be integers and at least 1x1 pixel
    scaledWidth = Math.max(1, Math.round(scaledWidth));
    scaledHeight = Math.max(1, Math.round(scaledHeight));

    // 4. Create a temporary canvas and draw the (potentially scaled) image onto it
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = scaledWidth;
    tempCanvas.height = scaledHeight;
    const tempCtx = tempCanvas.getContext('2d');

    if (!tempCtx) {
        console.error("Failed to get 2D context from temporary canvas. This browser might not support Canvas properly.");
        // Fallback: return a minimal error canvas
        const errorCanvas = document.createElement('canvas'); errorCanvas.width=1; errorCanvas.height=1; return errorCanvas;
    }
    tempCtx.drawImage(originalImg, 0, 0, scaledWidth, scaledHeight);

    // 5. Generate compressed image data URL from the temporary canvas
    // The `qualitySetting` is used here for JPEG/WebP. It's ignored for PNG.
    let activeMimeType = mimeType; // Use a mutable variable for mimeType in case of fallback
    let compressedDataURL;
    try {
        compressedDataURL = tempCanvas.toDataURL(activeMimeType, qualitySetting);
    } catch (e) {
        // This can happen if the mimeType is not supported (e.g., 'image/webp' on an old browser)
        // or if qualitySetting causes issues (less common).
        console.warn(`Could not use mimeType "${activeMimeType}" with quality ${qualitySetting}. Error: ${e.message}. Falling back to "image/png".`);
        activeMimeType = 'image/png'; // Fallback to PNG
        compressedDataURL = tempCanvas.toDataURL(activeMimeType); // Quality is ignored for PNG by toDataURL
    }

    // 6. Load the compressed image data URL into a new Image object
    // This step effectively "applies" the compression specified by toDataURL into an image format.
    // The resulting `compressedImage` will have the new dimensions and encoded image data.
    const compressedImage = new Image();
    
    const imageLoadPromise = new Promise((resolve, reject) => {
        compressedImage.onload = () => resolve(compressedImage);
        // It's crucial to handle onerror during data URL loading.
        // Very long data URLs (e.g., from huge canvases) can sometimes cause issues.
        compressedImage.onerror = (errEvent) => {
            // errEvent is an Event object, not an Error. A generic error is more useful.
            console.error("Error loading image from data URL:", errEvent);
            reject(new Error("Failed to load image from data URL. The data URL might be malformed or too long for the browser to handle."));
        };
        compressedImage.src = compressedDataURL;
    });

    let loadedCompressedImage;
    try {
        loadedCompressedImage = await imageLoadPromise;
    } catch (err) {
        console.warn("Failed to reload image from data URL. Error: ", err.message, ". Returning the resized canvas; explicit quality compression might not be applied if data URL processing failed.");
        // Fallback: return the tempCanvas. It contains the resized image.
        // This is still a form of compression if resizing occurred.
        return tempCanvas;
    }

    // 7. Create the final output canvas and draw the (now data-URL-processed) compressed image onto it.
    // The finalCanvas will have dimensions matching the loadedCompressedImage (which should be scaledWidth/Height).
    const finalCanvas = document.createElement('canvas');
    finalCanvas.width = loadedCompressedImage.width; 
    finalCanvas.height = loadedCompressedImage.height; 
    
    const finalCtx = finalCanvas.getContext('2d');
    if (!finalCtx) {
        console.error("Failed to get 2D context from final canvas.");
        // Fallback: return tempCanvas, as it's better than nothing.
        return tempCanvas; 
    }
    finalCtx.drawImage(loadedCompressedImage, 0, 0);

    // 8. Return the final canvas. This canvas displays the compressed image.
    return finalCanvas;
}

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 Compression Tool allows users to reduce the file size of images while maintaining quality. It supports various image formats such as JPEG and PNG and enables users to specify compression quality and maximum dimensions. This tool is useful for web developers and graphic designers who need to optimize images for faster loading times on websites and to save storage space without sacrificing visual quality.

Leave a Reply

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