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 Image (2.5 MB)
Compress

Compressed Image (500 KB)
Installation
Install dependencies
1npm install pixel-craft --saveCopy 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 name | Type | Required | Default | Description |
|---|---|---|---|---|
imageURL | String | No | -- | URL to the external image to compress. |
imagePath | String | No | -- | Path to local or public image (e.g., /image/sample.jpg). Ignored if imageUrl is provide. |
targetSize | number | Yes | -- | 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)=>void | No | -- | 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
onCompressednull-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/ Issue | Cause | User's Measures/ Fixes |
|---|---|---|
| Image not displaying / compression not working | imageUrl or imagePath is missing or invalid | Ensure 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-Origin | Use 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/path | Check the URL/path in the browser to confirm it's accessible. |
| Blank or corrupted output image | Canvas can't render the image due to format or loading error | Use standard image formats like JPEG or PNG. Avoid SVGs or unsupported types. |
| Infinite loop or performance drop | Compression loop has no exit if blob size doesn't reduce much | Ensure the target size is realistically achievable (avoid too-small targets for large images). |
| Unexpected image quality | Compression aggressively reduces quality to meet size | Choose 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.
| Techniques | Benefits |
|---|---|
| Resize dimensions before compression | Reduces 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 compression | Break up compression steps using setTimeout or to prevent UI freezing. |
Allow custom minQuality minQuality or or props | control over compression aggressiveness. |