Passing bitmap from C# to C++ via a struct











up vote
4
down vote

favorite
1












First, I've read the a few questions regarding this issue, the most helpful being:
https://stackoverflow.com/questions/27463876/passing-bitmap-from-c-sharp-to-c



I was unable to get the provided solutions to work as I kept getting an AccessViolationException.



What I'm attempting to do is pass bitmap data to an unmanaged c++ dll. To do this I created a struct which holds a pointer to the image data as well as its length. I'm using a struct as I plan on passing in multiple images (in a single call) to the unmanaged API.



What I implemented works but I have a feeling there is probably some serious drawbacks so I'm curious as to what those drawbacks could be.



My current solution uses a generic pointer to hold the image data. This of course would be a drawback as I lose type safety. Anyway here is the relevant code.





C++ dll



raw_image.h



struct raw_image
{
void* data;
int size;
};


alignment.cpp (exports)



ALIGNMENT_API void submit( raw_image& img )
{
cv::Mat mat = cv::imdecode( cv::_InputArray(
static_cast<uchar*>( img.data ), img.size ), cv::IMREAD_COLOR );
cv::imshow( "image", mat );
cv::waitKey( );
cv::destroyWindow( "image" );
}




C# dll



RawImage.cs



[StructLayout( LayoutKind.Sequential )]
internal unsafe struct RawImage
{
internal void* ImageData;
internal int Size;
}


Aligner.cs (import)



[DllImport( "alignment-vc141-mtd-x64.dll", CallingConvention = 
CallingConvention.Cdecl )]
static extern void submit( RawImage img );


And this is where I pass the image to the unmanaged API.



using( var bitmap = new Bitmap( "AlignmentCenter.jpg" ) )
using( var stream = new MemoryStream( ) )
{
bitmap.Save( stream, ImageFormat.Jpeg );
var source = stream.ToArray( );
fixed( void* ptr = source )
{
var raw = new RawImage
{
ImageData = ptr,
Size = source.Length
};
submit( raw );
}
}


Is what I'm doing unsafe? Am I copying more than I should?
One last thing, I know about EmguCv and I've used it in the past but I won't be using it here.










share|improve this question









New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 2




    You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
    – t3chb0t
    2 days ago












  • @t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
    – WBuck
    2 days ago












  • When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
    – t3chb0t
    2 days ago










  • What do you mean by "Am I copying more than I should?"?
    – Henrik Hansen
    2 days ago










  • @HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
    – WBuck
    2 days ago















up vote
4
down vote

favorite
1












First, I've read the a few questions regarding this issue, the most helpful being:
https://stackoverflow.com/questions/27463876/passing-bitmap-from-c-sharp-to-c



I was unable to get the provided solutions to work as I kept getting an AccessViolationException.



What I'm attempting to do is pass bitmap data to an unmanaged c++ dll. To do this I created a struct which holds a pointer to the image data as well as its length. I'm using a struct as I plan on passing in multiple images (in a single call) to the unmanaged API.



What I implemented works but I have a feeling there is probably some serious drawbacks so I'm curious as to what those drawbacks could be.



My current solution uses a generic pointer to hold the image data. This of course would be a drawback as I lose type safety. Anyway here is the relevant code.





C++ dll



raw_image.h



struct raw_image
{
void* data;
int size;
};


alignment.cpp (exports)



ALIGNMENT_API void submit( raw_image& img )
{
cv::Mat mat = cv::imdecode( cv::_InputArray(
static_cast<uchar*>( img.data ), img.size ), cv::IMREAD_COLOR );
cv::imshow( "image", mat );
cv::waitKey( );
cv::destroyWindow( "image" );
}




C# dll



RawImage.cs



[StructLayout( LayoutKind.Sequential )]
internal unsafe struct RawImage
{
internal void* ImageData;
internal int Size;
}


Aligner.cs (import)



[DllImport( "alignment-vc141-mtd-x64.dll", CallingConvention = 
CallingConvention.Cdecl )]
static extern void submit( RawImage img );


And this is where I pass the image to the unmanaged API.



