chore: move from png to image-generic

This commit is contained in:
Ibrahima G. Coulibaly
2025-04-02 20:48:00 +00:00
parent 92858f2e24
commit a0ebd9c3b6
18 changed files with 125 additions and 101 deletions

View File

@@ -52,8 +52,17 @@ export default function ToolFileResult({
if (value) {
let filename: string = value.name;
if (extension) {
const hasExtension = filename.includes('.');
filename = hasExtension ? filename : `${filename}.${extension}`;
// Split at the last period to separate filename and extension
const parts = filename.split('.');
// If there's more than one part (meaning there was a period)
if (parts.length > 1) {
// Remove the last part (the extension) and add the new extension
parts.pop();
filename = `${parts.join('.')}.${extension}`;
} else {
// No extension exists, just add it
filename = `${filename}.${extension}`;
}
}
const blob = new Blob([value], { type: value.type });
const url = window.URL.createObjectURL(blob);

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';
import ToolImageInput from '@components/input/ToolImageInput';
import ToolFileResult from '@components/result/ToolFileResult';
import { changeOpacity } from './service';
@@ -97,16 +97,12 @@ export default function ChangeOpacity({ title }: ToolComponentProps) {
<ToolImageInput
value={input}
onChange={setInput}
accept={['image/png']}
title={'Input PNG'}
accept={['image/*']}
title={'Input image'}
/>
}
resultComponent={
<ToolFileResult
title={'Changed PNG'}
value={result}
extension={'png'}
/>
<ToolFileResult title={'Changed image'} value={result} />
}
initialValues={initialValues}
// exampleCards={exampleCards}

View File

@@ -0,0 +1,13 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('image-generic', {
name: 'Change image Opacity',
path: 'change-opacity',
icon: 'material-symbols:opacity',
description:
'Easily adjust the transparency of your images. Simply upload your image, use the slider to set the desired opacity level between 0 (fully transparent) and 1 (fully opaque), and download the modified image.',
shortDescription: 'Adjust transparency of images',
keywords: ['opacity', 'transparency', 'png', 'alpha', 'jpg', 'jpeg', 'image'],
component: lazy(() => import('./index'))
});

View File

@@ -9,7 +9,10 @@ interface OpacityOptions {
areaHeight: number;
}
export async function changeOpacity(file: File, options: OpacityOptions): Promise<File> {
export async function changeOpacity(
file: File,
options: OpacityOptions
): Promise<File> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
@@ -32,12 +35,12 @@ export async function changeOpacity(file: File, options: OpacityOptions): Promis
canvas.toBlob((blob) => {
if (blob) {
const newFile = new File([blob], file.name, { type: 'image/png' });
const newFile = new File([blob], file.name, { type: file.type });
resolve(newFile);
} else {
reject(new Error('Failed to generate image blob'));
}
}, 'image/png');
}, file.type);
};
img.onerror = () => reject(new Error('Failed to load image'));
img.src = event.target?.result as string;
@@ -67,9 +70,10 @@ function applyGradientOpacity(
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(img, 0, 0);
const gradient = options.gradientType === 'linear'
? createLinearGradient(ctx, options)
: createRadialGradient(ctx, options);
const gradient =
options.gradientType === 'linear'
? createLinearGradient(ctx, options)
: createRadialGradient(ctx, options);
ctx.fillStyle = gradient;
ctx.fillRect(areaLeft, areaTop, areaWidth, areaHeight);

View File

@@ -5,7 +5,7 @@ import Jimp from 'jimp';
test.describe('Create transparent PNG', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/png/create-transparent');
await page.goto('/image-generic/create-transparent');
});
//TODO check why failing

View File

@@ -112,8 +112,8 @@ export default function CreateTransparent({ title }: ToolComponentProps) {
<ToolImageInput
value={input}
onChange={setInput}
accept={['image/png']}
title={'Input PNG'}
accept={['image/*']}
title={'Input image'}
/>
}
resultComponent={
@@ -131,7 +131,7 @@ export default function CreateTransparent({ title }: ToolComponentProps) {
toolInfo={{
title: 'Create Transparent PNG',
description:
'This tool allows you to make specific colors in a PNG image transparent. You can select the color to replace and adjust the similarity threshold to include similar colors.'
'This tool allows you to make specific colors in an image transparent. You can select the color to replace and adjust the similarity threshold to include similar colors.'
}}
/>
);

View File

@@ -1,13 +1,13 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('png', {
export const tool = defineTool('image-generic', {
name: 'Create transparent PNG',
path: 'create-transparent',
icon: 'mdi:circle-transparent',
shortDescription: 'Quickly make a PNG image transparent',
shortDescription: 'Quickly make an image transparent',
description:
"World's simplest online Portable Network Graphics transparency maker. Just import your PNG image in the editor on the left and you will instantly get a transparent PNG on the right. Free, quick, and very powerful. Import a PNG get a transparent PNG.",
"World's simplest online Portable Network Graphics transparency maker. Just import your image in the editor on the left and you will instantly get a transparent PNG on the right. Free, quick, and very powerful. Import an image get a transparent PNG.",
keywords: ['create', 'transparent'],
component: lazy(() => import('./index'))
});

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -32,7 +32,7 @@ const validationSchema = Yup.object({
.required('Height is required')
});
export default function CropPng({ title }: ToolComponentProps) {
export default function CropImage({ title }: ToolComponentProps) {
const [input, setInput] = useState<File | null>(null);
const [result, setResult] = useState<File | null>(null);
@@ -101,11 +101,11 @@ export default function CropPng({ title }: ToolComponentProps) {
destCanvas.toBlob((blob) => {
if (blob) {
const newFile = new File([blob], file.name, {
type: 'image/png'
type: file.type
});
setResult(newFile);
}
}, 'image/png');
}, file.type);
};
processImage(input, x, y, width, height, isCircular);
@@ -180,13 +180,13 @@ export default function CropPng({ title }: ToolComponentProps) {
<SimpleRadio
onClick={() => updateField('cropShape', 'rectangular')}
checked={values.cropShape == 'rectangular'}
description={'Crop a rectangular fragment from a PNG.'}
description={'Crop a rectangular fragment from an image.'}
title={'Rectangular Crop Shape'}
/>
<SimpleRadio
onClick={() => updateField('cropShape', 'circular')}
checked={values.cropShape == 'circular'}
description={'Crop a circular fragment from a PNG.'}
description={'Crop a circular fragment from an image.'}
title={'Circular Crop Shape'}
/>
</Box>
@@ -200,8 +200,8 @@ export default function CropPng({ title }: ToolComponentProps) {
<ToolImageInput
value={input}
onChange={setInput}
accept={['image/png']}
title={'Input PNG'}
accept={['image/*']}
title={'Input image'}
showCropOverlay={!!input}
cropShape={values.cropShape as 'rectangular' | 'circular'}
cropPosition={{
@@ -225,16 +225,12 @@ export default function CropPng({ title }: ToolComponentProps) {
validationSchema={validationSchema}
renderCustomInput={renderCustomInput}
resultComponent={
<ToolFileResult
title={'Cropped PNG'}
value={result}
extension={'png'}
/>
<ToolFileResult title={'Cropped image'} value={result} />
}
toolInfo={{
title: 'Crop PNG Image',
title: 'Crop Image',
description:
'This tool allows you to crop a PNG image by specifying the position, size, and shape of the crop area. You can choose between rectangular or circular cropping.'
'This tool allows you to crop an image by specifying the position, size, and shape of the crop area. You can choose between rectangular or circular cropping.'
}}
/>
);

View File

@@ -1,7 +1,7 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('png', {
export const tool = defineTool('image-generic', {
name: 'Crop',
path: 'crop',
icon: 'mdi:crop', // Iconify icon as a string

View File

@@ -1,5 +1,17 @@
import { tool as resizeImage } from './resize/meta';
import { tool as compressImage } from './compress/meta';
import { tool as changeColors } from './change-colors/meta';
import { tool as removeBackground } from './remove-background/meta';
import { tool as cropImage } from './crop/meta';
import { tool as changeOpacity } from './change-opacity/meta';
import { tool as createTransparent } from './create-transparent/meta';
export const imageGenericTools = [resizeImage, compressImage, changeColors];
export const imageGenericTools = [
resizeImage,
compressImage,
removeBackground,
cropImage,
changeOpacity,
changeColors,
createTransparent
];

View File

@@ -1,4 +1,3 @@
import { Box, CircularProgress, Typography } from '@mui/material';
import React, { useState } from 'react';
import * as Yup from 'yup';
import ToolFileResult from '@components/result/ToolFileResult';
@@ -11,7 +10,9 @@ const initialValues = {};
const validationSchema = Yup.object({});
export default function RemoveBackgroundFromPng({ title }: ToolComponentProps) {
export default function RemoveBackgroundFromImage({
title
}: ToolComponentProps) {
const [input, setInput] = useState<File | null>(null);
const [result, setResult] = useState<File | null>(null);
const [isProcessing, setIsProcessing] = useState<boolean>(false);
@@ -64,7 +65,7 @@ export default function RemoveBackgroundFromPng({ title }: ToolComponentProps) {
<ToolImageInput
value={input}
onChange={setInput}
accept={['image/png', 'image/jpeg', 'image/jpg']}
accept={['image/*']}
title={'Input Image'}
/>
}
@@ -78,7 +79,7 @@ export default function RemoveBackgroundFromPng({ title }: ToolComponentProps) {
/>
}
toolInfo={{
title: 'Remove Background from PNG',
title: 'Remove Background from Image',
description:
'This tool uses AI to automatically remove the background from your images, creating a transparent PNG. Perfect for product photos, profile pictures, and design assets.'
}}

View File

@@ -0,0 +1,21 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('image-generic', {
name: 'Remove Background from Image',
path: 'remove-background',
icon: 'mdi:image-remove',
description:
"World's simplest online tool to remove backgrounds from images. Just upload your image and our AI-powered tool will automatically remove the background, giving you a transparent PNG. Perfect for product photos, profile pictures, and design assets.",
shortDescription: 'Automatically remove backgrounds from images',
keywords: [
'remove',
'background',
'png',
'transparent',
'image',
'ai',
'jpg'
],
component: lazy(() => import('./index'))
});

View File

@@ -1,12 +0,0 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('png', {
name: 'Change PNG Opacity',
path: 'change-opacity',
icon: 'material-symbols:opacity',
description: 'Easily adjust the transparency of your PNG images. Simply upload your PNG file, use the slider to set the desired opacity level between 0 (fully transparent) and 1 (fully opaque), and download the modified image.',
shortDescription: 'Adjust transparency of PNG images',
keywords: ['opacity', 'transparency', 'png', 'alpha'],
component: lazy(() => import('./index'))
});

View File

@@ -1,15 +1,4 @@
import { tool as pngCrop } from './crop/meta';
import { tool as pngCompressPng } from './compress-png/meta';
import { tool as convertJgpToPng } from './convert-jgp-to-png/meta';
import { tool as pngCreateTransparent } from './create-transparent/meta';
import { tool as changeOpacity } from './change-opacity/meta';
import { tool as removeBackground } from './remove-background/meta';
export const pngTools = [
pngCompressPng,
pngCreateTransparent,
convertJgpToPng,
changeOpacity,
pngCrop,
removeBackground
];
export const pngTools = [pngCompressPng, convertJgpToPng];

View File

@@ -1,13 +0,0 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('png', {
name: 'Remove Background from PNG',
path: 'remove-background',
icon: 'mdi:image-remove',
description:
"World's simplest online tool to remove backgrounds from PNG images. Just upload your image and our AI-powered tool will automatically remove the background, giving you a transparent PNG. Perfect for product photos, profile pictures, and design assets.",
shortDescription: 'Automatically remove backgrounds from images',
keywords: ['remove', 'background', 'png', 'transparent', 'image', 'ai'],
component: lazy(() => import('./index'))
});

View File

@@ -13,7 +13,7 @@ import { IconifyIcon } from '@iconify/react';
import { pdfTools } from '../pages/tools/pdf';
const toolCategoriesOrder: ToolCategory[] = [
'png',
'image-generic',
'string',
'json',
'pdf',
@@ -21,9 +21,9 @@ const toolCategoriesOrder: ToolCategory[] = [
'csv',
'video',
'number',
'gif',
'png',
'time',
'image-generic'
'gif'
];
export const tools: DefinedTool[] = [
...imageTools,