Setting img.src to dataUrl Leaks Memory

后端 未结 5 885
萌比男神i
萌比男神i 2021-01-02 04:16

Below I\'ve created a simple test case that shows that when an img tag\'s src is set to different dataUrls, it leaks memory. It looks like the image data is never unloaded a

相关标签:
5条回答
  • 2021-01-02 04:53

    I'm also experiencing this issue and I do believe it's a browser bug. I see this happening in FF and Chrome as well. At least Chrome once had a similar bug that was fixed. I think it's not gone or not completely gone. I see a constant increase in memory when I set img.src repeatedly to unique images. I have filed a bug with Chromium, if you want to put some weight in :) https://code.google.com/p/chromium/issues/detail?id=309543&thanks=309543&ts=1382344039 (The bug triggering example does not necessarily generate a new unique image every time around, but at at least it does with a high probability)

    0 讨论(0)
  • 2021-01-02 05:04

    Setting the source to a fixed minimal dataURI after handling the image seems to fix the issue for me:

    const dummyPng = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII=';
    
    img.onload = () => {
        // ... process the image
        URL.revokeObjectURL(img.src);
        img.onload = null;
        img.src = dummyPng;
    };
    img.src = URL.createObjectURL(new window.Blob([new Uint8Array(data)], {type: 'image/png'}));
    
    0 讨论(0)
  • 2021-01-02 05:09

    I ended up doing a work around for the issue. The memory bloat only happens when the image.src is changed, so I just bypassed the Image object altogether. I did this by taking the dataUrl, converting it into binary (https://gist.github.com/borismus/1032746) then parsing it using jpg.js (https://github.com/notmasteryet/jpgjs). Using jpg.js I can then copy the image back to my canvas, so the Image element is completely bybassed thus negating the need to set its src attribute.

    0 讨论(0)
  • 2021-01-02 05:10

    Some solutions not mentioned in the other answers:

    For browser

    jpeg-js

    Similar to jpgjs mentioned by @PaulMilham, but with additional features and a nicer API (imo).

    For NodeJS/Electron

    sharp

    General purpose image-processing library for NodeJS, with functionality to both read and write jpeg, png, etc. images (as files, or just in memory).

    Since my program is in Electron, I ended up using sharp, as jpeg-js mentioned it as a more performant alternative (due to its core being written in native code).

    0 讨论(0)
  • 2021-01-02 05:15

    Panchosoft's answer solved this for me in Safari.

    This workaround avoids the memory increase by bypassing the leaking Image object.

    // Methods to address the memory leaks problems in Safari
    var BASE64_MARKER = ';base64,';
    var temporaryImage;
    var objectURL = window.URL || window.webkitURL;
    
    function convertDataURIToBlob(dataURI) {
        // Validate input data
        if(!dataURI) return;
    
        // Convert image (in base64) to binary data
        var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
        var base64 = dataURI.substring(base64Index);
        var raw = window.atob(base64);
        var rawLength = raw.length;
        var array = new Uint8Array(new ArrayBuffer(rawLength));
    
        for(i = 0; i < rawLength; i++) {
            array[i] = raw.charCodeAt(i);
        }
    
        // Create and return a new blob object using binary data
        return new Blob([array], {type: "image/jpeg"});
    }
    

    then, in the processImage rendering loop:

    // Destroy old image
    if(temporaryImage) objectURL.revokeObjectURL(temporaryImage);
    
    // Create a new image from binary data
    var imageDataBlob = convertDataURIToBlob(imageData);
    
    // Create a new object URL
    temporaryImage = objectURL.createObjectURL(imageDataBlob);
    
    // Set the new image
    image.src = temporaryImage;
    
    0 讨论(0)
提交回复
热议问题