using( var bitmap = new Bitmap( "AlignmentCenter.jpg" ) )
using( var stream = new MemoryStream( ) )
{
bitmap.Save( stream, ImageFormat.Jpeg );
var source = stream.ToArray( );
fixed( void* ptr = source )
{
var raw = new RawImage
{
ImageData = ptr,
Size = source.Length
};
submit( raw );
}
}


Is what I'm doing unsafe? Am I copying more than I should?
One last thing, I know about EmguCv and I've used it in the past but I won't be using it here.










share|improve this question









New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 2




    You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
    – t3chb0t
    2 days ago












  • @t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
    – WBuck
    2 days ago












  • When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
    – t3chb0t
    2 days ago










  • What do you mean by "Am I copying more than I should?"?
    – Henrik Hansen
    2 days ago










  • @HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
    – WBuck
    2 days ago













up vote
4
down vote

favorite
1









up vote
4
down vote

favorite
1






1





First, I've read the a few questions regarding this issue, the most helpful being:
https://stackoverflow.com/questions/27463876/passing-bitmap-from-c-sharp-to-c



I was unable to get the provided solutions to work as I kept getting an AccessViolationException.



What I'm attempting to do is pass bitmap data to an unmanaged c++ dll. To do this I created a struct which holds a pointer to the image data as well as its length. I'm using a struct as I plan on passing in multiple images (in a single call) to the unmanaged API.



What I implemented works but I have a feeling there is probably some serious drawbacks so I'm curious as to what those drawbacks could be.



My current solution uses a generic pointer to hold the image data. This of course would be a drawback as I lose type safety. Anyway here is the relevant code.





C++ dll



raw_image.h



struct raw_image
{
void* data;
int size;
};


alignment.cpp (exports)



ALIGNMENT_API void submit( raw_image& img )
{
cv::Mat mat = cv::imdecode( cv::_InputArray(
static_cast<uchar*>( img.data ), img.size ), cv::IMREAD_COLOR );
cv::imshow( "image", mat );
cv::waitKey( );
cv::destroyWindow( "image" );
}




C# dll



RawImage.cs



[StructLayout( LayoutKind.Sequential )]
internal unsafe struct RawImage
{
internal void* ImageData;
internal int Size;
}


Aligner.cs (import)



[DllImport( "alignment-vc141-mtd-x64.dll", CallingConvention = 
CallingConvention.Cdecl )]
static extern void submit( RawImage img );


And this is where I pass the image to the unmanaged API.



using( var bitmap = new Bitmap( "AlignmentCenter.jpg" ) )
using( var stream = new MemoryStream( ) )
{
bitmap.Save( stream, ImageFormat.Jpeg );
var source = stream.ToArray( );
fixed( void* ptr = source )
{
var raw = new RawImage
{
ImageData = ptr,
Size = source.Length
};
submit( raw );
}
}


Is what I'm doing unsafe? Am I copying more than I should?
One last thing, I know about EmguCv and I've used it in the past but I won't be using it here.










share|improve this question









New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











First, I've read the a few questions regarding this issue, the most helpful being:
https://stackoverflow.com/questions/27463876/passing-bitmap-from-c-sharp-to-c



I was unable to get the provided solutions to work as I kept getting an AccessViolationException.



What I'm attempting to do is pass bitmap data to an unmanaged c++ dll. To do this I created a struct which holds a pointer to the image data as well as its length. I'm using a struct as I plan on passing in multiple images (in a single call) to the unmanaged API.



What I implemented works but I have a feeling there is probably some serious drawbacks so I'm curious as to what those drawbacks could be.



My current solution uses a generic pointer to hold the image data. This of course would be a drawback as I lose type safety. Anyway here is the relevant code.





C++ dll



raw_image.h



struct raw_image
{
void* data;
int size;
};


alignment.cpp (exports)



ALIGNMENT_API void submit( raw_image& img )
{
cv::Mat mat = cv::imdecode( cv::_InputArray(
static_cast<uchar*>( img.data ), img.size ), cv::IMREAD_COLOR );
cv::imshow( "image", mat );
cv::waitKey( );
cv::destroyWindow( "image" );
}




C# dll



RawImage.cs



[StructLayout( LayoutKind.Sequential )]
internal unsafe struct RawImage
{
internal void* ImageData;
internal int Size;
}


Aligner.cs (import)



[DllImport( "alignment-vc141-mtd-x64.dll", CallingConvention = 
CallingConvention.Cdecl )]
static extern void submit( RawImage img );


And this is where I pass the image to the unmanaged API.



using( var bitmap = new Bitmap( "AlignmentCenter.jpg" ) )
using( var stream = new MemoryStream( ) )
{
bitmap.Save( stream, ImageFormat.Jpeg );
var source = stream.ToArray( );
fixed( void* ptr = source )
{
var raw = new RawImage
{
ImageData = ptr,
Size = source.Length
};
submit( raw );
}
}


Is what I'm doing unsafe? Am I copying more than I should?
One last thing, I know about EmguCv and I've used it in the past but I won't be using it here.







c# c++ image opencv native-code






share|improve this question









New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 2 days ago









200_success

127k15148411




127k15148411






New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 2 days ago









WBuck

1233




1233




New contributor




WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






WBuck is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 2




    You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
    – t3chb0t
    2 days ago












  • @t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
    – WBuck
    2 days ago












  • When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
    – t3chb0t
    2 days ago










  • What do you mean by "Am I copying more than I should?"?
    – Henrik Hansen
    2 days ago










  • @HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
    – WBuck
    2 days ago














  • 2




    You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
    – t3chb0t
    2 days ago












  • @t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
    – WBuck
    2 days ago












  • When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
    – t3chb0t
    2 days ago










  • What do you mean by "Am I copying more than I should?"?
    – Henrik Hansen
    2 days ago










  • @HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
    – WBuck
    2 days ago








2




2




You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
– t3chb0t
2 days ago






You could create a c++/cli wrapper for the native API and let it do the hard lifting with pointers and calling the native function so that you can keep your C# code clean.
– t3chb0t
2 days ago














@t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
– WBuck
2 days ago






@t3chb0t I originally planned on using C++/CLI for this, but ended up just using pinvoke for its simplicity. I'm not very familiar with C++/CLI. That being said, at the end of the day, if C++/CLI is the better option than I'll write a wrapper around the unmanaged dll.
– WBuck
2 days ago














When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
– t3chb0t
2 days ago




When not using system functions I find such a wrapper easier to use than pinvoke because with it you can use C# more naturally without the native stuff and you can work with the native stuff without workarounds inside the C++/CLI wrapper because it can more naturally communicate with native code.
– t3chb0t
2 days ago












What do you mean by "Am I copying more than I should?"?
– Henrik Hansen
2 days ago




What do you mean by "Am I copying more than I should?"?
– Henrik Hansen
2 days ago












@HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
– WBuck
2 days ago




@HenrikHansen Currently I'm copying the contents of the Bitmap in to the MemoryStream. I was curious if this was necessary, or if I should use the Bitmap's scan0 property, and locking the Bitmap's pixels and then passing an IntPtr to the unmanaged API..
– WBuck
2 days ago










2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










There is not much to review. The only thing I can contribute with is that you don't have to run in unsafe mode:



If you define the data structure as:



  [StructLayout(LayoutKind.Sequential)]
internal struct RawImage
{
internal IntPtr ImageData;
internal int Size;
}


Then you can run the .NET side as:



  using (var bitmap = new Bitmap(@"fileName.Jpeg"))
using (var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Jpeg);
var source = stream.ToArray();

IntPtr handle = IntPtr.Zero;

try
{
handle = Marshal.AllocHGlobal(source.Length);
Marshal.Copy(source, 0, handle, source.Length);

var raw = new RawImage
{
ImageData = handle,
Size = source.Length
};
submit(raw);
}
catch (Exception ex)
{
if (handle != IntPtr.Zero)
{
Marshal.FreeHGlobal(handle);
}
}
}


The above works with the same signature for submit(RawImage img).



It's a little more code, but you are not limiting the use of your module.






share|improve this answer























  • Yeah I prefer this solution, more C# friendly.
    – WBuck
    2 days ago


















up vote
3
down vote













Both your and Henrik's approach can be optimized by replacing stream.ToArray() with stream.GetBuffer(). This returns the MemoryStream's internal buffer array instead of making a copy.



