I'm making an app to edit images and I'm stuck when it is about downloading the images after applying the filters. As expected, the user can drag & drop (or just upload) an image (creating a dynamic URL on Cloudinary) and apply the CSS filters to the uploaded image.
So, basically, I want to save the image into the Cloudinary API, but also applying the filters.
Edite web app architecture or more about here
You can reproduce this issue by cloning the Edite GitHub repository and following the guide to set up the services.
Note: see that src is the root
components/Toolbar/Right/options.json
[
{
"property": "brightness",
"value": 100,
"range": {
"min": 0,
"max": 100
},
"unit": "%"
},
{
"property": "contrast",
"value": 100,
"range": {
"min": 0,
"max": 200
},
"unit": "%"
},
{
"property": "saturate",
"value": 100,
"range": {
"min": 0,
"max": 200
},
"unit": "%"
},
{
"property": "grayscale",
"value": 0,
"range": {
"min": 0,
"max": 100
},
"unit": "%"
},
{
"property": "sepia",
"value": 0,
"range": {
"min": 0,
"max": 100
},
"unit": "%"
},
{
"property": "invert",
"value": 0,
"range": {
"min": 0,
"max": 100
},
"unit": "%"
},
{
"property": "hue-rotate",
"value": 0,
"range": {
"min": 0,
"max": 360
},
"unit": "deg"
}
]
components/FileUploader/index.js
function FileUploader() {
// Image uploading states
const dndRef = useRef(); // Access DnD element reference and its current state
const [isDragging, setIsDragging] = useState(false);
const [isUploading, setIsUploading] = useState(false);
const [uploadedImageUrl, setUploadedImageUrl] = useState('');
const [src, { blur }] = useProgressiveImg(
'',
uploadedImageUrl
);
const [uploadedImageName, setUploadedImageName] = useState('image');
// CSS Filters
const { activeTool } = useContext(ToolsContext);
const [options, setOptions] = useState(DEFAULT_OPTIONS);
const selectedFilter = options[activeTool];
// Get the file's data and send to clodinary
const onFileChange = async e => {
let formData = new FormData();
formData.append('file', e.target.files[0]);
formData.append('upload_preset', 'Edite_App');
setIsUploading(true);
let data = await api.post('/image/upload', formData);
const file = data.data;
setIsDragging(false);
setIsUploading(false);
setUploadedImageUrl(file.secure_url);
setUploadedImageName(file.original_filename);
}
// Get slider value according to the tools
const handleSliderChange = ({ target }) => {
setOptions(prevOptions => {
return prevOptions.map((option, index) => {
if (index !== activeTool) return option
return { ...option, value: target.value }
})
})
}
// Get CSS filters and return as a object
const handleImageStyling = async () => {
const filters = options.map(option => {
return `${option.property}(${option.value}${option.unit})`
})
return filters.join(' ');
I }
}
Note: To explain better and not just give too much code, you see above that, basically, I get a CSS filters list (JSON file) and also use Cloudinary API to post the data and create a dynamic URL. Although Cloudinary has support for image transformations, I always get stuck on this topic.
Cloudinary won't be able to use the filters in the JSON format, therefore, you will want to map these filters from the JSON file into Cloudinary image transformations. To do that, you will want to create some code/class that handles different input options from your JSON file and converts them to syntax using Cloudinary transformations. E.g. Brightness to e_brightness, Sepia effect to e_sepia etc.
Once you do that there are two options: