If you need a copy of MemoryStream data, you can just use
MemoryStream.ToArray(); Instead of this:
Code:
imageBits = new byte[streamLength];
memory.Seek(0, SeekOrigin.Begin);
memory.Read(imageBits, 0, streamLength);
But remember that MemoryStream.ToArray() creates a copy of a byte array encapsulated by MemoryStream. To reduce memory usage and improve performance you should use
MemoryStream.GetBuffer();However note that MemoryStream.GetBuffer() method returns the entire allocated buffer (even the unused buffer) with padding for the unused buffer space. So you should never use imageBits.Length if you want to know the actual data length inside the array. Instead use helper variable:
Code:
int streamLength = memory.Length;
byte[] imageBits = memory.GetBuffer();
memory.Close();
As a matter of fact MemoryStream.Close() or MemoryStream.Dispose() does nothing to release memory used by the MemoryStream. So thanks to MemoryStream.GetBuffer() you can reuse the byte array and omit creating new one.
I've attached a modified PdfImage.cs file with appropriate changes. I didn't have time to try WritableBitmap.BackBuffer / Bitmap.LockBits solution but I still believe that it is the right way to go. You should consider that.
I've also noticed that inside method FlateDecode.Encode() you do something like this:
Code:
MemoryStream.Capacity = MemoryStream.Length;
return MemoryStream.GetBuffer();
By changing memory stream's capacity you create another copy of a byte array used by that memory stream. It's another easy way to hit the LOH issue. You could return whole buffer and then write to pdf only actual data, without padding bytes. You would have to store real data length or use reverse loop before writing bytes to a file, to get actual data length inside buffer array.