Domanda

I need to display an Image (~5000*~7000 px) on a canvas in a XUL desktop application. The image data comes from a C-DLL, which does basic image manipulating operations. I have performance problems with the methods i tried so far:

  1. I tried to encode the image as Base64 inside my dll and send the string via js-Ctypes to javascript and set the b64 string as source for a basic html image object.(~13-18secs to get the image onto the canvas)
  2. I tried to wirte the image as jpg to the harddisk and load it again in javascript (~3-4secs)
  3. i now have the following function which calls my C-DLL: (the vars scalFactor, pageNumber and pdfFilePath are irrelevant for my questions)

       copyImageData : function(pdfFilePath, pageNumber, canvas, scaleFactor) { 
         var startLoad = new Date();
         var ctx = canvas.getContext('2d');
         var imageData = ctx.createImageData(canvas.width, canvas.height);
         var buffer    = new ArrayBuffer(imageData.data.length);
         var buffer8   = new Uint8ClampedArray(buffer);
         var bufferPtr = ctypes.uint32_t.ptr(buffer);
    
         copyImageData(pdfFilePath, pageNumber, bufferPtr, canvas.width, canvas.height, 0, 0, scaleFactor);
    
         imageData.data.set(buffer8);
    
         ctx.putImageData(imageData, 0, 0);
         consoleService.logStringMessage("Operation load image took: " + (new Date() - startLoad));
    
       }
    

The copyImageData sends the informations to my DLL, which then fills the Arraybuffer with imagedata directly in C. This is possible because of the pointer: ctypes.uint32_t.ptr(buffer).

The problem now is, that the standart ".set" function (imagedata.data.set(buffer8);) is too slow. The ".set" function copies the provided data somewhere inside.(It takes about 0.3secs on a 2.6GHz CPU, and thats not fast enough)

Is it possible to directly set the data without copying it around? Is it possible to directly fill the arraybuffer of the canvas?

Does anyone have another idea how i can get this to be faster?

È stato utile?

Soluzione

Ok. I've solved my problem. The fastest way is to not let Javascript do anything at all :D The trick is to take the underlying buffer of the image object (Imagedata.data.buffer) and put a Uint8ClampedArray around it. The buffer of the image object will be directly filled inside the C-dll and is never been copied around by the "set" function of the image object.

This code takes 42ms to get the requiered data onto the canvas. Heres the code:

        copyImageData : function(pdfFilePath, pageNumber, canvas, offsetX, offsetY, scaleFactor) { 
            var startLoad = new Date();

            var ctx = canvas.getContext('2d');
            var imageData = ctx.createImageData(canvas.width, canvas.height);
            var buffer    = imageData.data.buffer;
            var buffer8   = new Uint8ClampedArray(buffer);
            var bufferPtr = ctypes.uint32_t.ptr(buffer);

            copyImageData(pdfFilePath, pageNumber, bufferPtr, canvas.width, canvas.height, offsetX, offsetY, scaleFactor);
            ctx.putImageData(imageData, 0, 0);
       }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top