Crop image from snapshot in flow

I made a sensor in my mailbox. Every time a letter is delivered, I get a notification with a snapshot from my camera, see below.

I actually want to crop it so that only the top left part is visible. Does anyone have any idea if that can be done in a flow?

Like this:

Voorkant - 10-3-2024, 14.38.24 GMT+2

Dont think you can crop without coding stuff. But I have an app that automatically crops down to any face that it sees:

Or maybe you can use free online services like this: Image Resize API: Online Image Crop & Resize & Optimization • Sirv

Thanks! I have now (with the help of ChatGPT) put this together. I still isn’t finished, but it’s promising!

// ----- Configuration -----

// Fill in your Sirv API Client ID and Client Secret
const clientId = 'your_client_id';
const clientSecret = 'your_client_secret';

// Replace 'your_account' with your Sirv account name
const accountName = 'your_account';

// The URL of the image you want to fetch and upload
const imageUrl = args[0] || 'https://example.com/image.jpg'; // Adjust this to your own image

// The location where you want to save the image on Sirv
const destinationPath = '/uploads/my_image.jpg'; // Adjust this as needed

// Specifications for cropping
const cropWidth = 600;  // Width for the crop (in pixels)
const cropHeight = 600; // Height for the crop (in pixels)
const cropX = 0;        // X position for the crop (in pixels)
const cropY = 0;        // Y position for the crop (in pixels)

// ----- Functions -----

// Function to retrieve the access token
async function getAccessToken() {
    const authUrl = 'https://api.sirv.com/v2/token';
    const response = await fetch(authUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            clientId: clientId,
            clientSecret: clientSecret
        })
    });

    if (!response.ok) {
        throw new Error('Error retrieving access token: ' + response.statusText);
    }

    const data = await response.json();
    return data.token; // This is the Bearer Token
}

// Function to download an image and convert it to ArrayBuffer (binary data)
async function downloadImageAsArrayBuffer(imageUrl) {
    const response = await fetch(imageUrl);
    if (!response.ok) {
        throw new Error('Error fetching the image: ' + response.statusText);
    }

    const arrayBuffer = await response.arrayBuffer();
    return arrayBuffer;  // This is the image as an arraybuffer (binary data)
}

// Function to upload the image to Sirv as a binary file
async function uploadImage(accessToken, imageBuffer, destinationPath) {
    const uploadUrl = `https://api.sirv.com/v2/files/upload?filename=${encodeURIComponent(destinationPath)}`;

    const response = await fetch(uploadUrl, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/octet-stream'  // Binary content type
        },
        body: imageBuffer  // Send the image as binary data
    });

    if (!response.ok) {
        throw new Error('Error uploading the image: ' + response.statusText);
    }

    console.log('Image successfully uploaded to Sirv.');
}

// Function to generate the cropped image URL using URL parameters
function getCroppedImageUrl(destinationPath, cropWidth, cropHeight, cropX, cropY) {
    const croppedImageUrl = `https://${accountName}.sirv.com${destinationPath}?cw=${cropWidth}&ch=${cropHeight}&cx=${cropX}&cy=${cropY}`;
    return croppedImageUrl;
}

// ----- Main Script -----

(async () => {
    try {
        // Step 1: Retrieve the access token
        const accessToken = await getAccessToken();
        console.log('Access token retrieved:', accessToken);

        // Step 2: Download the image and convert it to ArrayBuffer (binary data)
        const imageBuffer = await downloadImageAsArrayBuffer(imageUrl);
        console.log('Image successfully downloaded as binary data.');

        // Step 3: Upload the binary image to Sirv
        await uploadImage(accessToken, imageBuffer, destinationPath);

        // Step 4: Generate the cropped image URL using URL parameters
        const croppedImageUrl = getCroppedImageUrl(destinationPath, cropWidth, cropHeight, cropX, cropY);
        console.log('Cropped image URL:', croppedImageUrl);

        // Step 5: Update the Homey logical variable with the new value
        const vars = await Homey.logic.getVariables(); 
        const myVar = _.find(vars, (o) => o.name === "GecropteAfbeeldingURL"); // Adjust the name if necessary

        if (myVar) {
            await Homey.logic.updateVariable({id: myVar.id, variable: {value: croppedImageUrl}});
            console.log('The cropped image URL has been saved to the variable "GecropteAfbeeldingURL".');
        } else {
            console.error('Variable "GecropteAfbeeldingURL" not found.');
        }

    } catch (error) {
        console.error('An error occurred:', error.message);
    }
})();