pqina / filepond-plugin-image-transform Goto Github PK
View Code? Open in Web Editor NEW๐ผ Client-side image transformations for FilePond
Home Page: https://pqina.nl/filepond
License: MIT License
๐ผ Client-side image transformations for FilePond
Home Page: https://pqina.nl/filepond
License: MIT License
You can reproduce it using sample code from here:
https://github.com/pqina/react-filepond/blob/master/example/src/App.js
This is the final FilePond object:
<FilePond ref={ref => this.pond = ref}
files={this.state.files}
allowMultiple={true}
imageResizeTargetWidth="200"
imageResizeTargetHeight="200"
server={{
// fake server to simulate loading a 'local' server file and processing a file
process: (fieldName, file, metadata, load) => {
// simulates uploading a file
setTimeout(() => {
load(Date.now())
}, 1500);
},
load: (source, load) => {
console.log(source);
console.log(load);
// simulates loading a file from the server
fetch(source)
.then(res => { console.log(res); return res.blob();})
.then((blob) =>{console.log(blob); return load(blob);});
}
}}
oninit={() => this.handleInit() }
onupdatefiles={fileItems => {
// Set currently active file objects to this.state
this.setState({
files: fileItems.map(fileItem => fileItem.file)
});
}}>
</FilePond>
If you try to compress this very long png, its size changes from 2MB to 7.3MB (3.6 times of original).
In these cases, I would like to upload original instead for obvious reasons.
Is this currently possible?
Or choose to transform only jpeg files, because I think png files are often better untouched.
Describe the bug
imageTransform is re-compressing (even when no changes) unless imageTransformOutputMimeType is set
Logs
n/a
To Reproduce
FilePond.registerPlugin(
FilePondPluginFileValidateSize,
FilePondPluginImageExifOrientation,
FilePondPluginImagePreview,
FilePondPluginImageTransform
);
// do not set resize, crop, or set any other transform related options (other than those below) to isolate bug
Case 1
FilePond.setOptions({
// do not set imageTransformOutputMimeType
});
upload a jpeg
imageTransform will transform (re-compress) the jpeg
Case 2
FilePond.setOptions({
imageTransformOutputMimeType: 'image/jpeg',
});
upload a jpeg
imageTransform will not transform the jpeg
Expected behavior
Case 1: imageTransform should not transform (re-compress) the jpeg since the mime type has not changed. One way around this is to set imageTransformOutputQualityMode: 'optional'
. However, this is only works if imageTransformOutputQuality
is set to a number (not browser default), so basically, to preserve mime type and avoid recompression one is forced to set imageTransformOutputQualityMode: 'optional'
and imageTransformOutputQuality
to a number.
Case 2: behaving as expected.
Stacktraces
n/a
Information about your project:
Windows 10, latest firefox, latest filepond
Additional context
n/a
Hi. I really hate when I can't use such awsome library. Its raelly graet!!! Thanks guys.
But lately I stuck ror 3 days...
I use getFileEncodeBase64String method on file item in react's file pond library, I get the result (proper Base64 string) and then the app crashes with warnings:
TypeError: Cannot read property 'data' of undefinedgetFileEncodeBase64String
C:/dev/dokMenagier/client/node_modules/filepond-plugin-file-encode/dist/filepond-plugin-file-encode.js:69
66 | if (!query('GET_ALLOW_FILE_ENCODE')) return;
67 |
68 | item.extend('getFileEncodeBase64String', function() {
69 | return base64Cache[item.id].data;
| ^ 70 | });
71 | item.extend('getFileEncodeDataURL', function() {
72 | return 'data:'
<FilePond
allowFileEncode={true}
files={cover}
// allowMultiple={true}
server={null}
instantUpload={false}
onupdatefiles={fileItems =>
onFileChange(fileItems[0])
}
></FilePond>
and as a handler:
const onFileChange = fileEncoded => {
if (
fileEncoded === null ||
fileEncoded === undefined ||
fileEncoded === '' ||
fileEncoded === {}
) {
console.log('!!!');
} else {
console.log(fileEncoded.getFileEncodeBase64String());
}
};
There is a valid Base64String in a console but app breaks.
Any ideas?
I've seen that there are plugins for resizing and quality, I would need to apply a watermark, after having resized and lowered the quality of an image, can i use FilePond with another library like watermarkjs?
Although the best solution would be to have a specific plugin for filepond...
Thanks!
I upgraded today from version 3.2.4
to 3.3.1.
and file uploads are now failing with the following HTTP response error: No format specified for Image. I can get a working example if need be but I'm not really doing anything that deviates dramatically from the docs. The only other plugin I am using is filepond-plugin-image-exif-orientation
and all versions are the latest and greatest.
I'm currently trying to find a way to set the imageTransformOutputQuality to a calculated value. the example in this page shows that you can only set it on FilePond.create(). I would like to:
Calculate the value for imageTransformOutputQuality based on the image's file size. for example.
If my max file size is 1mb, and i have a 20mb image. the percentage would be
pctAdjustment = (1/20) * 100; //5%
is this possible?
Hello Rik,
i'm having problem with uploading animated GIFs - they aren't animated anymore after implicit transform by transform plugin. They are uploaded as PNG
My setup - i am using Vue.js / filepond-vue with some plugins
FilePondPluginExif,
FilePondPluginImagePreview,
FilePondPluginImageEdit
FilePondPluginImageTransform
And i need have the Image Transform active because i have also Doka in my setup
I've tried to disable Doka - issue is still there
I've tried to keep Doka and disable Image Transform plugin - issue disapeares and gifs are uploaded correctly
I've tried to use somewhere recommended ImageTransformImageFilter option / callback ... not documented, keyword can be found in source codes, but seems to be not working anymore ...
also using allowImageExifOrientation and need to support also other filetypes
my versions as in package.json
"filepond": "^4.20.1",
"filepond-plugin-file-validate-type": "1.2.5",
"filepond-plugin-image-crop": "^2.0.4",
"filepond-plugin-image-edit": "^1.6.1",
"filepond-plugin-image-exif-orientation": "^1.0.9",
"filepond-plugin-image-preview": "^4.6.4",
"filepond-plugin-image-transform": "^3.7.4",
So my guess is that problem is really in transform plugin
Is there any way out of this problem?
Thanks, Adam
When adding the EXIF orientation plugin images that are uploaded to the server are sent without being reoriented and with a black bar across part of the image.
The image preview and image editor display the image correctly, it's only the uploaded output that has the issues. Only images with EXIF orientation data are affected.
I found an issue when imageResizeUpscale = false
, smaller images (smaller than imageResizeTargetWidth
or imageResizeTargetHeight
) don't have access to the resize transform in imageTransformVariants
. In order to work around this, I enable imageResizeUpscale
, so that I can resize everything, but I end up throwing away the original image after it gets to the server. Here is a snippet of the code that has issues:
const pond = FilePond.create(document.querySelector('input'), {
imageResizeTargetWidth: 1280,
imageResizeTargetHeight: 1280,
imageResizeMode: 'contain',
imageResizeUpscale: false,
imageTransformOutputQuality: 80,
imageTransformVariants: {
'm_': transforms => {
// errors here on any image that is less than the 1280x1280 defined above, since it doesn't have to resize the image.
transforms.resize.size.width = 640;
transforms.resize.size.height = 640;
return transforms;
}
}
});
The documentation seems to not be available
It seems like the newest version re-exports FilePondFile which clashes with the base library. Just letting the maintainers know. Cannot build my angular project because of it. Downgrading to 3.7.6 works.
When an SVG is used in the markup attribute and is offline (perhaps momentarily), Filepond stops handling all files, the upload cannot be cancelled and no error is displayed.
When uploading a .jpeg image the file extension is set to .jpg, yet the file metadata keeps the .jpeg extension.
I tracked it down to
var renameFileToMatchMimeType = function renameFileToMatchMimeType(
filename,
format
) {
var name = getFilenameWithoutExtension(filename);
var extension = format === 'image/jpeg' ? 'jpg' : format.split('/')[1];
return name + '.' + extension;
};
Is this a bug and should it be set to .jpeg or am i missing something?
var extension = format === 'image/jpeg' ? 'jpeg' : format.split('/')[1];
Need to make webp for faster reload? Right now, when I use this plugin, formdata doesn't read the converted file:
ondata: (formData) => {
// const formData = new FormData();
// formData.append('filepond', convertedwebp);
}
A client sent a file to the FilePond with transform plugin enabled.
It crashed FilePond JS and makes the upload unlimited with no error.
The JS error is not clearly readable from the navigator, but it seems to crash here
Here's the file:
(I wiped it to white because sensible content, if you want the original ask me)
https://user-images.githubusercontent.com/25293190/215067250-8bc2fc32-6a86-4612-bf48-98b7a168fe6b.jpg
root@4147797bee55:/var/www/html# yarn list --pattern filepond
yarn list v1.22.19
โโ [email protected]
โโ [email protected]
โโ [email protected]
โโ [email protected]
โโ [email protected]
โโ [email protected]
Browser : FireFox 109.0 (64 bits)
Trying to understand if there is a way to do that, but so far I did not have any luck.
I've noticed you implemented the upscale = false, to prevent upscaling images smaller than target size, which is one thing I was looking before.
But my next issues is I need to be able to upload original images without re-encoding into JPG again in case there are not transformations applied. Is that possible?
Hi,
I have a web page where, after loading files with drag&drop (like in standard filepond examples) they are uploaded on a PHP server (using filepond uploader).
That works for all file types I have to use except for TIFF image files.
In browser with TIFF support (ex: Safari in OSX) everything is ok, but in browsers whitout TIFF support (Ex: Firefox and Chrome on Mac or Win), after the loading I have a js crash with an uncaught error related to this promise at line 3710 on 3.7.2:
// add default output version if output default set to true or if no variants defined
if (query('GET_IMAGE_TRANSFORM_VARIANTS_INCLUDE_DEFAULT')) {
variants.push(function(transform, file, metadata) {
return new Promise(function(resolve) {
transform(file, metadata).then(function(file) {
return resolve({
name: query('GET_IMAGE_TRANSFORM_VARIANTS_DEFAULT_NAME'),
file: file
});
});
});
});
}
I suppose that the promise lacks to check for error (not sure) and perhps the same issue can happens also in other promises of the module...
Of course I can't suppose to have thumbnail/preview for TIFF in browsers without TIFF support; I am thinking about inserting a dummy reject function in promise to skip error.
Is it the good direction ?
Thanks
The plugin strips EXIF data from the image as of version 3.4.0, even with the option: imageTransformOutputStripImageHead=false
I can confirm it is working with version 3.3.3, and stops working from 3.4.0 up to the current version.
Hey, not sure if this is the intended behavior, but I discovered that SVGs are turned into bitmaps when transformed.
This totally makes sense, because you can't really resize or crop an SVG.
But I'm wondering if there could be an option for this, ex: imageTransformSVGs
, which would default to true
(backwards compatible) but could be set to false
to leave SVGs as is.
Thoughts?
I would like to add a caption to the bottom of photos and a small logo, but I haven't been able to figure it out yet
docs?
I have read through all of the documentation and had a skim over the source code, but can't seem to find a solution to this. I'm not entirely clear if this question is more relevant to the crop, resize or transform plugin, so I hope it is ok for this to be posted here.
Is there a way to return an image that has a specific ratio by using padding instead of cropping? So the source image is basically resized as per the current functionality, but then padded to meet the ratio?
Hi!
First of all: thanks for this amazing library โค๏ธ
I'm using filepond (the React component.) on a custom form and I want to upload the images when saving the whole for information. I'm saving files on component's state and when submitting the data I'm uploading each file and the save the data with the uploaded file urls on the server.
How do I get the transformed files on client size before uploading them to the server if I'm not using the server
method?
This is a simplify version of my component:
import React, { Component } from 'react';
import { FilePond, registerPlugin } from 'react-filepond';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImageResize from 'filepond-plugin-image-resize';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageTransform from 'filepond-plugin-image-transform';
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
registerPlugin(FilePondPluginFileValidateType,
FilePondPluginImagePreview,
FilePondPluginImageResize,
FilePondPluginImageTransform,
);
class Form extends Component {
constructor(props, context) {
super(props, context);
this.handleSubmit = this.handleSubmit.bind(this);
this.onDropPhotos = this.onDropPhotos.bind(this);
this.state = {
title: '',
photos: [],
};
}
onDropPhotos() {
const files = this.photosFilePond.getFiles();
this.setState({
photos: files.map(f => f.file),
});
}
handleValueChange(field, value) {
this.setState({ [field]: value });
}
async handleSubmit() {
const {
title, photos,
} = this.state;
const uploadedPhotos = [];
if (photos.length) {
await Promise.all(
photos.map(async (file) => {
const snapshot = await firebase.storage().ref().put(file);
const downloadURL = await snapshot.ref.getDownloadURL();
uploadedPhotos.push(downloadURL);
}),
);
}
const payload = {
title,
photos: uploadedPhotos,
};
// Save data on server
}
render() {
const { title } = this.state;
return (
<div className="Form">
<Input placeholder="title..." value={title} onChange={e => this.handleValueChange('title', e.target.value)} />
<FilePond
ref={ref => this.photosFilePond = ref} // eslint-disable-line no-return-assign
allowMultiple
allowImageResize
allowImageTransform
imageTransformOutputMimeType="image/jpeg"
imageResizeUpscale={false}
imageResizeTargetWidth={900}
acceptedFileTypes={['image/png', 'image/jpeg']}
imagePreviewHeight="100"
onaddfile={this.onDropPhotos}
onremovefile={this.onDropPhotos}
/>
<Button onClick={this.handleSubmit}>Post</Button>
</div>
);
}
}
export default Form;
Thanks in advance!
It would be nice to be able to access the transformed blob from the file using something like
const blob = await file.getTransformedImage();
Basically like what filepond-plugin-encode
does with file.getFileEncodeDataURL()
but without the encoding part
I have the following options enabled:
allowImageTransform: true,
imageTransformOutputQuality: 20,
imageTransformOutputQualityMode: 'optional',
allowImageResize: true,
allowImageCrop: true,
imageResizeMode: 'cover',
// some other values
When I upload a PNG file of filesize 1.73MB, which is exactly the given size (and thus no transform is applied, I assume), it ends up being around 2.1MB Chrome and 2.2MB in Firefox.
Changing the imageTransformOutputQuality does not seem to result in any changes in filesize or image quality.
Please note the image in question is compressed in Photoshop using the option 'slowest/smallest'.
See https://renolooijmans.nl/public/file_example.png as example. It's size is 1.3MB, and once 'transformed' by Filepond its size is near to 1.9MB (in Chrome).
Why is the filesize increased by a fair bit while the image is not being transformed? I can't seem to find the reason.
Update: If I also use imageTransformOutputMimeType: 'image/jpeg', the size of the png (now jpeg) is greatly reduced. Is this something which is typical for png?
Can you create a release of this addon?
Would it be possible to add typescript support to this plugin? The other plugins (like FileEncode and ImageResize work fine).
I'm getting the error
Cannot find module 'filepond-plugin-image-transform/dist' or its corresponding type declarations.
for the line in app.module.ts
import FilePondPluginImageTransform from "filepond-plugin-image-transform/dist";
I'm on Angular 11.
Hey there.
First of all, thanks a lot for the great tool. I've tried a few uploader but your's far better than any of them.
Having a couple of small problems with Transform plugin: I'd like to use resing of the original image and generate two thumbnails. Here's part of my config:
imageResizeTargetWidth: 720,
imageTransformVariants: {
thumb_medium_: transforms => {
transforms.resize.size.width = 300;
return transforms;
},
thumb_small_: transforms => {
transforms.resize.size.width = 80;
return transforms;
}
},
The problem is Filepond sends just the last "thumb_small_x" image. As far as I understood from your blog post on dev.to it's a problem of output type: now, instead of one image, I have three.
onpreparefile
for sending files is not a good move.Thanks for sharing this intresting pice of software..
I have a question regarding
imageTransformVariants: {
thumb_medium_
Which works as expected.. My question is How to have variant name APPENDED instead of PREPENDED to filename..
With prepended scrolling the dir with a filepicker.. it is difficult to find/see desired file as all starts with thumb or whatever name choosen as variant name..
Other option would be to save be able to save variant with original filename but in subdir with name of VARIANT.. (like thumb_medium in this case..)
Thanks,,
I am following documentation how to setup different image sizes to upload them via process method.
Here is my vue-filepond HTML (ignore extra parameters):
<file-pond
allow-multiple="true"
max-files="8"
:accepted-file-types="['image/jpeg']"
:image-resize-target-width="1920"
:image-transform-variants="{
thumb_medium_: (transforms) => {
transforms.resize = {
size: {
width: 384,
height: 384,
},
};
return transforms;
},
}"
:server="filepondServer"
@init="handleFilepondInit"
@processfile="handleFilepondProcessFile"
@updatefiles="handleFilepondUpdateFiles"
/>
When I have items inside image-transform-variants my backend (Laravel Illuminate\Http\Request class) always has only last file in array and image is resized to this correct width/height. When I remove variants and just leave target-width, image is resized to 1920w. So this part of resizing is working; but how to get all files on backend, not just the last one in the list?
This is header request:
filepond: {"resize":{"mode":"cover","upscale":true,"size":{"width":1920,"height":1920}},"crop":{"center":{"x":0.5,"y":0.5},"flip":{"horizontal":false,"vertical":false},"rotation":0,"zoom":1,"aspectRatio":null},"color":null,"output":{"type":null,"quality":null,"client":["crop","resize","filter","markup","output"]}}
filepond: (binary)
filepond: (binary)
This is Laravel response ($request->allFiles()); it should be 2 files (or 3 if I add another variant), no?
array:1 [
"filepond" => Illuminate\Http\UploadedFile {#1655
-test: false
-originalName: "thumb_medium_46972981-lion-hd-wallpaper.jpg"
-mimeType: "image/jpeg"
-error: 0
#hashName: null
path: "C:\wamp64\tmp"
filename: "php6ED8.tmp"
basename: "php6ED8.tmp"
pathname: "C:\wamp64\tmp\php6ED8.tmp"
extension: "tmp"
realPath: "C:\wamp64\tmp\php6ED8.tmp"
aTime: 2021-08-02 17:55:21
mTime: 2021-08-02 17:55:21
cTime: 2021-08-02 17:55:21
inode: 75153818781832786
size: 21724
perms: 0100666
owner: 0
group: 0
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
linkTarget: "C:\wamp64\tmp\php6ED8.tmp"
}
]
When using the image transform plugin, the file name is replaced for the word "blob".
In some instances, the original file name is required by the server. In my case, I am uploading product images that tie to a specific product using this name.
FilePond.create($refs.input, {
imageResizeMode: 'contain',
imageResizeTargetWidth: 1500,
imageResizeTargetHeight: 1500,
imageTransformOutputMimeType: 'image/jpeg',
allowImageTransform: true,
});
Will produce a binary file upload with the following properties:
------WebKitFormBoundaryphp51Y8NEZqAWF1s
Content-Disposition: form-data; name="files[]"; filename="blob"
Content-Type: image/jpeg
...
Notice the "blob" filename. The original file name is now lost.
Hi Guys, need help.
I have this code that should resize big files to a limit of 2000 pixels width/height, and them create a thumbnail of 500px.
Works fine when images are below 2000 pixels, if they are smaller if appears if affecting the imageTransformVariants probably because there's no resized image and I get this: "Uncaught (in promise) TypeError: Cannot read property 'size' of undefined".
My point is now to use the original imagem for example to create a transform if the source file is smaller and there's no resize happening. Any thoughts ?
import * as FilePond from 'filepond';
// Import the plugin code
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageResize from 'filepond-plugin-image-resize';
import FilePondPluginImageTransform from 'filepond-plugin-image-transform';
import FilePondPluginImageCrop from 'filepond-plugin-image-crop';
// Register the plugin
FilePond.registerPlugin(
// register the Image Crop plugin with FilePond
FilePondPluginImageCrop,
FilePondPluginImagePreview,
FilePondPluginImageResize,
FilePondPluginImageTransform
);
// Create a multi file upload component
const inputElement = document.querySelector('.file01');
const pond = FilePond.create(inputElement,
{
imageTransformOutputQuality: 'image/jpeg',
imageResizeTargetWidth: 2000,
imageResizeMode: 'contain',
imageResizeUpscale: false,
// add imageTransformVariant settings
imageTransformVariants: {
'thumb_medium_': transforms => {
transforms.resize.size.width = 500;
return transforms;
}
},
onaddfile: (err, fileItem) => {
// console.log(err, fileItem.getMetadata('resize'));
},
// alter the output property
onpreparefile: (fileItem, outputFiles) => {
// loop over the outputFiles array
outputFiles.forEach(output => {
const img = new Image();
// output now is an object containing a `name` and a `file` property, we only need the `file`
img.src = URL.createObjectURL(output.file);
document.body.appendChild(img);
})}
});
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.