react-image-utilities
Version:
A React component library for image manipulation: cropping, compressing, resizing, format conversion, and effects
329 lines (258 loc) • 8.95 kB
Markdown
# React Image Utilities
A powerful and flexible React component library for image manipulation, providing a comprehensive suite of tools for cropping, compressing, resizing, format conversion, and applying visual effects to images in your web applications.
## 🚀 Features
- **📏 Image Cropping**: Interactive cropping with resizable crop area and aspect ratio control
- **🗜️ Image Compression**: Smart compression with quality control and size limits
- **↔️ Image Resizing**: Flexible resizing with multiple modes and aspect ratio preservation
- **🔄 Format Conversion**: Convert between popular image formats (JPEG, PNG, WebP, GIF)
- **✨ Visual Effects**: Apply professional-grade effects and filters
- **📱 Responsive**: Works seamlessly across different screen sizes
- **🔒 Type-Safe**: Written in TypeScript with full type definitions
- **🎨 Customizable**: Extensive styling and configuration options
## 📦 Installation
```bash
npm install react-image-utilities
# or
yarn add react-image-utilities
# or
pnpm add react-image-utilities
```
## 💻 Usage
### Image Cropping
```tsx
import { ImageCrop } from 'react-image-utilities';
function App() {
const handleCropComplete = (croppedBlob: Blob) => {
const url = URL.createObjectURL(croppedBlob);
console.log('Cropped image URL:', url);
};
return (
<ImageCrop
image="/path/to/image.jpg" // Can be a File, Blob, or URL string
width={300}
height={200}
aspectRatio={1.5}
allowResize={true}
showGrid={true}
onProcessingComplete={handleCropComplete}
onError={(error) => console.error('Crop error:', error)}
/>
);
}
```
### Image Compression
```tsx
import { ImageCompress } from 'react-image-utilities';
function App() {
const handleCompressionComplete = (compressedBlob: Blob) => {
console.log('Compressed size:', compressedBlob.size);
};
return (
<ImageCompress
image="/path/to/image.jpg"
quality={75}
maxSizeMB={1}
showProgress={true}
onCompressProgress={(progress) => console.log(`${progress}%`)}
onProcessingComplete={handleCompressionComplete}
onError={(error) => console.error('Compression error:', error)}
/>
);
}
```
### Image Resizing
```tsx
import { ImageResize } from 'react-image-utilities';
function App() {
return (
<ImageResize
image="/path/to/image.jpg"
width={800}
height={600}
maintainAspectRatio={true}
resizeMode="contain"
onProcessingComplete={(resizedBlob) => {
console.log('Resized image:', resizedBlob);
}}
/>
);
}
```
### Format Conversion
```tsx
import { ImageFormat } from 'react-image-utilities';
function App() {
return (
<ImageFormat
image="/path/to/image.jpg"
format="webp"
quality={80}
onProcessingComplete={(convertedBlob) => {
console.log('Converted image:', convertedBlob);
}}
/>
);
}
```
### Visual Effects
```tsx
import { ImageEffects } from 'react-image-utilities';
function App() {
return (
<ImageEffects
image="/path/to/image.jpg"
effect="grayscale"
intensity={75}
onProcessingComplete={(processedBlob) => {
console.log('Processed image:', processedBlob);
}}
/>
);
}
```
## 📚 API Reference
### Common Props
All components share these base props:
| Prop | Type | Description |
|------|------|-------------|
| `image` | `File \| Blob \| string` | The source image (File, Blob, or URL) |
| `onProcessingComplete` | `(processedImage: Blob) => void` | Callback with processed image |
| `onError` | `(error: Error) => void` | Error handling callback |
| `className` | `string` | CSS class name |
| `style` | `React.CSSProperties` | Inline styles |
| `validateInput` | `boolean` | Enable input validation |
| `onValidationError` | `(error: ValidationError) => void` | Validation error callback |
### ImageCrop
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `width` | `number` | Required | Crop area width |
| `height` | `number` | Required | Crop area height |
| `aspectRatio` | `number` | `undefined` | Lock aspect ratio |
| `allowResize` | `boolean` | `true` | Enable resize handles |
| `showGrid` | `boolean` | `true` | Show grid overlay |
| `gridColor` | `string` | `'rgba(255,255,255,0.8)'` | Grid line color |
### ImageCompress
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `quality` | `number` | `80` | Compression quality (0-100) |
| `maxSizeMB` | `number` | `undefined` | Max file size in MB |
| `showProgress` | `boolean` | `true` | Show progress bar |
| `onCompressProgress` | `(progress: number) => void` | `undefined` | Progress callback |
### ImageResize
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `width` | `number` | Required | Target width |
| `height` | `number` | Required | Target height |
| `maintainAspectRatio` | `boolean` | `true` | Preserve aspect ratio |
| `resizeMode` | `'contain' \| 'cover' \| 'stretch'` | `'contain'` | Resize behavior |
### ImageFormat
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `format` | `'jpeg' \| 'png' \| 'webp' \| 'gif'` | Required | Target format |
| `quality` | `number` | `80` | Output quality |
### ImageEffects
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `effect` | `EffectType` | Required | Effect to apply |
| `intensity` | `number` | `100` | Effect strength |
| `blurRadius` | `number` | `undefined` | Blur amount |
## 🔧 Error Handling
### Error Types
```typescript
type ImageProcessingErrorType =
| 'INVALID_INPUT'
| 'UNSUPPORTED_FORMAT'
| 'COMPRESSION_FAILED'
| 'RESIZE_FAILED'
| 'FORMAT_CONVERSION_FAILED'
| 'EFFECT_APPLICATION_FAILED';
```
### Example with Error Handling
```tsx
import { ImageCompress, ValidationError } from 'react-image-utilities';
function App() {
return (
<ImageCompress
image={imageFile}
quality={75}
validateInput={true}
onError={(error) => {
if (error.type === 'COMPRESSION_FAILED') {
console.error('Compression failed:', error.message);
}
}}
onValidationError={(error) => {
console.error('Validation failed:', error.message);
}}
retryOnError={true}
maxRetries={3}
/>
);
}
```
## 🌐 Browser Compatibility
### Feature Detection
```tsx
import { checkBrowserSupport } from 'react-image-utilities';
const support = checkBrowserSupport();
if (!support.webp) {
console.warn('WebP format not supported');
}
```
### Minimum Browser Versions
- Chrome: 79+
- Firefox: 73+
- Safari: 14+
- Edge: 79+
## ⚡ Performance Considerations
1. **Image Size Limits**
- Recommended max input image size: 20MB
- For larger images, use compression first
- Consider using Web Workers for heavy processing
2. **Memory Usage**
- Images are processed in chunks when possible
- Large images are automatically downscaled during preview
- Resources are properly cleaned up after processing
3. **Processing Time**
- Compression: ~100ms - 2s depending on size
- Resizing: ~50ms - 1s depending on dimensions
- Effects: ~50ms - 500ms depending on complexity
## 🔍 Troubleshooting
### Common Issues
1. **Image Not Loading**
- Check if the image URL is accessible
- Verify CORS settings for remote images
- Ensure the image format is supported
2. **Processing Errors**
- Check browser console for detailed error messages
- Verify input image dimensions and format
- Ensure sufficient memory is available
3. **Performance Issues**
- Reduce input image size
- Lower quality settings for faster processing
- Use Web Workers for heavy operations
## 🤝 Contributing
We welcome contributions! Please follow these steps:
1. Fork the repository
2. Create a feature branch
3. Commit your changes
4. Push to the branch
5. Open a Pull Request
### Development Setup
```bash
# Clone the repository
git clone https://github.com/yourusername/react-image-utilities.git
# Install dependencies
npm install
# Start development server
npm run dev
# Run tests
npm test
```
## 📄 License
MIT © [Your Name]
---
## 🙋 Support
- Documentation: [https://github.com/yourusername/react-image-utilities](https://github.com/yourusername/react-image-utilities)
- Issues: [https://github.com/yourusername/react-image-utilities/issues](https://github.com/yourusername/react-image-utilities/issues)
- Discord: [Join our community](https://discord.gg/yourdiscord)