Image Compressor

The ImageCompressor component compresses a given image (from a URL or local/public path) to a desired target file size. It's ideal for image optimization before uploading or sharing, ensuring reduced bandwidth without significant quality loss.

Original

Original Image (2.5 MB)

Compress

Compressed

Compressed Image (500 KB)

Installation

Install dependencies

1npm install pixel-craft --save

Copy the source code

components/ImageCompressor.tsx

1import React, { useEffect, useState } from 'react';
2
3type Unit = 'KB' | 'MB';
4
5interface ImageCompressorProps {
6  imageUrl?: string;       // External image URL
7  imagePath?: string;      // Local/public path to image
8  targetSize: number;      // Target size value
9  unit?: Unit;             // KB or MB
10  onCompressed?: (compressedDataUrl: string, blob: Blob) => void;
11}
12
13const ImageCompressor: React.FC<ImageCompressorProps> = ({
14  imageUrl,
15  imagePath,
16  targetSize,
17  unit = 'KB',
18  onCompressed,
19}) => {
20  const [compressedUrl, setCompressedUrl] = useState<string | null>(null);
21
22  useEffect(() => {
23    const finalImageSource = imageUrl || imagePath;
24    if (!finalImageSource) return;
25
26    const compressImage = async () => {
27      const img = new Image();
28      img.crossOrigin = 'anonymous';
29      img.src = finalImageSource;
30
31      const targetBytes = unit === 'MB' ? targetSize * 1024 * 1024 : targetSize * 1024;
32
33      img.onload = () => {
34        const canvas = document.createElement('canvas');
35        const ctx = canvas.getContext('2d');
36        if (!ctx) return;
37
38        canvas.width = img.width;
39        canvas.height = img.height;
40        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
41
42        let quality = 0.92;
43        let dataUrl = canvas.toDataURL('image/jpeg', quality);
44        let blob = dataURLToBlob(dataUrl);
45
46        const compressLoop = () => {
47          dataUrl = canvas.toDataURL('image/jpeg', quality);
48          blob = dataURLToBlob(dataUrl);
49
50          if (blob.size <= targetBytes || quality <= 0.1) {
51            setCompressedUrl(dataUrl);
52            onCompressed?.(dataUrl, blob);
53            return;
54          }
55
56          quality -= 0.05;
57          compressLoop();
58        };
59
60        compressLoop();
61      };
62
63      img.onerror = () => {
64        console.error('Failed to load image.');
65      };
66    };
67
68    compressImage();
69  }, [imageUrl, imagePath, targetSize, unit, onCompressed]);
70
71  const dataURLToBlob = (dataUrl: string): Blob => {
72    const byteString = atob(dataUrl.split(',')[1]);
73    const mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
74    const ab = new ArrayBuffer(byteString.length);
75    const ia = new Uint8Array(ab);
76    for (let i = 0; i < byteString.length; i++) {
77      ia[i] = byteString.charCodeAt(i);
78    }
79    return new Blob([ab], { type: mimeString });
80  };
81
82  return (
83    <div>
84      {compressedUrl ? (
85        <div>
86          <p>Compressed Image:</p>
87          <img src={compressedUrl} alt="Compressed" style={{ maxWidth: '100%' }} />
88        </div>
89      ) : (
90        <p>Compressing image...</p>
91      )}
92    </div>
93  );
94};
95
96export default ImageCompressor;

Props

Prop nameTypeRequiredDefaultDescription
imageURLStringNo
--
URL to the external image to compress.
imagePathStringNo
--
Path to local or public image (e.g., /image/sample.jpg). Ignored if imageUrl is provide.
targetSizenumberYes
--
The desired size of the compressed image (in KB or MB, depending on unit)
unit'KB' | 'MB'No
'KB'
Unit to measure the target size.
onCompressed(compressedDataUrl:string, blob:Blob)=>voidNo
--
Callback invoke once compression completes with the data URL and Blob of the image.

Additional Suggestions for Users

Common Issues

  • Prevalidate the image URL or path before passing it to avoid unnecessary component render cycles
  • Add error handling logic in parent components to notify users if compression fails (e.g., try/catch wrappers or onCompressed null-checks).
  • Avoid unrealistic target sizes—compression is limited by minimum quality and image dimensions.
  • Consider adjusting the quality step or allowing it as a prop for fine control.
  • For local/public images, ensure they are placed inside the /public directory of your React app.

Possible Errors and User Measures

Error/ IssueCauseUser's Measures/ Fixes
Image not displaying / compression not workingimageUrl or imagePath is missing or invalidEnsure one valid prop is passed: either imageUrl (with CORS enabled) or imageUrl (public path from public/).
CORS-related error (Image from another domain)The external image doesn't have proper CORS headers Access-Control-Allow-OriginUse images with CORS headers or host images on a server with proper CORS config.
Browser console logs: “Failed to load image.”Invalid or unreachable image URL/pathCheck the URL/path in the browser to confirm it's accessible.
Blank or corrupted output imageCanvas can't render the image due to format or loading errorUse standard image formats like JPEG or PNG. Avoid SVGs or unsupported types.
Infinite loop or performance dropCompression loop has no exit if blob size doesn't reduce muchEnsure the target size is realistically achievable (avoid too-small targets for large images).
Unexpected image qualityCompression aggressively reduces quality to meet sizeChoose a reasonable targetSize (e.g., not below 50 KB for large images). Optionally adjust logic to clamp quality degradation.

Real World Uses

CMS or blog editor

Automatically reduce image sizes before saving media content to avoid bloated page loads.

Social media post editor

Limit image size before sharing content to speed up uploads and optimize mobile performance.

Chat or messaging apps

Compress images before sending in chat to avoid large payloads.

E-commerce platforms

Reduce the size of product images dynamically for faster customer-facing rendering.

Image Optimization Techniques

Image Formats & Compression

Use modern image formats like WebP and AVIF for better compression and quality. Implement proper image compression to reduce file sizes.

TechniquesBenefits
Resize dimensions before compressionReduces pixel data before compression, allowing higher visual quality at smaller sizes.
Use WebP instead of JPEG (if browser supports it)WebP often provides better compression ratios with similar quality.
Async chunked compressionBreak up compression steps using setTimeout or Access-Control-Allow-Origin to prevent UI freezing.
Allow custom minQuality minQuality or or stepprops   control over compression aggressiveness.