ප්‍රධාන අන්තර්ගතයට පනින්න

Image Processing

Bandwidth සහ storage පිරිවැය අඩු කිරීමට upload කිරීමට පෙර client-side images process කරන්න.

Image Compression

import { useDropup } from '@samithahansaka/dropup';
import { compressImage } from '@samithahansaka/dropup/image';

function CompressedUploader() {
const { files, actions, getDropProps, getInputProps } = useDropup({
accept: 'image/*',
upload: { url: '/api/upload' },

// Upload කිරීමට පෙර ගොනු process කරන්න
onFilesAdded: async (newFiles) => {
for (const file of newFiles) {
// Image එක compress කරන්න
const compressed = await compressImage(file.file, {
maxWidth: 1920,
maxHeight: 1080,
quality: 0.8,
});

// Compressed version එකෙන් ප්‍රතිස්ථාපනය කරන්න
actions.updateFileMeta(file.id, {
originalSize: file.size,
compressedFile: compressed,
});
}
},
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>Upload කිරීමට පෙර images compress වේ</p>
</div>
);
}

Compression Options

interface CompressOptions {
// උපරිම dimensions (aspect ratio පවත්වයි)
maxWidth?: number; // පෙරනිමි: 1920
maxHeight?: number; // පෙරනිමි: 1080

// Quality (0-1)
quality?: number; // පෙරනිමි: 0.8

// Output format
type?: 'image/jpeg' | 'image/png' | 'image/webp'; // පෙරනිමි: මුල් type
}

// උදාහරණ
await compressImage(file, { quality: 0.6 }); // අඩු quality
await compressImage(file, { maxWidth: 800, maxHeight: 600 }); // කුඩා ප්‍රමාණය
await compressImage(file, { type: 'image/webp' }); // WebP වෙත පරිවර්තනය

Preview සමඟ Compression

import { useDropup } from '@samithahansaka/dropup';
import { compressImage } from '@samithahansaka/dropup/image';
import { useState } from 'react';

function PreviewWithCompression() {
const [compressionStats, setCompressionStats] = useState<Map<string, {
original: number;
compressed: number;
}>>(new Map());

const { files, actions, getDropProps, getInputProps } = useDropup({
accept: 'image/*',

onFilesAdded: async (newFiles) => {
for (const file of newFiles) {
const compressed = await compressImage(file.file, {
maxWidth: 1200,
quality: 0.75,
});

setCompressionStats(prev => new Map(prev).set(file.id, {
original: file.size,
compressed: compressed.size,
}));

// Upload සඳහා compressed ගොනුව ගබඩා කරන්න
actions.updateFileMeta(file.id, { compressedFile: compressed });
}
},
});

const formatSize = (bytes: number) => {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
};

return (
<div>
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>Compress කිරීමට images දමන්න</p>
</div>

<div style={styles.grid}>
{files.map(file => {
const stats = compressionStats.get(file.id);
const savings = stats
? ((1 - stats.compressed / stats.original) * 100).toFixed(0)
: 0;

return (
<div key={file.id} style={styles.card}>
{file.preview && (
<img src={file.preview} alt="" style={styles.preview} />
)}
<p>{file.name}</p>
{stats && (
<p style={styles.stats}>
{formatSize(stats.original)}{formatSize(stats.compressed)}
<span style={styles.savings}> (-{savings}%)</span>
</p>
)}
</div>
);
})}
</div>
</div>
);
}

const styles = {
dropzone: {
border: '2px dashed #ccc',
borderRadius: 8,
padding: 40,
textAlign: 'center' as const,
marginBottom: 20,
},
grid: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
gap: 16,
},
card: {
border: '1px solid #eee',
borderRadius: 8,
padding: 12,
},
preview: {
width: '100%',
height: 150,
objectFit: 'cover' as const,
borderRadius: 4,
},
stats: {
fontSize: 12,
color: '#666',
},
savings: {
color: '#4caf50',
fontWeight: 'bold',
},
};

Image Resizing

import { resizeImage } from '@samithahansaka/dropup/image';

// නිශ්චිත dimensions වෙත resize කරන්න
const resized = await resizeImage(file, {
width: 300,
height: 300,
mode: 'cover', // 'cover' | 'contain' | 'fill'
});

// Thumbnail සාදන්න
const thumbnail = await resizeImage(file, {
width: 150,
height: 150,
mode: 'cover',
});

Resize Modes

Modeවිස්තරය
coverසම්පූර්ණ area පුරවයි, crop විය හැක
containArea තුළ ගැළපේ, හිස් ඉඩ තිබිය හැක
fillපුරවීමට stretch කරයි (විකෘති විය හැක)

EXIF Orientation Fix

සමහර cameras EXIF rotation data සමඟ images save කරයි. Display කිරීමට පෙර orientation නිවැරදි කරන්න:

