mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-14 19:49:32 +02:00
feat: image to text
This commit is contained in:
43
.idea/workspace.xml
generated
43
.idea/workspace.xml
generated
@@ -4,17 +4,16 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: uninstall @jspawn/ghostscript-wasm">
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/pdf/protect-pdf/index.tsx" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/pdf/protect-pdf/meta.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/pdf/protect-pdf/service.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/pdf/protect-pdf/types.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/pdf/utils.ts" afterDir="false" />
|
||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="feat: protect pdf">
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/image/generic/image-to-text/index.tsx" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/image/generic/image-to-text/meta.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/image/generic/image-to-text/service.ts" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/pages/tools/image/generic/image-to-text/types.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/lib/ghostscript/background-worker.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/ghostscript/background-worker.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/lib/ghostscript/worker-init.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/ghostscript/worker-init.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/tools/pdf/compress-pdf/service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/pdf/compress-pdf/service.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/tools/pdf/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/pdf/index.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/components/result/ToolTextResult.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/result/ToolTextResult.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/pages/tools/image/generic/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/image/generic/index.ts" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -416,15 +415,7 @@
|
||||
<workItem from="1743458576265" duration="13083000" />
|
||||
<workItem from="1743690613245" duration="77000" />
|
||||
<workItem from="1743691250813" duration="1550000" />
|
||||
<workItem from="1743699386059" duration="6244000" />
|
||||
</task>
|
||||
<task id="LOCAL-00140" summary="style: optimizations">
|
||||
<option name="closed" value="true" />
|
||||
<created>1740936527951</created>
|
||||
<option name="number" value="00140" />
|
||||
<option name="presentableId" value="LOCAL-00140" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1740936527951</updated>
|
||||
<workItem from="1743699386059" duration="8791000" />
|
||||
</task>
|
||||
<task id="LOCAL-00141" summary="feat: ToolContent.tsx">
|
||||
<option name="closed" value="true" />
|
||||
@@ -810,7 +801,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1743691471368</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="189" />
|
||||
<task id="LOCAL-00189" summary="feat: protect pdf">
|
||||
<option name="closed" value="true" />
|
||||
<created>1743705749057</created>
|
||||
<option name="number" value="00189" />
|
||||
<option name="presentableId" value="LOCAL-00189" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1743705749057</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="190" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -857,7 +856,6 @@
|
||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||
<option name="CHECK_NEW_TODO" value="false" />
|
||||
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||
<MESSAGE value="refactor: file inputs" />
|
||||
<MESSAGE value="feat: background removal" />
|
||||
<MESSAGE value="feat: split pdf" />
|
||||
<MESSAGE value="fix: typo" />
|
||||
@@ -882,7 +880,8 @@
|
||||
<MESSAGE value="fix: vite worker format" />
|
||||
<MESSAGE value="fix: tests" />
|
||||
<MESSAGE value="chore: uninstall @jspawn/ghostscript-wasm" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="chore: uninstall @jspawn/ghostscript-wasm" />
|
||||
<MESSAGE value="feat: protect pdf" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="feat: protect pdf" />
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
|
67
package-lock.json
generated
67
package-lock.json
generated
@@ -40,6 +40,7 @@
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-crop": "^11.0.7",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"tesseract.js": "^6.0.0",
|
||||
"type-fest": "^4.35.0",
|
||||
"use-deep-compare-effect": "^1.8.1",
|
||||
"yup": "^1.4.0"
|
||||
@@ -6297,6 +6298,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/idb-keyval": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
|
||||
"integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
@@ -6817,6 +6824,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-url": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
|
||||
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-weakmap": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
|
||||
@@ -8102,6 +8115,15 @@
|
||||
"protobufjs": "^7.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/opencollective-postinstall": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
|
||||
"integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"opencollective-postinstall": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
@@ -10091,6 +10113,36 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/tesseract.js": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.0.tgz",
|
||||
"integrity": "sha512-tqYCod1HwJzkeZw1l6XWx+ly2hhisGcBtak9MArhYwDAxL0NgeVhLJcUjqPxZMQtpgtVUzWcpZPryi+hnaQGVw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"bmp-js": "^0.1.0",
|
||||
"idb-keyval": "^6.2.0",
|
||||
"is-url": "^1.2.4",
|
||||
"node-fetch": "^2.6.9",
|
||||
"opencollective-postinstall": "^2.0.3",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"tesseract.js-core": "^6.0.0",
|
||||
"wasm-feature-detect": "^1.2.11",
|
||||
"zlibjs": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tesseract.js-core": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz",
|
||||
"integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/tesseract.js/node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/text-extensions": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
|
||||
@@ -10690,6 +10742,12 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wasm-feature-detect": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz",
|
||||
"integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
@@ -11103,6 +11161,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zlibjs": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz",
|
||||
"integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.2",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
|
||||
|
@@ -57,6 +57,7 @@
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-crop": "^11.0.7",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"tesseract.js": "^6.0.0",
|
||||
"type-fest": "^4.35.0",
|
||||
"use-deep-compare-effect": "^1.8.1",
|
||||
"yup": "^1.4.0"
|
||||
|
@@ -1,21 +1,24 @@
|
||||
import { Box, TextField } from '@mui/material';
|
||||
import { Box, CircularProgress, TextField, Typography } from '@mui/material';
|
||||
import React, { useContext } from 'react';
|
||||
import { CustomSnackBarContext } from '../../contexts/CustomSnackBarContext';
|
||||
import InputHeader from '../InputHeader';
|
||||
import ResultFooter from './ResultFooter';
|
||||
import { replaceSpecialCharacters } from '@utils/string';
|
||||
import mime from 'mime';
|
||||
import { globalInputHeight } from '../../config/uiConfig';
|
||||
|
||||
export default function ToolTextResult({
|
||||
title = 'Result',
|
||||
value,
|
||||
extension = 'txt',
|
||||
keepSpecialCharacters
|
||||
keepSpecialCharacters,
|
||||
loading
|
||||
}: {
|
||||
title?: string;
|
||||
value: string;
|
||||
extension?: string;
|
||||
keepSpecialCharacters?: boolean;
|
||||
loading?: boolean;
|
||||
}) {
|
||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||
const handleCopy = () => {
|
||||
@@ -46,18 +49,37 @@ export default function ToolTextResult({
|
||||
return (
|
||||
<Box>
|
||||
<InputHeader title={title} />
|
||||
<TextField
|
||||
value={keepSpecialCharacters ? value : replaceSpecialCharacters(value)}
|
||||
fullWidth
|
||||
multiline
|
||||
sx={{
|
||||
'&.MuiTextField-root': {
|
||||
backgroundColor: 'background.paper'
|
||||
{loading ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: globalInputHeight
|
||||
}}
|
||||
>
|
||||
<CircularProgress />
|
||||
<Typography variant="body2" sx={{ mt: 2 }}>
|
||||
Loading... This may take a moment.
|
||||
</Typography>
|
||||
</Box>
|
||||
) : (
|
||||
<TextField
|
||||
value={
|
||||
keepSpecialCharacters ? value : replaceSpecialCharacters(value)
|
||||
}
|
||||
}}
|
||||
rows={10}
|
||||
inputProps={{ 'data-testid': 'text-result' }}
|
||||
/>
|
||||
fullWidth
|
||||
multiline
|
||||
sx={{
|
||||
'&.MuiTextField-root': {
|
||||
backgroundColor: 'background.paper'
|
||||
}
|
||||
}}
|
||||
rows={10}
|
||||
inputProps={{ 'data-testid': 'text-result' }}
|
||||
/>
|
||||
)}
|
||||
<ResultFooter handleCopy={handleCopy} handleDownload={handleDownload} />
|
||||
</Box>
|
||||
);
|
||||
|
108
src/pages/tools/image/generic/image-to-text/index.tsx
Normal file
108
src/pages/tools/image/generic/image-to-text/index.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import * as Yup from 'yup';
|
||||
import ToolImageInput from '@components/input/ToolImageInput';
|
||||
import ToolTextResult from '@components/result/ToolTextResult';
|
||||
import { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import SelectWithDesc from '@components/options/SelectWithDesc';
|
||||
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { extractTextFromImage, getAvailableLanguages } from './service';
|
||||
import { InitialValuesType } from './types';
|
||||
import { CustomSnackBarContext } from '../../../../../contexts/CustomSnackBarContext';
|
||||
|
||||
const initialValues: InitialValuesType = {
|
||||
language: 'eng',
|
||||
detectParagraphs: true
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
language: Yup.string().required('Language is required')
|
||||
});
|
||||
|
||||
export default function ImageToText({ title }: ToolComponentProps) {
|
||||
const [input, setInput] = useState<File | null>(null);
|
||||
const [result, setResult] = useState<string>('');
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||
const { showSnackBar } = useContext(CustomSnackBarContext);
|
||||
const compute = async (optionsValues: InitialValuesType, input: any) => {
|
||||
if (!input) return;
|
||||
|
||||
setIsProcessing(true);
|
||||
|
||||
try {
|
||||
const extractedText = await extractTextFromImage(input, optionsValues);
|
||||
setResult(extractedText);
|
||||
} catch (err: any) {
|
||||
showSnackBar(
|
||||
err.message || 'An error occurred while processing the image',
|
||||
'error'
|
||||
);
|
||||
setResult('');
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getGroups: GetGroupsType<InitialValuesType> = ({
|
||||
values,
|
||||
updateField
|
||||
}) => [
|
||||
{
|
||||
title: 'OCR Options',
|
||||
component: (
|
||||
<Box>
|
||||
<SelectWithDesc
|
||||
selected={values.language}
|
||||
onChange={(val) => updateField('language', val)}
|
||||
description={
|
||||
'Select the primary language in the image for better accuracy'
|
||||
}
|
||||
options={getAvailableLanguages()}
|
||||
/>
|
||||
<CheckboxWithDesc
|
||||
checked={values.detectParagraphs}
|
||||
onChange={(value) => updateField('detectParagraphs', value)}
|
||||
description={
|
||||
'Attempt to preserve paragraph structure in the extracted text'
|
||||
}
|
||||
title={'Detect Paragraphs'}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ToolContent
|
||||
title={title}
|
||||
initialValues={initialValues}
|
||||
getGroups={getGroups}
|
||||
compute={compute}
|
||||
input={input}
|
||||
validationSchema={validationSchema}
|
||||
inputComponent={
|
||||
<ToolImageInput
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
accept={['image/jpeg', 'image/png']}
|
||||
title={'Input Image'}
|
||||
/>
|
||||
}
|
||||
resultComponent={
|
||||
<ToolTextResult
|
||||
title={'Extracted Text'}
|
||||
value={result}
|
||||
loading={isProcessing}
|
||||
/>
|
||||
}
|
||||
toolInfo={{
|
||||
title: 'Image to Text (OCR)',
|
||||
description:
|
||||
'This tool extracts text from images using Optical Character Recognition (OCR). Upload an image containing text, select the primary language, and get the extracted text. For best results, use clear images with good contrast.'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
22
src/pages/tools/image/generic/image-to-text/meta.ts
Normal file
22
src/pages/tools/image/generic/image-to-text/meta.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
name: 'Image to Text (OCR)',
|
||||
path: 'image-to-text',
|
||||
icon: 'mdi:text-recognition', // Iconify icon as a string
|
||||
description:
|
||||
'Extract text from images (JPG, PNG) using optical character recognition (OCR).',
|
||||
shortDescription: 'Extract text from images using OCR.',
|
||||
keywords: [
|
||||
'ocr',
|
||||
'optical character recognition',
|
||||
'image to text',
|
||||
'extract text',
|
||||
'scan',
|
||||
'tesseract',
|
||||
'jpg',
|
||||
'png'
|
||||
],
|
||||
component: lazy(() => import('./index'))
|
||||
});
|
56
src/pages/tools/image/generic/image-to-text/service.ts
Normal file
56
src/pages/tools/image/generic/image-to-text/service.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { createWorker } from 'tesseract.js';
|
||||
import { InitialValuesType } from './types';
|
||||
|
||||
export const extractTextFromImage = async (
|
||||
file: File,
|
||||
options: InitialValuesType
|
||||
): Promise<string> => {
|
||||
try {
|
||||
const { language, detectParagraphs } = options;
|
||||
|
||||
// Create a Tesseract worker
|
||||
const worker = await createWorker(language);
|
||||
|
||||
// Convert file to URL
|
||||
const imageUrl = URL.createObjectURL(file);
|
||||
|
||||
// Recognize text
|
||||
const { data } = await worker.recognize(imageUrl);
|
||||
|
||||
// Clean up
|
||||
URL.revokeObjectURL(imageUrl);
|
||||
await worker.terminate();
|
||||
|
||||
// Process the result based on options
|
||||
if (detectParagraphs) {
|
||||
// Return text with paragraph structure preserved
|
||||
return data.text;
|
||||
} else {
|
||||
// Return plain text with basic formatting
|
||||
return data.text;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error extracting text from image:', error);
|
||||
throw new Error(
|
||||
'Failed to extract text from image. Please try again with a clearer image.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to get available languages
|
||||
export const getAvailableLanguages = (): { value: string; label: string }[] => {
|
||||
return [
|
||||
{ value: 'eng', label: 'English' },
|
||||
{ value: 'fra', label: 'French' },
|
||||
{ value: 'deu', label: 'German' },
|
||||
{ value: 'spa', label: 'Spanish' },
|
||||
{ value: 'ita', label: 'Italian' },
|
||||
{ value: 'por', label: 'Portuguese' },
|
||||
{ value: 'rus', label: 'Russian' },
|
||||
{ value: 'jpn', label: 'Japanese' },
|
||||
{ value: 'chi_sim', label: 'Chinese (Simplified)' },
|
||||
{ value: 'chi_tra', label: 'Chinese (Traditional)' },
|
||||
{ value: 'kor', label: 'Korean' },
|
||||
{ value: 'ara', label: 'Arabic' }
|
||||
];
|
||||
};
|
4
src/pages/tools/image/generic/image-to-text/types.ts
Normal file
4
src/pages/tools/image/generic/image-to-text/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export type InitialValuesType = {
|
||||
language: string;
|
||||
detectParagraphs: boolean;
|
||||
};
|
@@ -5,6 +5,7 @@ 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';
|
||||
import { tool as imageToText } from './image-to-text/meta';
|
||||
|
||||
export const imageGenericTools = [
|
||||
resizeImage,
|
||||
@@ -13,5 +14,6 @@ export const imageGenericTools = [
|
||||
cropImage,
|
||||
changeOpacity,
|
||||
changeColors,
|
||||
createTransparent
|
||||
createTransparent,
|
||||
imageToText
|
||||
];
|
||||
|
Reference in New Issue
Block a user