0
votes

???? Issue

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.

????️ Architecture

Edite web app architecture or more about here

⚙️ Reproduce the issue

You can reproduce this issue by cloning the Edite GitHub repository and following the guide to set up the services.

???? Code

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.

1

1 Answers

1
votes

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:

  1. If you want the original image on Cloudinary to be the one with the filters applied you will want to use an incoming transformation. This is where the requested Cloudinary transformations will be applied on the image before it's stored in your account. The output image with the transformations applied will be what is stored in your account.
  2. The alternative is to upload the original image (untouched) and requesting to generate the transformed versions using eager transformations. This would create a situation where the original image does not have any transformations and you would create 'derived' versions with different transformations, which in your case will be the transformations based on the JSON file.