import { fixOrientation } from '@samithahansaka/dropup/image';

const corrected = await fixOrientation(file);

Crop Image

import { cropImage } from '@samithahansaka/dropup/image';

const cropped = await cropImage(file, {
x: 100, // ආරම්භ X
y: 50, // ආරම්භ Y
width: 400, // Crop width
height: 400, // Crop height
});

Image Editor Component

import { useDropup } from '@samithahansaka/dropup';
import { compressImage, cropImage } from '@samithahansaka/dropup/image';
import { useState, useRef } from 'react';

function ImageEditor() {
const [selectedFile, setSelectedFile] = useState<DropupFile | null>(null);
const [cropArea, setCropArea] = useState({ x: 0, y: 0, width: 200, height: 200 });

const { files, actions, getDropProps, getInputProps } = useDropup({
accept: 'image/*',
maxFiles: 1,
multiple: false,
});

const handleCrop = async () => {
if (!selectedFile) return;

const cropped = await cropImage(selectedFile.file, cropArea);

// මුල් එකෙන් cropped version ප්‍රතිස්ථාපනය කරන්න
actions.updateFileMeta(selectedFile.id, {
processedFile: cropped,
});
};

const handleCompress = async () => {
if (!selectedFile) return;

const compressed = await compressImage(selectedFile.file, {
quality: 0.7,
});

actions.updateFileMeta(selectedFile.id, {
processedFile: compressed,
});
};

return (
<div style={styles.container}>
{files.length === 0 ? (
<div {...getDropProps()} style={styles.dropzone}>
<input {...getInputProps()} />
<p>Edit කිරීමට image එකක් දමන්න</p>
</div>
) : (
<div style={styles.editor}>
<div style={styles.preview}>
<img
src={files[0].preview}
alt=""
style={styles.image}
onClick={() => setSelectedFile(files[0])}
/>
</div>

<div style={styles.tools}>
<h4>Tools</h4>
<button onClick={handleCrop}>Crop</button>
<button onClick={handleCompress}>Compress</button>
<button onClick={() => actions.reset()}>ඉවත් කරන්න</button>
</div>
</div>
)}
</div>
);
}

const styles = {
container: {
maxWidth: 600,
margin: '0 auto',
},
dropzone: {
border: '2px dashed #ccc',
borderRadius: 8,
padding: 60,
textAlign: 'center' as const,
},
editor: {
display: 'flex',
gap: 20,
},
preview: {
flex: 1,
},
image: {
maxWidth: '100%',
borderRadius: 8,
},
tools: {
width: 150,
display: 'flex',
flexDirection: 'column' as const,
gap: 8,
},
};

Convert Image Format

import { convertImage } from '@samithahansaka/dropup/image';

// කුඩා ගොනු ප්‍රමාණය සඳහා WebP වෙත පරිවර්තනය කරන්න
const webp = await convertImage(file, 'image/webp');

// JPEG වෙත පරිවර්තනය කරන්න
const jpeg = await convertImage(file, 'image/jpeg', { quality: 0.9 });

// PNG වෙත පරිවර්තනය කරන්න (lossless)
const png = await convertImage(file, 'image/png');

Get Image Metadata

import { getImageMetadata } from '@samithahansaka/dropup/image';

const metadata = await getImageMetadata(file);
console.log(metadata);
// {
// width: 1920,
// height: 1080,
// aspectRatio: 1.78,
// orientation: 1, // EXIF orientation
// hasAlpha: false,
// format: 'image/jpeg',
// }

Pipeline Processing

බහු operations chain කරන්න:

import {
compressImage,
fixOrientation,
resizeImage,
} from '@samithahansaka/dropup/image';

async function processImage(file: File): Promise<File> {
let processed = file;

// පියවර 1: Orientation නිවැරදි කරන්න
processed = await fixOrientation(processed);

// පියවර 2: ඉතා විශාල නම් resize කරන්න
const metadata = await getImageMetadata(processed);
if (metadata.width > 2000 || metadata.height > 2000) {
processed = await resizeImage(processed, {
maxWidth: 2000,
maxHeight: 2000,
});
}

// පියවර 3: Compress කරන්න
processed = await compressImage(processed, {
quality: 0.8,
type: 'image/webp',
});

return processed;
}

// Uploader එක සමඟ භාවිතා කරන්න
const { files } = useDropup({
accept: 'image/*',
onFilesAdded: async (newFiles) => {
for (const file of newFiles) {
const processed = await processImage(file.file);
actions.updateFileMeta(file.id, { processedFile: processed });
}
},
});

Browser Support

Image processing Canvas API භාවිතා කරන අතර සියලුම නවීන browsers වල සහය දක්වයි:

FeatureChromeFirefoxSafariEdge
Resize/Crop
JPEG/PNG
WebP14+
EXIF Fix