2019-03-12 17:29:20 +01:00
/ * *
* @ author j433866 [ j433866 @ gmail . com ]
* @ copyright Crown Copyright 2019
* @ license Apache - 2.0
* /
2019-07-09 13:23:59 +02:00
import Operation from "../Operation.mjs" ;
import OperationError from "../errors/OperationError.mjs" ;
import { isImage } from "../lib/FileType.mjs" ;
import { toBase64 } from "../lib/Base64.mjs" ;
2023-02-27 18:55:52 +01:00
import jimp from "jimp" ;
2019-03-12 17:29:20 +01:00
/ * *
* Convert Image Format operation
* /
class ConvertImageFormat extends Operation {
/ * *
* ConvertImageFormat constructor
* /
constructor ( ) {
super ( ) ;
2019-03-19 14:54:39 +01:00
this . name = "Convert Image Format" ;
2019-03-12 17:29:20 +01:00
this . module = "Image" ;
this . description = "Converts an image between different formats. Supported formats:<br><ul><li>Joint Photographic Experts Group (JPEG)</li><li>Portable Network Graphics (PNG)</li><li>Bitmap (BMP)</li><li>Tagged Image File Format (TIFF)</li></ul><br>Note: GIF files are supported for input, but cannot be outputted." ;
this . infoURL = "https://wikipedia.org/wiki/Image_file_formats" ;
2019-04-01 11:54:46 +02:00
this . inputType = "ArrayBuffer" ;
this . outputType = "ArrayBuffer" ;
2019-03-12 17:29:20 +01:00
this . presentType = "html" ;
this . args = [
{
name : "Output Format" ,
type : "option" ,
value : [
"JPEG" ,
"PNG" ,
"BMP" ,
"TIFF"
]
} ,
{
name : "JPEG Quality" ,
type : "number" ,
value : 80 ,
min : 1 ,
max : 100
} ,
{
name : "PNG Filter Type" ,
type : "option" ,
value : [
"Auto" ,
"None" ,
"Sub" ,
"Up" ,
"Average" ,
"Paeth"
]
} ,
{
name : "PNG Deflate Level" ,
type : "number" ,
value : 9 ,
min : 0 ,
max : 9
}
] ;
}
/ * *
2019-04-01 11:54:46 +02:00
* @ param { ArrayBuffer } input
2019-03-12 17:29:20 +01:00
* @ param { Object [ ] } args
* @ returns { byteArray }
* /
async run ( input , args ) {
const [ format , jpegQuality , pngFilterType , pngDeflateLevel ] = args ;
const formatMap = {
"JPEG" : jimp . MIME _JPEG ,
"PNG" : jimp . MIME _PNG ,
"BMP" : jimp . MIME _BMP ,
"TIFF" : jimp . MIME _TIFF
} ;
const pngFilterMap = {
"Auto" : jimp . PNG _FILTER _AUTO ,
"None" : jimp . PNG _FILTER _NONE ,
"Sub" : jimp . PNG _FILTER _SUB ,
"Up" : jimp . PNG _FILTER _UP ,
"Average" : jimp . PNG _FILTER _AVERAGE ,
2020-12-14 18:51:12 +01:00
"Paeth" : jimp . PNG _FILTER _PATH
2019-03-12 17:29:20 +01:00
} ;
const mime = formatMap [ format ] ;
2019-09-04 14:54:59 +02:00
if ( ! isImage ( input ) ) {
2019-03-12 17:29:20 +01:00
throw new OperationError ( "Invalid file format." ) ;
}
let image ;
try {
2019-04-01 11:54:46 +02:00
image = await jimp . read ( input ) ;
2019-03-12 17:29:20 +01:00
} catch ( err ) {
throw new OperationError ( ` Error opening image file. ( ${ err } ) ` ) ;
}
try {
switch ( format ) {
case "JPEG" :
image . quality ( jpegQuality ) ;
break ;
case "PNG" :
image . filterType ( pngFilterMap [ pngFilterType ] ) ;
image . deflateLevel ( pngDeflateLevel ) ;
break ;
}
const imageBuffer = await image . getBufferAsync ( mime ) ;
2019-04-01 11:54:46 +02:00
return imageBuffer . buffer ;
2019-03-12 17:29:20 +01:00
} catch ( err ) {
throw new OperationError ( ` Error converting image format. ( ${ err } ) ` ) ;
}
}
/ * *
* Displays the converted image using HTML for web apps
*
2019-04-01 11:54:46 +02:00
* @ param { ArrayBuffer } data
2019-03-12 17:29:20 +01:00
* @ returns { html }
* /
present ( data ) {
2019-04-01 11:54:46 +02:00
if ( ! data . byteLength ) return "" ;
const dataArray = new Uint8Array ( data ) ;
2019-03-12 17:29:20 +01:00
2019-04-01 11:54:46 +02:00
const type = isImage ( dataArray ) ;
2019-03-12 17:29:20 +01:00
if ( ! type ) {
2019-04-01 11:54:46 +02:00
throw new OperationError ( "Invalid file type." ) ;
2019-03-12 17:29:20 +01:00
}
2019-04-01 11:54:46 +02:00
return ` <img src="data: ${ type } ;base64, ${ toBase64 ( dataArray ) } "> ` ;
2019-03-12 17:29:20 +01:00
}
}
export default ConvertImageFormat ;