feat: gif resize

This commit is contained in:
Ibrahima G. Coulibaly
2025-04-02 04:25:02 +00:00
parent 676359ed50
commit 8f42d2dc27
6 changed files with 89 additions and 22 deletions

View File

@@ -5,6 +5,7 @@ import { capitalizeFirstLetter } from '../utils/string';
import Grid from '@mui/material/Grid';
import { Icon, IconifyIcon } from '@iconify/react';
import { categoriesColors } from '../config/uiConfig';
import { getToolsByCategory } from '@tools/index';
const StyledButton = styled(Button)(({ theme }) => ({
backgroundColor: 'white',
@@ -70,7 +71,9 @@ export default function ToolHeader({
items={[
{ title: 'All tools', link: '/' },
{
title: capitalizeFirstLetter(type),
title: getToolsByCategory().find(
(category) => category.type === type
)!.rawTitle,
link: '/categories/' + type
},
{ title }

View File

@@ -53,7 +53,10 @@ export default function ToolLayout({
{children}
<Separator backgroundColor="#5581b5" margin="50px" />
<AllTools
title={`All ${capitalizeFirstLetter(type)} tools`}
title={`All ${capitalizeFirstLetter(
getToolsByCategory().find((category) => category.type === type)!
.rawTitle
)} tools`}
toolCards={otherCategoryTools}
/>
</Box>

View File

@@ -43,10 +43,11 @@ export default function Home() {
<IconButton onClick={() => navigate('/')}>
<ArrowBackIcon color={'primary'} />
</IconButton>
<Typography
fontSize={22}
color={theme.palette.primary.main}
>{`All ${capitalizeFirstLetter(categoryName)} Tools`}</Typography>
<Typography fontSize={22} color={theme.palette.primary.main}>{`All ${
getToolsByCategory().find(
(category) => category.type === categoryName
)!.rawTitle
} Tools`}</Typography>
</Stack>
<Grid container spacing={2} mt={2}>
{getToolsByCategory()

View File

@@ -1,4 +1,6 @@
import { InitialValuesType } from './types';
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
export const processImage = async (
file: File,
@@ -97,6 +99,60 @@ export const processImage = async (
console.error('Error processing SVG:', error);
// Fall back to canvas method if SVG processing fails
}
} else if (file.type === 'image/gif') {
try {
const ffmpeg = new FFmpeg();
await ffmpeg.load({
wasmURL:
'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.9/dist/esm/ffmpeg-core.wasm'
});
// Write the input file to memory
await ffmpeg.writeFile('input.gif', await fetchFile(file));
// Calculate new dimensions
let newWidth = 0;
let newHeight = 0;
let scaleFilter = '';
if (resizeMethod === 'pixels') {
if (dimensionType === 'width') {
newWidth = parseInt(width);
if (maintainAspectRatio) {
scaleFilter = `scale=${newWidth}:-1`;
} else {
newHeight = parseInt(height);
scaleFilter = `scale=${newWidth}:${newHeight}`;
}
} else {
// height
newHeight = parseInt(height);
if (maintainAspectRatio) {
scaleFilter = `scale=-1:${newHeight}`;
} else {
newWidth = parseInt(width);
scaleFilter = `scale=${newWidth}:${newHeight}`;
}
}
} else {
// percentage
const scale = parseInt(percentage) / 100;
scaleFilter = `scale=iw*${scale}:ih*${scale}`;
}
// Run FFmpeg command
await ffmpeg.exec(['-i', 'input.gif', '-vf', scaleFilter, 'output.gif']);
// Read the output file
const data = await ffmpeg.readFile('output.gif');
// Create a new File object
return new File([data], file.name, { type: 'image/gif' });
} catch (error) {
console.error('Error processing GIF with FFmpeg:', error);
// Fall back to canvas method if FFmpeg processing fails
}
}
// Create canvas
const canvas = document.createElement('canvas');

View File

@@ -130,6 +130,7 @@ export const filterTools = (
export const getToolsByCategory = (): {
title: string;
rawTitle: string;
description: string;
icon: IconifyIcon | string;
type: string;
@@ -144,6 +145,7 @@ export const getToolsByCategory = (): {
(config) => config.type === type
);
return {
rawTitle: categoryConfig?.title ?? capitalizeFirstLetter(type),
title: `${categoryConfig?.title ?? capitalizeFirstLetter(type)} Tools`,
description: categoryConfig?.value ?? '',
type,