You do have to take into account that the buffer can be larger than the actual data, so use the Length of the stream, not of the buffer. It's also possible that the data doesn't start at index 0, but that's only the case if you used one of the MemoryStream constructors that accepts an array, index and count. No problem here, but something to keep in mind if you want to generalize this.






share|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });






    WBuck is a new contributor. Be nice, and check out our Code of Conduct.










     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208070%2fpassing-bitmap-from-c-to-c-via-a-struct%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted










    There is not much to review. The only thing I can contribute with is that you don't have to run in unsafe mode:



    If you define the data structure as:



      [StructLayout(LayoutKind.Sequential)]
    internal struct RawImage
    {
    internal IntPtr ImageData;
    internal int Size;
    }


    Then you can run the .NET side as:



      using (var bitmap = new Bitmap(@"fileName.Jpeg"))
    using (var stream = new MemoryStream())
    {
    bitmap.Save(stream, ImageFormat.Jpeg);
    var source = stream.ToArray();

    IntPtr handle = IntPtr.Zero;

    try
    {
    handle = Marshal.AllocHGlobal(source.Length);
    Marshal.Copy(source, 0, handle, source.Length);

    var raw = new RawImage
    {
    ImageData = handle,
    Size = source.Length
    };
    submit(raw);
    }
    catch (Exception ex)
    {
    if (handle != IntPtr.Zero)
    {
    Marshal.FreeHGlobal(handle);
    }
    }
    }


    The above works with the same signature for submit(RawImage img).



    It's a little more code, but you are not limiting the use of your module.






    share|improve this answer























    • Yeah I prefer this solution, more C# friendly.
      – WBuck
      2 days ago















    up vote
    3
    down vote



    accepted










    There is not much to review. The only thing I can contribute with is that you don't have to run in unsafe mode:



    If you define the data structure as:



      [StructLayout(LayoutKind.Sequential)]
    internal struct RawImage
    {
    internal IntPtr ImageData;
    internal int Size;
    }


    Then you can run the .NET side as:



      using (var bitmap = new Bitmap(@"fileName.Jpeg"))
    using (var stream = new MemoryStream())
    {
    bitmap.Save(stream, ImageFormat.Jpeg);
    var source = stream.ToArray();

    IntPtr handle = IntPtr.Zero;

    try
    {
    handle = Marshal.AllocHGlobal(source.Length);
    Marshal.Copy(source, 0, handle, source.Length);

    var raw = new RawImage
    {
    ImageData = handle,
    Size = source.Length
    };
    submit(raw);
    }
    catch (Exception ex)
    {
    if (handle != IntPtr.Zero)
    {
    Marshal.FreeHGlobal(handle);
    }
    }
    }


    The above works with the same signature for submit(RawImage img).



    It's a little more code, but you are not limiting the use of your module.






    share|improve this answer























    • Yeah I prefer this solution, more C# friendly.
      – WBuck
      2 days ago













    up vote
    3
    down vote



    accepted







    up vote
    3
    down vote



    accepted






    There is not much to review. The only thing I can contribute with is that you don't have to run in unsafe mode:



    If you define the data structure as:



      [StructLayout(LayoutKind.Sequential)]
    internal struct RawImage
    {
    internal IntPtr ImageData;
    internal int Size;
    }


    Then you can run the .NET side as:



      using (var bitmap = new Bitmap(@"fileName.Jpeg"))
    using (var stream = new MemoryStream())
    {
    bitmap.Save(stream, ImageFormat.Jpeg);
    var source = stream.ToArray();

    IntPtr handle = IntPtr.Zero;

    try
    {
    handle = Marshal.AllocHGlobal(source.Length);
    Marshal.Copy(source, 0, handle, source.Length);

    var raw = new RawImage
    {
    ImageData = handle,
    Size = source.Length
    };
    submit(raw);
    }
    catch (Exception ex)
    {
    if (handle != IntPtr.Zero)
    {
    Marshal.FreeHGlobal(handle);
    }
    }
    }


    The above works with the same signature for submit(RawImage img).



    It's a little more code, but you are not limiting the use of your module.






    share|improve this answer














    There is not much to review. The only thing I can contribute with is that you don't have to run in unsafe mode:



    If you define the data structure as:



      [StructLayout(LayoutKind.Sequential)]
    internal struct RawImage
    {
    internal IntPtr ImageData;
    internal int Size;
    }


    Then you can run the .NET side as:



      using (var bitmap = new Bitmap(@"fileName.Jpeg"))
    using (var stream = new MemoryStream())
    {
    bitmap.Save(stream, ImageFormat.Jpeg);
    var source = stream.ToArray();

    IntPtr handle = IntPtr.Zero;

    try
    {
    handle = Marshal.AllocHGlobal(source.Length);
    Marshal.Copy(source, 0, handle, source.Length);

    var raw = new RawImage
    {
    ImageData = handle,
    Size = source.Length
    };
    submit(raw);
    }
    catch (Exception ex)
    {
    if (handle != IntPtr.Zero)
    {
    Marshal.FreeHGlobal(handle);
    }
    }
    }


    The above works with the same signature for submit(RawImage img).



    It's a little more code, but you are not limiting the use of your module.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 2 days ago

























    answered 2 days ago









    Henrik Hansen

    6,1731722




    6,1731722












    • Yeah I prefer this solution, more C# friendly.
      – WBuck
      2 days ago


















    • Yeah I prefer this solution, more C# friendly.
      – WBuck
      2 days ago
















    Yeah I prefer this solution, more C# friendly.
    – WBuck
    2 days ago




    Yeah I prefer this solution, more C# friendly.
    – WBuck
    2 days ago












    up vote
    3
    down vote













    Both your and Henrik's approach can be optimized by replacing stream.ToArray() with stream.GetBuffer(). This returns the MemoryStream's internal buffer array instead of making a copy.



    You do have to take into account that the buffer can be larger than the actual data, so use the Length of the stream, not of the buffer. It's also possible that the data doesn't start at index 0, but that's only the case if you used one of the MemoryStream constructors that accepts an array, index and count. No problem here, but something to keep in mind if you want to generalize this.






    share|improve this answer

























      up vote
      3
      down vote













      Both your and Henrik's approach can be optimized by replacing stream.ToArray() with stream.GetBuffer(). This returns the MemoryStream's internal buffer array instead of making a copy.



      You do have to take into account that the buffer can be larger than the actual data, so use the Length of the stream, not of the buffer. It's also possible that the data doesn't start at index 0, but that's only the case if you used one of the MemoryStream constructors that accepts an array, index and count. No problem here, but something to keep in mind if you want to generalize this.






      share|improve this answer























        up vote
        3
        down vote










        up vote
        3
        down vote









        Both your and Henrik's approach can be optimized by replacing stream.ToArray() with stream.GetBuffer(). This returns the MemoryStream's internal buffer array instead of making a copy.



        You do have to take into account that the buffer can be larger than the actual data, so use the Length of the stream, not of the buffer. It's also possible that the data doesn't start at index 0, but that's only the case if you used one of the MemoryStream constructors that accepts an array, index and count. No problem here, but something to keep in mind if you want to generalize this.






        share|improve this answer












        Both your and Henrik's approach can be optimized by replacing stream.ToArray() with stream.GetBuffer(). This returns the MemoryStream's internal buffer array instead of making a copy.



        You do have to take into account that the buffer can be larger than the actual data, so use the Length of the stream, not of the buffer. It's also possible that the data doesn't start at index 0, but that's only the case if you used one of the MemoryStream constructors that accepts an array, index and count. No problem here, but something to keep in mind if you want to generalize this.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        Pieter Witvoet

        4,926723




        4,926723






















            WBuck is a new contributor. Be nice, and check out our Code of Conduct.










             

            draft saved


            draft discarded


















            WBuck is a new contributor. Be nice, and check out our Code of Conduct.













            WBuck is a new contributor. Be nice, and check out our Code of Conduct.












            WBuck is a new contributor. Be nice, and check out our Code of Conduct.















             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208070%2fpassing-bitmap-from-c-to-c-via-a-struct%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Ellipse (mathématiques)

            Quarter-circle Tiles

            Mont Emei