Search code examples
javascriptes6-promise

javascript promises does not work as expected while image combining


below is my javascript code which i use for combining 64 images to generate a panorama image. but when i load it first time it gives me broken image however at seconds or third time it gives me right image. In Below combine function do all image combine process, combinedArray contains all urls of images.

     function combine(imgSources, width, height, right, left) {
    
                return Promise.all(imgSources.map(function (url) {
                   
    
                    return new Promise(function (resolve) {
                        let img = new Image();
                        img.crossOrigin = `anonymous`;
                        img.src = url;
                        img.onload = function () {resolve(img);};
    
                    });
                })).then(function (images) {
                   
                    let canvas =           document.createElement(`canvas`);
                    canvas.width = width;
                    canvas.height = height;
                    // draw images to the canvas
                    let ctx = canvas.getContext(`2d`);
                    for (let i = 0; i < imgSources.length; i++) {
                        ctx.drawImage(images[i], right * i, left * i);
                    }
                    // return the resulting image in base64 form
                    return canvas.toDataURL(`image/jpeg`);
                });
            }
    
            function generateParonama(angle = 10) {
                let url=`https://cdn.yourvrtours.com/000679.fcf5f084b8794573a6789774f9bfcbaf.1122/A4CDD7C7-3F58-435A-9A5B-9522078DE10B/optimized/Point_7537F461-3868-4EFB-9B82-3A1E3CF81955/3/`;
                let mainImage;
               
                let allSides = [`f`, `r`, `b`, `l`];
                let allImages = [];
                let combinedArray = [];
                let ind = 0;
    
                
    
                // generates array for all 64 images 
                function genareteArray() {
                    for (let index = 0; index < allSides.length; index++) {
                        for (let i = 0; i < 4; i++) {
                            for (let j = 0; j < 4; j++) {
                                let t = `${url + allSides[index] + j + '_' + i}.jpg`;
                                combinedArray.push(t);
                            }
                        }
                    }
                }
    
    
    
    
            
    
                // arrange array at given angle
                function reArrangeArray() {
                    let position = 0 / 22.5;
                   
                    let array2 = [];
    
                    if (position <= 8) {
                        position = (position + 8) * 4;
    
                        array2 = combinedArray.slice(position, 64);
                        combinedArray.splice(position)
                        combinedArray = array2.concat(combinedArray)
                    }
                    else {
                        position = (position - 8) * 4;
                        array2 = combinedArray.slice(0, position);
                        combinedArray.push(array2)
                    }
                }
    
    
                genareteArray();
                reArrangeArray();
                allSides.map((side, i) => {
    
                    return new Promise((res) => {
    
                        for (let index = 0; index < 4; index++) {
    
                            combine(
                                [
                                    combinedArray[0 + ind],
                                    combinedArray[1 + ind],
                                    combinedArray[2 + ind],
                                    combinedArray[3 + ind],
                                ], 512, 2048, 0, 512)
                                .then(function (result) {
                                 
                                    // result will be a column of 512 box
                                    allImages.push(result);
    
                                    if (allImages.length > 15) {
                                        combine(allImages, 8192, 2048, 512, 0).then((r) => {
                                         
                                                    var img = new Image();
                                        img.src = r;
                                        document.body.appendChild(img);
                                               
    
                                        });
                                    }
    
                                });
                            ind = ind + 4;
                        }
                    });
    
                });
            }

  generateParonama(10);
img{
max-width:600px;
}


Solution

  • Can you try this -

    function combine(imgSources, width, height, right, left) {
    
        return Promise.all(imgSources.map(function (url) {
            return new Promise(function (resolve) {
                let img = new Image();
                img.crossOrigin = `anonymous`;
                img.src = url;
                img.onload = function () { resolve(img); };
    
            });
        })).then(function (images) {
    
            let canvas = document.createElement(`canvas`);
            canvas.width = width;
            canvas.height = height;
            // draw images to the canvas
            let ctx = canvas.getContext(`2d`);
            for (let i = 0; i < imgSources.length; i++) {
                ctx.drawImage(images[i], right * i, left * i);
            }
            // return the resulting image in base64 form
            return canvas.toDataURL(`image/jpeg`);
        });
    }
    
    async function generateParonama(angle = 10) {
        let url = `https://cdn.yourvrtours.com/000679.fcf5f084b8794573a6789774f9bfcbaf.1122/A4CDD7C7-3F58-435A-9A5B-9522078DE10B/optimized/Point_7537F461-3868-4EFB-9B82-3A1E3CF81955/3/`;
        let mainImage;
    
        let allSides = [`f`, `r`, `b`, `l`];
        let allImages = [];
        let combinedArray = [];
        let ind = 0;
    
        // generates array for all 64 images 
        function genareteArray() {
            for (let index = 0; index < allSides.length; index++) {
                for (let i = 0; i < 4; i++) {
                    for (let j = 0; j < 4; j++) {
                        let t = `${url + allSides[index] + j + '_' + i}.jpg`;
                        combinedArray.push(t);
                    }
                }
            }
        }
    
        // arrange array at given angle
        function reArrangeArray() {
            let position = 0 / 22.5;
    
            let array2 = [];
    
            if (position <= 8) {
                position = (position + 8) * 4;
    
                array2 = combinedArray.slice(position, 64);
                combinedArray.splice(position)
                combinedArray = array2.concat(combinedArray)
            }
            else {
                position = (position - 8) * 4;
                array2 = combinedArray.slice(0, position);
                combinedArray.push(array2)
            }
        }
    
        genareteArray();
        reArrangeArray();
        console.log(combinedArray);
    
        for (let i = 0; i < allSides.length; i++) {
            const side = allSides[i];
    
            for (let index = 0; index < 4; index++) {
                var result = await combine(
                    [
                        combinedArray[0 + ind],
                        combinedArray[1 + ind],
                        combinedArray[2 + ind],
                        combinedArray[3 + ind],
                    ], 512, 2048, 0, 512);
    
                // result will be a column of 512 box
                allImages.push(result);
    
                if (allImages.length > 15) {
                    var r = await combine(allImages, 8192, 2048, 512, 0);
                    var img = new Image();
                    img.src = r;
                    document.body.appendChild(img);
                }
    
                ind = ind + 4;
            }
        }
    }
    
    generateParonama(10);
    
    
    

    It is not the most efficient way of using promises. I only used async-await feature to make sure image components are getting loaded in sequence.

    As an example this solution might be made more efficient by using Promise.All API (you can it by altering my code)