mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-04 21:37:11 -04:00
Merge pull request #1 from sharevb/feat/heic-converter
Feat/heic converter
This commit is contained in:
commit
ae99f42540
8 changed files with 284 additions and 89 deletions
30
src/tools/heic-converter/heic-convert.d.ts
vendored
Normal file
30
src/tools/heic-converter/heic-convert.d.ts
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
declare module 'heic-convert/browser' {
|
||||
interface ConversionOptions {
|
||||
/**
|
||||
* the HEIC file buffer
|
||||
*/
|
||||
buffer: ArrayBufferLike;
|
||||
/**
|
||||
* output format
|
||||
*/
|
||||
format: "JPEG" | "PNG";
|
||||
/**
|
||||
* the JPEG compression quality, between 0 and 1
|
||||
* @default 0.92
|
||||
*/
|
||||
quality?: number;
|
||||
}
|
||||
|
||||
interface Convertible {
|
||||
convert(): Promise<ArrayBuffer>;
|
||||
}
|
||||
|
||||
/** @async */
|
||||
declare function convert(image: ConversionOptions): Promise<ArrayBuffer>;
|
||||
declare namespace convert {
|
||||
/** @async */
|
||||
function all(image: ConversionOptions): Promise<Convertible[]>;
|
||||
}
|
||||
|
||||
export default convert;
|
||||
}
|
87
src/tools/heic-converter/heic-converter.vue
Normal file
87
src/tools/heic-converter/heic-converter.vue
Normal file
|
@ -0,0 +1,87 @@
|
|||
<script setup lang="ts">
|
||||
import { Base64 } from 'js-base64';
|
||||
import heicConvert from 'heic-convert/browser';
|
||||
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
|
||||
|
||||
const status = ref<'idle' | 'done' | 'error' | 'processing'>('idle');
|
||||
const file = ref<File | null>(null);
|
||||
|
||||
const base64OutputImage = ref('');
|
||||
const fileName = ref('');
|
||||
const format = ref('jpg');
|
||||
const formats = [
|
||||
{ value: 'jpg', label: 'JPEG' },
|
||||
{ value: 'png', label: 'PNG' },
|
||||
];
|
||||
const { download } = useDownloadFileFromBase64(
|
||||
{
|
||||
source: base64OutputImage,
|
||||
filename: fileName,
|
||||
});
|
||||
|
||||
async function onFileUploaded(uploadedFile: File) {
|
||||
file.value = uploadedFile;
|
||||
const fileBuffer = await uploadedFile.arrayBuffer();
|
||||
|
||||
fileName.value = `${uploadedFile.name}.${format.value}`;
|
||||
status.value = 'processing';
|
||||
try {
|
||||
let convertFormat;
|
||||
if (format.value === 'jpg') {
|
||||
convertFormat = 'JPEG';
|
||||
}
|
||||
else if (format.value === 'png') {
|
||||
convertFormat = 'PNG';
|
||||
}
|
||||
else {
|
||||
throw new Error('unknown format');
|
||||
}
|
||||
|
||||
const outputBuffer = await heicConvert({
|
||||
buffer: new Uint8Array(fileBuffer),
|
||||
format: convertFormat as ('JPEG' | 'PNG'),
|
||||
quality: 0.98,
|
||||
});
|
||||
base64OutputImage.value = `data:image/${convertFormat.toLowerCase()};base64,${Base64.fromUint8Array(new Uint8Array(outputBuffer))}`;
|
||||
|
||||
status.value = 'done';
|
||||
|
||||
download();
|
||||
}
|
||||
catch (e) {
|
||||
status.value = 'error';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<c-select
|
||||
v-model:value="format"
|
||||
:options="formats"
|
||||
label="Output format"
|
||||
/>
|
||||
|
||||
<div style="flex: 0 0 100%" mt-3>
|
||||
<div mx-auto max-w-600px>
|
||||
<c-file-upload
|
||||
title="Drag and drop a HEIC file here, or click to select a file"
|
||||
accept=".heic,.heif" @file-upload="onFileUploaded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div mt-3 flex justify-center>
|
||||
<img :src="base64OutputImage" max-w-300px>
|
||||
</div>
|
||||
|
||||
<div mt-3 flex justify-center>
|
||||
<c-alert v-if="status === 'error'" type="error">
|
||||
An error occured processing {{ fileName }}. HEIC/HEIF is invalid.
|
||||
</c-alert>
|
||||
<n-spin
|
||||
v-if="status === 'processing'"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
12
src/tools/heic-converter/index.ts
Normal file
12
src/tools/heic-converter/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Photo } from '@vicons/tabler';
|
||||
import { defineTool } from '../tool';
|
||||
|
||||
export const tool = defineTool({
|
||||
name: 'HEIC Converter',
|
||||
path: '/heic-converter',
|
||||
description: 'HEIC Converter to JPEG or PNG',
|
||||
keywords: ['heic', 'heif', 'convert', 'decoder', 'converter'],
|
||||
component: () => import('./heic-converter.vue'),
|
||||
icon: Photo,
|
||||
createdAt: new Date('2024-04-28'),
|
||||
});
|
|
@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
|||
|
||||
import { tool as textToUnicode } from './text-to-unicode';
|
||||
import { tool as safelinkDecoder } from './safelink-decoder';
|
||||
import { tool as heicConverter } from './heic-converter';
|
||||
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
|
||||
import { tool as numeronymGenerator } from './numeronym-generator';
|
||||
import { tool as macAddressGenerator } from './mac-address-generator';
|
||||
|
@ -132,7 +133,13 @@ export const toolsByCategory: ToolCategory[] = [
|
|||
},
|
||||
{
|
||||
name: 'Images and videos',
|
||||
components: [qrCodeGenerator, wifiQrCodeGenerator, svgPlaceholderGenerator, cameraRecorder],
|
||||
components: [
|
||||
qrCodeGenerator,
|
||||
wifiQrCodeGenerator,
|
||||
svgPlaceholderGenerator,
|
||||
cameraRecorder,
|
||||
heicConverter,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Development',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue