Search code examples
c#wpfpointersimagesource

ImageSource from 3 IntPtr


I get three IntPtr's to the arrays of the RGB channels from an external library. At the moment I merge the three arrays to one and create an ImageSource from the new array.

But the images can be really huge (at the moment up to 8000 x 4000 px), so the conversion of the data, which are already laying in the memory takes too long.

Is there a way to use these pointers to show the image in a canvas without copying? I.e. a derived class of ImageSource with costum OnRender method or something else?

I didn't found anything belongs to my problem.

Update: My current code looks like this:

int unmapByes = Math.Abs(stride) - (width * 3);
        byte* _ptrR = (byte*)ptrR;
        byte* _ptrG = (byte*)ptrG;
        byte* _ptrB = (byte*)ptrB;
        BitmapSource bmpsrc = null;
        App.Current.Dispatcher.Invoke(() =>
        {
            bmpsrc = BitmapSource.Create(width,
                                                  height,
                                                  96,
                                                  96,
                                                  PixelFormats.Bgr24,
                                                  null,
                                                  new byte[bytes],
                                                  stride);
        });
        BitmapBuffer bitmapBuffer = new BitmapBuffer(bmpsrc);
        byte* buffer = (byte*)bitmapBuffer.BufferPointer;


        Parallel.For(0, bytes / 3 - height, (offset) =>
        {
            int i = offset * 3 + (((offset + 1) / width)) * unmapByes;
            *(buffer + i) = *(_ptrB + offset);
            *(buffer + i + 1) = *(_ptrG + offset);
            *(buffer + i + 2) = *(_ptrR + offset);
        });
        return bmpsrc;

Solution

  • The right answer is:

    Get rid of computations in the loop, which have high costs. In this case it is the division. Computations with high costs are every computation which is not in the instruction set of the CPU.

    The second one is, that a Parallel.For loop can increase the speed, but only if every Thread of the loop has a bigger amount of work. Otherwise the costs for the handling are too high.

    So now I changed my code and use a Parallel.For loop for each line and an inner for loop for each pixel in this line.

    Now I can convert an image with the size of 8000x4000 24rgb in 32ms (on my system I can say 1 Megapixel = 1ms).

    For the future: Everyone who has a question wants to know, why his question was voted down. If you don't know the answer or only write bull***t, stop it.