# Crop image from snapshot in flow

**URL:** <https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263>\
**Category:** Questions & Help\
**Created:** [October 3, 2024, 12:38pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263 "2024-10-03T12:38:40Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Joosie](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/joosie/32/115600_2.png) [@Joosie](https://community.homey.app/u/Joosie)\
**Post date:** [October 3, 2024, 12:38pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/1 "2024-10-03T12:38:40Z")

</div>

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.

 ![Voorkant - 10-3-2024, 14.38.24 GMT+2](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/9/3/932aef9378a4517cd2e00f50e050077d18ae4dbc.jpeg)

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?

---

<div class="post-metadata">

**Author:** ![Joosie](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/joosie/32/115600_2.png) [@Joosie](https://community.homey.app/u/Joosie)\
**Post date:** [October 3, 2024, 12:39pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/2 "2024-10-03T12:39:35Z")

</div>

Like this:

![Voorkant - 10-3-2024, 14.38.24 GMT+2](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/b/7/b7c6e6bc742478962e74a3088457763ff7be903f.jpeg)

---

<div class="post-metadata">

**Author:** ![Gruijter](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/gruijter/32/1973_2.png) [@Gruijter](https://community.homey.app/u/Gruijter)\
**Post date:** [October 3, 2024, 12:49pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/3 "2024-10-03T12:49:15Z")

</div>

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

> **[Face++](https://homey.app/nl-nl/app/com.gruijter.facepp/Face++/)**
>
> Face recognition for Homey

Or maybe you can use free online services like this: [Image Resize API: Online Image Crop & Resize & Optimization • Sirv](https://sirv.com/features/image-resize-api/)

---

<div class="post-metadata">

**Author:** ![Joosie](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/joosie/32/115600_2.png) [@Joosie](https://community.homey.app/u/Joosie)\
**Post date:** [October 3, 2024, 3:02pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/4 "2024-10-03T15:02:30Z")

</div>

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

```auto
// ----- 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);
    }
})();

```

---

<div class="post-metadata">

**Author:** ![Joosie](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/joosie/32/115600_2.png) [@Joosie](https://community.homey.app/u/Joosie)\
**Post date:** [July 24, 2026, 12:49pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/5 "2026-07-24T12:49:28Z")

</div>

Just a little update. Sirv let me down lately so I developed an app (with the help of Claude) and now its’ published.

It does not only run faster, but more reliable and local!

> **[Afbeelding Uitknippen | Homey](https://homey.app/nl-nl/app/nl.blankestijnict.imagecrop/Afbeelding-Uitknippen/)**
>
> Knip afbeeldingen uit binnen een Homey flow.

---

<div class="post-metadata">

**Author:** ![SunBeech](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/sunbeech/32/111391_2.png) [@SunBeech](https://community.homey.app/u/SunBeech)\
**Post date:** [July 24, 2026, 1:04pm UTC](https://community.homey.app/t/crop-image-from-snapshot-in-flow/117263/6 "2026-07-24T13:04:48Z")

</div>

FYI - If you replace your language specific link with the non-specific one, then users will be redirected to their local language version in the Homey App Store when clicking the link: [Image Crop | Homey](https://homey.app/a/nl.blankestijnict.imagecrop/) 😀.
