0

I make a webrequest to receive a large jpeg as a byte array. This in turn can be converted to a memory stream. I need to get this data into a bitmapdata so that I can marshall copy it to a byte array again. Am i right in assuming that a byte array returned from a memory stream is not the same as a byte array returned from a marshall copy of bitmapdata to a byte array?

I do not want to write the memory stream out to an image as it will return a out of memory error due to its size AND the fact I am using compact cf C# 2.

this is my call to the server..

HttpWebRequest _request = (HttpWebRequest)WebRequest.Create("A url/00249.jpg");
                _request.Method = "GET";
                _request.Timeout = 5000;
                _request.ReadWriteTimeout = 20000;
                byte[] _buffer;
                int _blockLength = 1024;
                int _bytesRead = 0;
                MemoryStream _ms = new MemoryStream();
                using (Stream _response = ((HttpWebResponse)_request.GetResponse()).GetResponseStream())
                {
                    do
                    {
                        _buffer = new byte[_blockLength];
                        _bytesRead = _response.Read(_buffer, 0, _blockLength);
                        _ms.Write(_buffer, 0, _bytesRead);
                    } while (_bytesRead > 0);
                }

This is my code to read a byte array from a bitmapdata.

 Bitmap Sprite = new Bitmap(_file);
        Bitmapdata RawOriginal = Sprite.LockBits(new Rectangle(0, 0, Sprite.Width, Sprite.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
        int origByteCount = RawOriginal.Stride * RawOriginal.Height;
        SpriteBytes = new Byte[origByteCount];
        System.Runtime.InteropServices.Marshal.Copy(RawOriginal.Scan0, SpriteBytes, 0, origByteCount);
        Sprite.UnlockBits(RawOriginal);

Note: I do not want to use this:

Bitmap Sprite = new Bitmap(_file);

I want to go from:

MemoryStream _ms = new MemoryStream();

to

System.Runtime.InteropServices.Marshal.Copy(RawOriginal.Scan0, SpriteBytes, 0, origByteCount);

using what ever conversions are required without writing to a bitmap.

ChrisWue
  • 18,612
  • 4
  • 58
  • 83
Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179
  • And why not use a FileStream? I am guessing you are saying you dont have the space in memory but do have the space on the file system? – CrazyDart Oct 02 '13 at 19:31
  • @CrazyDart HI, thanks for your reply. The ultimate issue is to extract portions of this larger image to smaller images (aka Sprite). I would not know if this was possible using a filestream. Thanks for your thoughts though... – Andrew Simpson Oct 03 '13 at 06:12

1 Answers1

2

What you're asking is going to be difficult. The data you're receiving from the response object is a full jpeg image, which has a header and then a bunch of compressed data bytes. The byte array addressed by Scan0 is uncompressed and quite possibly includes some padding bytes at the end of each scan line.

Most importantly, you definitely cannot use Marshal.Copy to copy the received bytes to Scan0.

To do what you're asking will require that you parse the header of the jpeg that you receive and uncompress the image bits directly to Scan0, padding each scan line as appropriate. There is nothing in the .NET Framework that will do that for you.

The accepted answer to this question has a link to a library that might help you out.

Even if that works, I'm not certain it will help you out. If calling the BitMap constructor to create the image causes you to run out of memory, it's almost certain that this roundabout method will, as well.

Is the problem that you have so many sprites that you can't keep them all in memory, uncompressed? If so, you'll probably have to find some other way to solve your problem.

By the way, you can save yourself a lot of trouble by changing your code that reads the image to:

    MemoryStream _ms = new MemoryStream();
    using (Stream _response = ((HttpWebResponse)_request.GetResponse()).GetResponseStream())
    {
        _response.CopyTo(_ms);
    }
Community
  • 1
  • 1
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Hi Jim, thanks for taking the time to help. The problems are that working with large images can cause out of memory exceptions especially on mobile devices. I am using sprites to contain frames of a video you see. I will be displaying the images as and when i need them derived from the byte array rather than clipping the location like I would with a div in a web site. The solution was either to use a series of smaller images/sprites, remove headers (etc) from the byte array or/and do the conversion on the server to bitmpdata as the tolerance for large images is higher. – Andrew Simpson Oct 03 '13 at 06:02
  • The copyto method is not available in the compact cf unfortunately for me :(. I will let this question go for a bit before accepting your answer as definite though I am sure it is difficult to achieve. – Andrew Simpson Oct 03 '13 at 06:19
  • HI Again, 2 things. Would you know whether this library can load and compress an existing jpeg? If so, would you have sample code as I am finding it difficult to find a sample in the downloads as there is no 'getting started' stuff. Whilst this was not my initial question I would consider it kind of you to share any knowledge you have? Thanks – Andrew Simpson Oct 03 '13 at 09:08
  • @AndrewSimpson: I know nothing about that library. It looked like it might be helpful to you. – Jim Mischel Oct 03 '13 at 13:08
  • In case anyone was following this converting to bitmapdata BEFORE sending to mobile was a bad idea as of course the jpeg is uncompressed and the byte array is way too big to use in CF. – Andrew Simpson Oct 03 '13 at 13:08