2019-03-04 14:48:48 +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" ;
2019-03-04 14:48:48 +01:00
import { toBase64 } from "../lib/Base64.mjs" ;
2019-07-09 13:23:59 +02:00
import { isWorkerEnvironment } from "../Utils.mjs" ;
2023-02-27 18:55:52 +01:00
import jimp from "jimp" ;
2019-03-04 14:48:48 +01:00
/ * *
* Crop Image operation
* /
class CropImage extends Operation {
/ * *
* CropImage constructor
* /
constructor ( ) {
super ( ) ;
this . name = "Crop Image" ;
this . module = "Image" ;
2019-03-09 08:23:11 +01:00
this . description = "Crops an image to the specified region, or automatically crops edges.<br><br><b><u>Autocrop</u></b><br>Automatically crops same-colour borders from the image.<br><br><u>Autocrop tolerance</u><br>A percentage value for the tolerance of colour difference between pixels.<br><br><u>Only autocrop frames</u><br>Only crop real frames (all sides must have the same border)<br><br><u>Symmetric autocrop</u><br>Force autocrop to be symmetric (top/bottom and left/right are cropped by the same amount)<br><br><u>Autocrop keep border</u><br>The number of pixels of border to leave around the image." ;
2019-03-04 14:48:48 +01:00
this . infoURL = "https://wikipedia.org/wiki/Cropping_(image)" ;
2019-04-01 11:54:46 +02:00
this . inputType = "ArrayBuffer" ;
this . outputType = "ArrayBuffer" ;
2019-03-04 14:48:48 +01:00
this . presentType = "html" ;
this . args = [
{
name : "X Position" ,
type : "number" ,
value : 0 ,
min : 0
} ,
{
name : "Y Position" ,
type : "number" ,
value : 0 ,
min : 0
} ,
{
name : "Width" ,
type : "number" ,
value : 10 ,
min : 1
} ,
{
name : "Height" ,
type : "number" ,
value : 10 ,
min : 1
} ,
{
name : "Autocrop" ,
type : "boolean" ,
value : false
} ,
{
name : "Autocrop tolerance (%)" ,
type : "number" ,
value : 0.02 ,
min : 0 ,
max : 100 ,
step : 0.01
} ,
{
name : "Only autocrop frames" ,
type : "boolean" ,
value : true
} ,
{
name : "Symmetric autocrop" ,
type : "boolean" ,
value : false
} ,
{
name : "Autocrop keep border (px)" ,
type : "number" ,
value : 0 ,
min : 0
}
] ;
}
/ * *
2019-04-01 11:54:46 +02:00
* @ param { ArrayBuffer } input
2019-03-04 14:48:48 +01:00
* @ param { Object [ ] } args
* @ returns { byteArray }
* /
async run ( input , args ) {
const [ xPos , yPos , width , height , autocrop , autoTolerance , autoFrames , autoSymmetric , autoBorder ] = args ;
2019-09-04 14:54:59 +02:00
if ( ! isImage ( input ) ) {
2019-03-04 14:48:48 +01:00
throw new OperationError ( "Invalid file type." ) ;
}
2019-03-07 12:19:04 +01:00
let image ;
try {
2019-04-01 11:54:46 +02:00
image = await jimp . read ( input ) ;
2019-03-07 12:19:04 +01:00
} catch ( err ) {
throw new OperationError ( ` Error loading image. ( ${ err } ) ` ) ;
2019-03-04 14:48:48 +01:00
}
2019-03-07 12:19:04 +01:00
try {
2019-07-05 11:17:52 +02:00
if ( isWorkerEnvironment ( ) )
2019-03-07 12:19:04 +01:00
self . sendStatusMessage ( "Cropping image..." ) ;
if ( autocrop ) {
image . autocrop ( {
tolerance : ( autoTolerance / 100 ) ,
cropOnlyFrames : autoFrames ,
cropSymmetric : autoSymmetric ,
leaveBorder : autoBorder
} ) ;
} else {
image . crop ( xPos , yPos , width , height ) ;
}
2019-03-04 14:48:48 +01:00
2019-03-20 12:20:34 +01:00
let imageBuffer ;
if ( image . getMIME ( ) === "image/gif" ) {
imageBuffer = await image . getBufferAsync ( jimp . MIME _PNG ) ;
} else {
imageBuffer = await image . getBufferAsync ( jimp . AUTO ) ;
}
2019-04-01 11:54:46 +02:00
return imageBuffer . buffer ;
2019-03-07 12:19:04 +01:00
} catch ( err ) {
throw new OperationError ( ` Error cropping image. ( ${ err } ) ` ) ;
}
2019-03-04 14:48:48 +01:00
}
/ * *
* Displays the cropped image using HTML for web apps
2019-04-01 11:54:46 +02:00
* @ param { ArrayBuffer } data
2019-03-04 14:48:48 +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-04 14:48:48 +01:00
2019-04-01 11:54:46 +02:00
const type = isImage ( dataArray ) ;
2019-03-09 08:23:11 +01:00
if ( ! type ) {
throw new OperationError ( "Invalid file type." ) ;
2019-03-04 14:48:48 +01:00
}
2019-04-01 11:54:46 +02:00
return ` <img src="data: ${ type } ;base64, ${ toBase64 ( dataArray ) } "> ` ;
2019-03-04 14:48:48 +01:00
}
}
export default CropImage ;