filepond
filepond copied to clipboard
[Feature] Aspect ratio validation
Is there an existing issue for this?
- [X] I have searched the existing issues
Is your feature request related to a problem? Please describe.
My users may upload a photo that meets the resolution and size requirements but whose aspect ratio (width:height ratio) makes it very tall or very wide. I'd prefer to restrict uploads to photos that will be closer to square (but not necessarily square), for consistent appearance when viewing photos.
Describe the solution you'd like
I'd like to be able to use a plugin that allows me to specify a maximum aspect ratio.
If I specified a maximum of 1.0 then images must be square. If I specified a maximum of 2.0 then images may be rectangular, but if the height is more than double the width, or the width is more than double the height, then the image is rejected with a message: "too wide" or "too tall"
Describe alternatives you've considered
I tried the image-validate-size plugin but this didn't offer aspect ratio validation.
I advise to fork the validate size plugin and adjust it to test a min and max aspect ratio. you get aspect ratio by dividing image width by image height.
Will do thanks @rikschennink
Here's a quick reference. Checks if a selected image is a square:
/* eslint-disable */
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory())
: typeof define === 'function' && define.amd
? define(factory)
: ((global = global || self),
(global.FilePondPluginSquareCheck = factory()));
})(this, function() {
'use strict';
var plugin = function plugin(_ref) {
var addFilter = _ref.addFilter,
utils = _ref.utils;
// get quick reference to Type utils
var Type = utils.Type,
isString = utils.isString,
replaceInString = utils.replaceInString,
guesstimateMimeType = utils.guesstimateMimeType,
getExtensionFromFilename = utils.getExtensionFromFilename,
getFilenameFromURL = utils.getFilenameFromURL;
var validateFile = function validateFile(
item
) {
// use type detector
return new Promise(function(resolve, reject) {
let URL = (window.URL || window.webkitURL)
const blob = URL.createObjectURL(item)
let img = new Image()
img.onload = () => {
if (img.height !== img.width) {
reject()
}
resolve()
}
img.src = blob
});
};
var applyMimeTypeMap = function applyMimeTypeMap(map) {
return function(acceptedFileType) {
return map[acceptedFileType] === null
? false
: map[acceptedFileType] || acceptedFileType;
};
};
// filtering if an item is allowed in hopper
addFilter('ALLOW_HOPPER_ITEM', function(file, _ref2) {
var query = _ref2.query;
// if we are not doing file type validation exit
if (!query('GET_ALLOW_SQUARE_VALIDATION')) {
return true;
}
return validateFile(file);
});
// called for each file that is loaded
// right before it is set to the item state
// should return a promise
addFilter('LOAD_FILE', function(file, _ref3) {
var query = _ref3.query;
return new Promise(function(resolve, reject) {
if (!query('GET_ALLOW_SQUARE_VALIDATION')) {
resolve(file);
return;
}
// if invalid, exit here
var validationResult = validateFile(
file,
);
var handleRejection = function handleRejection() {
reject({
status: {
main: query('GET_LABEL_INVALID_ASPECT_RATIO'),
sub: query('GET_LABEL_INVALID_ASPECT_RATIO')
}
});
};
// has returned new filename immidiately
if (typeof validationResult === 'boolean') {
if (!validationResult) {
return handleRejection();
}
return resolve(file);
}
// is promise
validationResult
.then(function() {
resolve(file);
})
.catch(handleRejection);
});
});
// expose plugin
return {
// default options
options: {
// Enable or disable file type validation
allowSquareValidation: [false, Type.BOOLEAN],
// label to show when a type is not allowed
labelInvalidAspectRatio: ['Image is not a square', Type.STRING],
}
};
};
// fire pluginloaded event if running in browser, this allows registering the plugin when using async script tags
var isBrowser =
typeof window !== 'undefined' && typeof window.document !== 'undefined';
if (isBrowser) {
document.dispatchEvent(
new CustomEvent('FilePond:pluginloaded', { detail: plugin })
);
}
return plugin;
});
So, I racked my brain over a similar question for a long time. It may help you out here.
1 is square. Less than 1 is portrait. Greater than 1 is landscape.
If the image is too tall or too wide consider adding the image editor and present the user with the option to crop it to fit the desired ratio.
You could even add guides that show the preferred and closest aspect ratio in the editor.