diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 0e6a02e..26790ad 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,15 +4,23 @@
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -407,15 +415,7 @@
-
-
-
-
- 1740665609483
-
-
-
- 1740665609483
+
@@ -801,7 +801,15 @@
1743621602590
-
+
+
+ 1743623617781
+
+
+
+ 1743623617781
+
+
@@ -848,7 +856,6 @@
-
@@ -873,7 +880,8 @@
-
+
+
diff --git a/src/components/result/ToolFileResult.tsx b/src/components/result/ToolFileResult.tsx
index f0f7619..09b17be 100644
--- a/src/components/result/ToolFileResult.tsx
+++ b/src/components/result/ToolFileResult.tsx
@@ -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);
diff --git a/src/pages/tools/image/png/change-opacity/index.tsx b/src/pages/tools/image/generic/change-opacity/index.tsx
similarity index 96%
rename from src/pages/tools/image/png/change-opacity/index.tsx
rename to src/pages/tools/image/generic/change-opacity/index.tsx
index 8fc425d..5aaa995 100644
--- a/src/pages/tools/image/png/change-opacity/index.tsx
+++ b/src/pages/tools/image/generic/change-opacity/index.tsx
@@ -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) {
}
resultComponent={
-
+
}
initialValues={initialValues}
// exampleCards={exampleCards}
diff --git a/src/pages/tools/image/generic/change-opacity/meta.ts b/src/pages/tools/image/generic/change-opacity/meta.ts
new file mode 100644
index 0000000..81ef77f
--- /dev/null
+++ b/src/pages/tools/image/generic/change-opacity/meta.ts
@@ -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'))
+});
diff --git a/src/pages/tools/image/png/change-opacity/service.ts b/src/pages/tools/image/generic/change-opacity/service.ts
similarity index 91%
rename from src/pages/tools/image/png/change-opacity/service.ts
rename to src/pages/tools/image/generic/change-opacity/service.ts
index bea3a73..efcecaf 100644
--- a/src/pages/tools/image/png/change-opacity/service.ts
+++ b/src/pages/tools/image/generic/change-opacity/service.ts
@@ -9,7 +9,10 @@ interface OpacityOptions {
areaHeight: number;
}
-export async function changeOpacity(file: File, options: OpacityOptions): Promise {
+export async function changeOpacity(
+ file: File,
+ options: OpacityOptions
+): Promise {
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);
diff --git a/src/pages/tools/image/png/create-transparent/create-transparent.e2e.spec.ts b/src/pages/tools/image/generic/create-transparent/create-transparent.e2e.spec.ts
similarity index 95%
rename from src/pages/tools/image/png/create-transparent/create-transparent.e2e.spec.ts
rename to src/pages/tools/image/generic/create-transparent/create-transparent.e2e.spec.ts
index 9f8042a..364c0ae 100644
--- a/src/pages/tools/image/png/create-transparent/create-transparent.e2e.spec.ts
+++ b/src/pages/tools/image/generic/create-transparent/create-transparent.e2e.spec.ts
@@ -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
diff --git a/src/pages/tools/image/png/create-transparent/index.tsx b/src/pages/tools/image/generic/create-transparent/index.tsx
similarity index 94%
rename from src/pages/tools/image/png/create-transparent/index.tsx
rename to src/pages/tools/image/generic/create-transparent/index.tsx
index 45ed0b3..ce91a07 100644
--- a/src/pages/tools/image/png/create-transparent/index.tsx
+++ b/src/pages/tools/image/generic/create-transparent/index.tsx
@@ -112,8 +112,8 @@ export default function CreateTransparent({ title }: ToolComponentProps) {
}
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.'
}}
/>
);
diff --git a/src/pages/tools/image/png/create-transparent/meta.ts b/src/pages/tools/image/generic/create-transparent/meta.ts
similarity index 53%
rename from src/pages/tools/image/png/create-transparent/meta.ts
rename to src/pages/tools/image/generic/create-transparent/meta.ts
index 3ee1a9a..d606dfb 100644
--- a/src/pages/tools/image/png/create-transparent/meta.ts
+++ b/src/pages/tools/image/generic/create-transparent/meta.ts
@@ -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'))
});
diff --git a/src/pages/tools/image/png/create-transparent/test.png b/src/pages/tools/image/generic/create-transparent/test.png
similarity index 100%
rename from src/pages/tools/image/png/create-transparent/test.png
rename to src/pages/tools/image/generic/create-transparent/test.png
diff --git a/src/pages/tools/image/png/crop/index.tsx b/src/pages/tools/image/generic/crop/index.tsx
similarity index 91%
rename from src/pages/tools/image/png/crop/index.tsx
rename to src/pages/tools/image/generic/crop/index.tsx
index 2b4ec22..5f07eb5 100644
--- a/src/pages/tools/image/png/crop/index.tsx
+++ b/src/pages/tools/image/generic/crop/index.tsx
@@ -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(null);
const [result, setResult] = useState(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) {
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'}
/>
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'}
/>
@@ -200,8 +200,8 @@ export default function CropPng({ title }: ToolComponentProps) {
+
}
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.'
}}
/>
);
diff --git a/src/pages/tools/image/png/crop/meta.ts b/src/pages/tools/image/generic/crop/meta.ts
similarity index 88%
rename from src/pages/tools/image/png/crop/meta.ts
rename to src/pages/tools/image/generic/crop/meta.ts
index d10b27b..897eeeb 100644
--- a/src/pages/tools/image/png/crop/meta.ts
+++ b/src/pages/tools/image/generic/crop/meta.ts
@@ -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
diff --git a/src/pages/tools/image/generic/index.ts b/src/pages/tools/image/generic/index.ts
index d40fefa..a3bbb47 100644
--- a/src/pages/tools/image/generic/index.ts
+++ b/src/pages/tools/image/generic/index.ts
@@ -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
+];
diff --git a/src/pages/tools/image/png/remove-background/index.tsx b/src/pages/tools/image/generic/remove-background/index.tsx
similarity index 90%
rename from src/pages/tools/image/png/remove-background/index.tsx
rename to src/pages/tools/image/generic/remove-background/index.tsx
index 96115db..8c70633 100644
--- a/src/pages/tools/image/png/remove-background/index.tsx
+++ b/src/pages/tools/image/generic/remove-background/index.tsx
@@ -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(null);
const [result, setResult] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
@@ -64,7 +65,7 @@ export default function RemoveBackgroundFromPng({ title }: ToolComponentProps) {
}
@@ -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.'
}}
diff --git a/src/pages/tools/image/generic/remove-background/meta.ts b/src/pages/tools/image/generic/remove-background/meta.ts
new file mode 100644
index 0000000..fe13bbd
--- /dev/null
+++ b/src/pages/tools/image/generic/remove-background/meta.ts
@@ -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'))
+});
diff --git a/src/pages/tools/image/png/change-opacity/meta.ts b/src/pages/tools/image/png/change-opacity/meta.ts
deleted file mode 100644
index 1be290d..0000000
--- a/src/pages/tools/image/png/change-opacity/meta.ts
+++ /dev/null
@@ -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'))
-});
diff --git a/src/pages/tools/image/png/index.ts b/src/pages/tools/image/png/index.ts
index e4c4433..744e5f6 100644
--- a/src/pages/tools/image/png/index.ts
+++ b/src/pages/tools/image/png/index.ts
@@ -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];
diff --git a/src/pages/tools/image/png/remove-background/meta.ts b/src/pages/tools/image/png/remove-background/meta.ts
deleted file mode 100644
index 1ae19e7..0000000
--- a/src/pages/tools/image/png/remove-background/meta.ts
+++ /dev/null
@@ -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'))
-});
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 0f6e048..28a9b03 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -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,