-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #622 from danactive/add-heic-temp-generation
Add heic temp generation
- Loading branch information
Showing
13 changed files
with
4,816 additions
and
2,173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
v20.12.1 | ||
v20.15.0 |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { NextApiRequest, NextApiResponse } from 'next' | ||
|
||
import post from '../../../../src/lib/heifs' | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const { method, body } = req | ||
switch (method) { | ||
case 'POST': { | ||
const out = await post(body.files, body.destinationPath, true) | ||
return res.status(out.status).json(out.body) | ||
} | ||
default: | ||
return res.status(405) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import convert from 'heic-convert' | ||
import { readFile, writeFile } from 'node:fs/promises' | ||
import { basename } from 'node:path' | ||
import type { Filesystem } from './filesystems' | ||
import utilsFactory, { isStandardError } from './utils' | ||
|
||
type ResponseBody = { | ||
created: string[]; | ||
} | ||
|
||
type ErrorOptionalMessage = ResponseBody & { error?: { message: string } } | ||
const errorSchema = (message: string): ErrorOptionalMessage => { | ||
const out = { created: [] } | ||
if (!message) return out | ||
return { ...out, error: { message } } | ||
} | ||
|
||
type ResponseEnvelope = { | ||
body: ResponseBody; | ||
status: number; | ||
} | ||
|
||
function uniqueHeifs(files: Filesystem[]) { | ||
const groupedFiles = files.reduce((groups: Record<string, Filesystem[]>, file) => { | ||
const nameWithoutExt = basename(file.name, file.ext) | ||
if (!groups[nameWithoutExt]) { | ||
// eslint-disable-next-line no-param-reassign | ||
groups[nameWithoutExt] = [] | ||
} | ||
groups[nameWithoutExt].push(file) | ||
return groups | ||
}, {}) | ||
|
||
const heifFilesWithoutJpg = Object.values(groupedFiles) | ||
.filter((filteredFiles) => filteredFiles.some((file) => file.ext === 'heic') && !filteredFiles.some((file) => file.ext === 'jpg')) | ||
.flat() | ||
|
||
return heifFilesWithoutJpg | ||
} | ||
|
||
const utils = utilsFactory() | ||
async function processHeif(file: Filesystem, destinationPath: string): Promise<string> { | ||
const filenameHeif = utils.filenameAsJpg(file.filename) | ||
// eslint-disable-next-line no-await-in-loop | ||
const inputBuffer = await readFile(`public/${file.path}`) | ||
// eslint-disable-next-line no-await-in-loop | ||
const outputBuffer = await convert({ | ||
buffer: inputBuffer, // the HEIF file buffer | ||
format: 'JPEG', // output format | ||
quality: 0.8, // the jpeg compression quality, between 0 and 1 | ||
}) | ||
// eslint-disable-next-line no-await-in-loop | ||
await writeFile(`public${destinationPath}/${filenameHeif}`, new Uint8Array(outputBuffer)) | ||
return filenameHeif | ||
} | ||
|
||
async function post<T extends boolean = false>( | ||
files: Filesystem[], | ||
destinationPath: string, | ||
returnEnvelope?: T, | ||
): Promise<T extends true ? ResponseEnvelope : ResponseBody>; | ||
|
||
/** | ||
* Generate a photo image from HEIF files | ||
* @param {string} destinationPath path to save the converted files | ||
* @param {boolean} returnEnvelope will enable a return value with HTTP status code and body | ||
* @returns {Promise} files | ||
*/ | ||
async function post( | ||
files: Filesystem[], | ||
destinationPath: string, | ||
returnEnvelope = false, | ||
) { | ||
try { | ||
const heifs: string[] = [] | ||
for (const file of uniqueHeifs(files)) { | ||
// eslint-disable-next-line no-await-in-loop | ||
heifs.push(await processHeif(file, destinationPath)) | ||
} | ||
|
||
const body = { created: heifs } | ||
if (returnEnvelope) { | ||
return { body, status: 200 } | ||
} | ||
|
||
return body | ||
} catch (e) { | ||
if (returnEnvelope && isStandardError(e)) { | ||
return { body: errorSchema(e.message), status: 400 } | ||
} | ||
|
||
if (returnEnvelope) { | ||
return { body: errorSchema('Fail to process HEIFs'), status: 400 } | ||
} | ||
|
||
throw e | ||
} | ||
} | ||
|
||
export { type ResponseBody as HeifResponseBody } | ||
export default post |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.