mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-11-09 01:52:30 +05:30
feat: change pgn opacity
This commit is contained in:
parent
fc58d7f9ee
commit
5d04e5794a
11 changed files with 237 additions and 69 deletions
|
|
@ -5,7 +5,6 @@ import React, { ReactNode, RefObject, useContext, useEffect } from 'react';
|
|||
import { Formik, FormikProps, FormikValues, useFormikContext } from 'formik';
|
||||
import ToolOptionGroups, { ToolOptionGroup } from './ToolOptionGroups';
|
||||
import { CustomSnackBarContext } from '../../contexts/CustomSnackBarContext';
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export type UpdateField<T> = <Y extends keyof T>(field: Y, value: T[Y]) => void;
|
||||
|
||||
|
|
@ -26,6 +25,7 @@ const FormikListenerComponent = <T,>({
|
|||
compute(values, input);
|
||||
} catch (exception: unknown) {
|
||||
if (exception instanceof Error) showSnackBar(exception.message, 'error');
|
||||
else console.error(exception);
|
||||
}
|
||||
}, [values, input]);
|
||||
|
||||
|
|
|
|||
87
src/pages/tools/image/png/change-opacity/index.tsx
Normal file
87
src/pages/tools/image/png/change-opacity/index.tsx
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import ToolFileInput from '@components/input/ToolFileInput';
|
||||
import ToolFileResult from '@components/result/ToolFileResult';
|
||||
import { changeOpacity } from './service';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import { updateNumberField } from '@utils/string';
|
||||
|
||||
type InitialValuesType = {
|
||||
opacity: number;
|
||||
};
|
||||
|
||||
const initialValues: InitialValuesType = {
|
||||
opacity: 1
|
||||
};
|
||||
|
||||
const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
{
|
||||
title: 'Semi-transparent PNG',
|
||||
description: 'Make an image 50% transparent',
|
||||
sampleOptions: {
|
||||
opacity: 0.5
|
||||
},
|
||||
sampleResult: ''
|
||||
},
|
||||
{
|
||||
title: 'Slightly Faded PNG',
|
||||
description: 'Create a subtle transparency effect',
|
||||
sampleOptions: {
|
||||
opacity: 0.8
|
||||
},
|
||||
sampleResult: ''
|
||||
}
|
||||
];
|
||||
|
||||
export default function ChangeOpacity({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<File | null>(null);
|
||||
const [result, setResult] = useState<File | null>(null);
|
||||
|
||||
const compute = (values: InitialValuesType, input: any) => {
|
||||
if (input) {
|
||||
changeOpacity(input, values.opacity).then(setResult);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
input={input}
|
||||
inputComponent={
|
||||
<ToolFileInput
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
accept={['image/png']}
|
||||
title={'Input PNG'}
|
||||
/>
|
||||
}
|
||||
resultComponent={
|
||||
<ToolFileResult
|
||||
title={'Changed PNG'}
|
||||
value={result}
|
||||
extension={'png'}
|
||||
/>
|
||||
}
|
||||
initialValues={initialValues}
|
||||
exampleCards={exampleCards}
|
||||
getGroups={({ values, updateField }) => [
|
||||
{
|
||||
title: 'Opacity Settings',
|
||||
component: (
|
||||
<TextFieldWithDesc
|
||||
description="Set opacity between 0 (transparent) and 1 (opaque)"
|
||||
value={values.opacity}
|
||||
onOwnChange={(val) =>
|
||||
updateNumberField(val, 'opacity', updateField)
|
||||
}
|
||||
type="number"
|
||||
inputProps={{ step: 0.1, min: 0, max: 1 }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]}
|
||||
compute={compute}
|
||||
/>
|
||||
);
|
||||
}
|
||||
12
src/pages/tools/image/png/change-opacity/meta.ts
Normal file
12
src/pages/tools/image/png/change-opacity/meta.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
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'))
|
||||
});
|
||||
39
src/pages/tools/image/png/change-opacity/service.ts
Normal file
39
src/pages/tools/image/png/change-opacity/service.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
export async function changeOpacity(
|
||||
file: File,
|
||||
opacity: number
|
||||
): Promise<File> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
reject(new Error('Canvas context not supported'));
|
||||
return;
|
||||
}
|
||||
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.globalAlpha = opacity;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob) {
|
||||
const newFile = new File([blob], file.name, { type: 'image/png' });
|
||||
resolve(newFile);
|
||||
} else {
|
||||
reject(new Error('Failed to generate image blob'));
|
||||
}
|
||||
}, 'image/png');
|
||||
};
|
||||
img.onerror = () => reject(new Error('Failed to load image'));
|
||||
img.src = <string>event.target?.result;
|
||||
};
|
||||
reader.onerror = () => reject(new Error('Failed to read file'));
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
|
@ -2,10 +2,12 @@ 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 changeColorsInPng } from './change-colors-in-png/meta';
|
||||
import { tool as changeOpacity } from './change-opacity/meta';
|
||||
|
||||
export const pngTools = [
|
||||
pngCompressPng,
|
||||
pngCreateTransparent,
|
||||
changeColorsInPng,
|
||||
convertJgpToPng
|
||||
convertJgpToPng,
|
||||
changeOpacity
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { tool as listSort } from './sort/meta';
|
|||
|
||||
export const listTools = [
|
||||
listSort,
|
||||
listUnwrap,
|
||||
// listUnwrap,
|
||||
listReverse,
|
||||
listFindUnique,
|
||||
listFindMostPopular,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ export const tool = defineTool('string', {
|
|||
name: 'Reverse',
|
||||
path: 'reverse',
|
||||
icon: '',
|
||||
description: "World's simplest browser-based utility for reversing text. Input any text and get it instantly reversed, character by character. Perfect for creating mirror text, analyzing palindromes, or playing with text patterns. Preserves spaces and special characters while reversing.",
|
||||
description:
|
||||
"World's simplest browser-based utility for reversing text. Input any text and get it instantly reversed, character by character. Perfect for creating mirror text, analyzing palindromes, or playing with text patterns. Preserves spaces and special characters while reversing.",
|
||||
shortDescription: 'Reverse any text character by character',
|
||||
keywords: ['reverse'],
|
||||
component: lazy(() => import('./index'))
|
||||
|
|
|
|||
7
src/typed/jimp.d.ts
vendored
7
src/typed/jimp.d.ts
vendored
|
|
@ -1,7 +0,0 @@
|
|||
declare module 'jimp' {
|
||||
class JimpImage {
|
||||
getPixelColor: (x: number, y: number) => number;
|
||||
}
|
||||
|
||||
export function read(buffer: Buffer): Promise<JimpImage>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue