# Add multiple User Pictures to Task Card when Multiple users are assigned

**URL:** <https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615>\
**Category:** Ask for Help\
**Created:** [April 29, 2025, 11:54am UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615 "2025-04-29T11:54:30Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![AndrewJ](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/andrewj/32/84903_2.png) [@AndrewJ](https://community.glideapps.com/u/AndrewJ)\
**Post date:** [April 29, 2025, 11:54am UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/1 "2025-04-29T11:54:30Z")

</div>

Hey all, I’m building a Task Management module inside my app and made it so that multiple App users can be assigned a task. When only 1 user is assigned the correct user picture shows up on the card (see #1 on screenshot). When multiple users are assigned no picture shows up (see #2). Is there a way to organize my database so that both pictures show up on the card?

Thanks all!

 ![image](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/3/f/3fee59731ebf7490ba47547b3152c293e2adc8ef.png)

---

<div class="post-metadata">

**Author:** ![ThinhDinh](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/thinhdinh/32/49_2.png) [@ThinhDinh](https://community.glideapps.com/u/ThinhDinh)\
**Post date:** [April 29, 2025, 2:01pm UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/2 "2025-04-29T14:01:15Z")

</div>

You would have to find a way to bundle multiple images together using Cloudinary, there’s no easy native way to do it I think.

---

<div class="post-metadata">

**Author:** ![MaximeBaker](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/maximebaker/32/80877_2.png) [@MaximeBaker](https://community.glideapps.com/u/MaximeBaker)\
**Post date:** [April 29, 2025, 3:28pm UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/3 "2025-04-29T15:28:20Z")

</div>

Create a JavaScript column and put this code:

```html
function calculateDimensions(images, sizeAdjustment, keepRatio, isVertical) {
    let totalWidth = 0;
    let totalHeight = 0;
    const dimensions = [];

    images.forEach(img => {
        let width = img.width;
        let height = img.height;

        if (sizeAdjustment === "reduce") {
            const scale = Math.min(width / img.width, height / img.height);
            width = img.width * scale;
            height = img.height * scale;
        }

        dimensions.push({ width, height });

        if (isVertical) {
            totalWidth = Math.max(totalWidth, width);
            totalHeight += height;
        } else {
            totalWidth += width;
            totalHeight = Math.max(totalHeight, height);
        }
    });

    return {
        totalWidth,
        totalHeight,
        dimensions
    };
}

function mergeImages(imageUrls) {
    return new Promise((resolve, reject) => {
        if (!imageUrls || imageUrls.length < 2) {
            reject('Please provide an array with at least two image URLs to merge');
            return;
        }

        // Create new Image objects to ensure images are fully loaded
        const loadImages = (urls) => {
            return Promise.all(urls.map(url => {
                return new Promise((resolve, reject) => {
                    const img = new Image();
                    img.crossOrigin = "Anonymous";
                    img.onload = () => resolve(img);
                    img.onerror = (event) => reject(new Error(`Failed to load image: ${url}`));
                    img.src = url;
                });
            }));
        };

        loadImages(imageUrls)
            .then(images => {
                // Create a temporary canvas
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                const isVertical = true;
                const borderWidth = 0;
                const borderColor = "#ffffff";
                const sizeAdjustment = "reduce";
                const keepRatio = true;

                // Calculate dimensions
                let dims = calculateDimensions(images, sizeAdjustment, keepRatio, isVertical);

                // Set canvas size
                if (isVertical) {
                    canvas.width = dims.totalWidth;
                    canvas.height = dims.totalHeight + (borderWidth * (images.length - 1));
                } else {
                    canvas.width = dims.totalWidth + (borderWidth * (images.length - 1));
                    canvas.height = dims.totalHeight;
                }

                // Draw images on the canvas
                let offset = 0;
                images.forEach((img, index) => {
                    const dim = dims.dimensions[index];
                    if (isVertical) {
                        ctx.drawImage(img, 0, offset, dim.width, dim.height);
                        offset += dim.height + borderWidth;
                    } else {
                        ctx.drawImage(img, offset, 0, dim.width, dim.height);
                        offset += dim.width + borderWidth;
                    }

                    if (borderWidth > 0 && index < images.length - 1) {
                        if (isVertical) {
                            ctx.fillStyle = borderColor;
                            ctx.fillRect(0, offset - borderWidth, canvas.width, borderWidth);
                        } else {
                            ctx.fillStyle = borderColor;
                            ctx.fillRect(offset - borderWidth, 0, borderWidth, canvas.height);
                        }
                    }
                });

                // Convert to base64 with compression
                const base64Image = canvas.toDataURL('image/jpeg', 0.7); // Adjust compression quality here

                // Upload to ImgBB
                uploadToImgBB(base64Image)
                    .then(uploadedUrl => resolve(uploadedUrl))
                    .catch(error => reject('Error uploading image: ' + error.message));
            })
            .catch(error => {
                reject('Error merging images: ' + error.message);
            });
    });
}

async function uploadToImgBB(base64Image) {
    const apiUrl = 'https://api.imgbb.com/1/upload';
    const apiKey = p3; // Ensure p3 contains your ImgBB API key
    const imageData = base64Image.split(',')[1]; // Remove the base64 prefix

    const formData = new FormData();
    formData.append('key', apiKey);
    formData.append('image', imageData);
    formData.append('expiration', '600'); // Set expiration to 600 seconds as per your example

    const response = await fetch(apiUrl, {
        method: 'POST',
        body: formData
    });

    if (!response.ok) {
        throw new Error(`Failed to upload image: ${response.statusText}`);
    }

    const result = await response.json();
    if (result.success) {
        return result.data.url;
    } else {
        throw new Error(result.error.message);
    }
}

// Usage example:
const imageUrls = JSON.parse(p1); // Ensure p1 contains a JSON string of image URLs
return await mergeImages(imageUrls)
    .then(uploadedUrl => {
        console.log('Uploaded image URL:', uploadedUrl);
        return uploadedUrl;
    })
    .catch(error => {
        console.error(error);
    });

```

In p1, put images’ url in the following format: [“url1”,“url2”,“url3”].  
In p3, put your imgbb api key. Create a random account because that API key will be visible to everyone. Not a big deal in this case.

Url the returned URL from the Javascript column in your image component:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/a/7/a75721023fe13868829a658a8665262bce8b95ea.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/8/1/819f0c9106fd3be4ad4d1f414c3e23ae37a6cf4a.png)

> **Source**  
> Base source code from: [Merge two images online](https://mate.tools/merge-images), heavily modified by chat.mistral.ai.

---

<div class="post-metadata">

**Author:** ![ThinhDinh](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/thinhdinh/32/49_2.png) [@ThinhDinh](https://community.glideapps.com/u/ThinhDinh)\
**Post date:** [April 29, 2025, 11:54pm UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/4 "2025-04-29T23:54:29Z")

</div>

> [@camera\_with\_flash Combining multiple images to form a dynamic image with Cloudinary](https://community.glideapps.com/t/combining-multiple-images-to-form-a-dynamic-image-with-cloudinary/13375):
>
> Recently I came across a challenge where I needed an image which included various images from different profiles, some icons and some lines based on conditions. I didn’t think it was possible until I tried to dig deeper and play around with Cloudinary and I eventually found a way to achieve it. This one image consists of 6 different images: 3 Profile pictures 2 line images on either side (Both are dynamic and are governed by conditions so when the status changes, the lines b…

Something like this, @Robert_Petitto has already had a prototype with multiple circles next to each other but I can’t seem to find the keyword for that post.

---

<div class="post-metadata">

**Author:** ![Robert\_Petitto](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/robert_petitto/32/25193_2.png) [@Robert\_Petitto](https://community.glideapps.com/u/Robert_Petitto)\
**Post date:** [April 30, 2025, 5:33am UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/5 "2025-04-30T05:33:44Z")

</div>

> [@busts\_in\_silhouette Overlapping Avatars!](https://community.glideapps.com/t/overlapping-avatars/68285):
>
> Here’s a relatively easy way to get an overlapping avatars effect. Create a comma separated string of image URLS using a join list column (most likely from a multiple relation) Create a JavaScript column with the code below. Point variable p1 to the image URL CSV column Create a rich text component and set the source as the JavaScript column [[Create Overlapping Avatars in Glide] ](https://www.youtube.com/watch?v=NnfKQd_9KpQ) function generateHtmlFromCsv(csvString) { const imageUrls = csvString.split(','); //…

---

<div class="post-metadata">

**Author:** ![Robert\_Petitto](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/robert_petitto/32/25193_2.png) [@Robert\_Petitto](https://community.glideapps.com/u/Robert_Petitto)\
**Post date:** [April 30, 2025, 5:34am UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/6 "2025-04-30T05:34:14Z")

</div>

I also have an experimental code column: `https://rpetitto.github.io/avatars`

---

<div class="post-metadata">

**Author:** ![AndrewJ](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/andrewj/32/84903_2.png) [@AndrewJ](https://community.glideapps.com/u/AndrewJ)\
**Post date:** [September 1, 2025, 1:33pm UTC](https://community.glideapps.com/t/add-multiple-user-pictures-to-task-card-when-multiple-users-are-assigned/81615/7 "2025-09-01T13:33:08Z")

</div>

Thanks all for this help. Sorry for the late thank you
