Source: crop.js

const hasard = require('hasard');
const AbstractAugmenter = require('./abstract');

/**
* Left - Top - Right - Bottom array
* If Size 2, then we consider Left = Right and Top = Bottom
* If Number, then Left = Top = Right = Bottom = Number
* @typedef {Number  | Array.<Number> | Hasard.<Number> | Hasard.<Array.<Number>>} ArraylRTB
*/

/**
* Crop the image
* @param {Object} opts options, if number of array, it is considered as size
* @param {ArraylRTB} opts.percent percent of cropping to do
* @param {ArraylRTB} opts.size value of cropping to do
* @example
// Simple usage, crop by 10px, on every side
ia.crop(10);
* @example
//Simple usage with random variable crop by 10% to 30%
ia.crop({percent : h.number(0.1, 0.3)});
* @example
//Crop by 10% on left, 20% on top, to 30% on the right, 10% on the bottom
ia.crop({percent: [0.1, 0.2, 0.3, 0.1]});
*/

class CropAugmenter extends AbstractAugmenter {
	constructor(opts, ia) {
		let o;
		if (typeof (opts) === 'number' || Array.isArray(opts) || hasard.isHasard(opts)) {
			o = {size: opts};
		} else {
			o = opts;
		}

		super(o, ia);
		const {percent, size} = o;
		if (hasard.isHasard(size) || typeof (size) === 'number' || Array.isArray(size)) {
			this.size = this.toSize4(size);
		} else {
			this.percent = this.toSize4(percent);
		}
	}

	buildParams({width, height}) {
		return new hasard.Object({
			size: this.size || hasard.fn(p => [
				Math.round(width * p[0]),
				Math.round(height * p[1]),
				Math.round(width * p[2]),
				Math.round(height * p[3])
			])(this.percent)
		});
	}

	checkParams({size}) {
		size.forEach(p => {
			if (p < 0) {
				throw (new Error('only positive value allowed in crop for percent'));
			}
		});
	}

	getRect({width, height, params}) {
		const size = params.size.concat();
		return {
			x: size[0],
			y: size[1],
			w: width - size[2] - size[0],
			h: height - size[3] - size[1]
		};
	}

	augmentImage({image, width, height}, params) {
		const rect = this.getRect({width, height, params});
		if (rect.w <= 0 || rect.h <= 0) {
			throw (new Error(`Cannot crop by ${JSON.stringify(params)}`));
		}

		const res = this.backend.crop(image, rect);
		return res;
	}

	augmentPointsOnImage({points, width, height}, params) {
		const rect = this.getRect({width, height, params});
		const origin = this.backend.point(rect.x, rect.y);
		return points.map(p => p.sub(origin));
	}
}

module.exports = CropAugmenter;