feat: compress png

This commit is contained in:
Ibrahima G. Coulibaly 2025-02-23 14:45:10 +00:00
commit 99492b4ab3
4 changed files with 133 additions and 0 deletions

View file

@ -0,0 +1,6 @@
import { expect, describe, it } from 'vitest';
// import { } from './service';
//
// describe('compress-png', () => {
//
// })

View file

@ -0,0 +1,113 @@
import { Box } from '@mui/material';
import React, { useState } from 'react';
import * as Yup from 'yup';
import ToolFileInput from '@components/input/ToolFileInput';
import ToolFileResult from '@components/result/ToolFileResult';
import ToolOptions from '@components/options/ToolOptions';
import TextFieldWithDesc from 'components/options/TextFieldWithDesc';
import ToolInputAndResult from '@components/ToolInputAndResult';
import imageCompression from 'browser-image-compression';
import Typography from '@mui/material/Typography';
const initialValues = {
rate: '50'
};
const validationSchema = Yup.object({
// splitSeparator: Yup.string().required('The separator is required')
});
export default function ChangeColorsInPng() {
const [input, setInput] = useState<File | null>(null);
const [result, setResult] = useState<File | null>(null);
const [originalSize, setOriginalSize] = useState<number | null>(null); // Store original file size
const [compressedSize, setCompressedSize] = useState<number | null>(null); // Store compressed file size
const compressImage = async (file: File, rate: number) => {
if (!file) return;
// Set original file size
setOriginalSize(file.size);
const options = {
maxSizeMB: 1, // Maximum size in MB
maxWidthOrHeight: 1024, // Maximum width or height
quality: rate / 100, // Convert percentage to decimal (e.g., 50% becomes 0.5)
useWebWorker: true
};
try {
const compressedFile = await imageCompression(file, options);
setResult(compressedFile);
setCompressedSize(compressedFile.size); // Set compressed file size
} catch (error) {
console.error('Error during compression:', error);
}
};
const compute = (optionsValues: typeof initialValues, input: any) => {
if (!input) return;
const { rate } = optionsValues;
compressImage(input, Number(rate)); // Pass the rate as a number
};
return (
<Box>
<ToolInputAndResult
input={
<ToolFileInput
value={input}
onChange={setInput}
accept={['image/png']}
title={'Input PNG'}
/>
}
result={
<ToolFileResult
title={'Compressed PNG'}
value={result}
extension={'png'}
/>
}
/>
<ToolOptions
compute={compute}
getGroups={({ values, updateField }) => [
{
title: 'Compression options',
component: (
<Box>
<TextFieldWithDesc
value={values.rate}
onOwnChange={(val) => updateField('rate', val)}
description={'Compression rate (1-100)'}
/>
</Box>
)
},
{
title: 'File sizes',
component: (
<Box>
<Box>
{originalSize !== null && (
<Typography>
Original Size: {(originalSize / 1024).toFixed(2)} KB
</Typography>
)}
{compressedSize !== null && (
<Typography>
Compressed Size: {(compressedSize / 1024).toFixed(2)} KB
</Typography>
)}
</Box>
</Box>
)
}
]}
initialValues={initialValues}
input={input}
/>
</Box>
);
}

View file

@ -0,0 +1,14 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('png', {
name: 'Compress png',
path: 'compress-png',
// image,
description:
'This is a program that compresses PNG pictures. As soon as you paste your PNG picture in the input area, the program will compress it and show the result in the output area. In the options, you can adjust the compression level, as well as find the old and new picture file sizes.',
shortDescription: 'Quicly compress a PNG',
keywords: ['compress', 'png'],
component: lazy(() => import('./index'))
});