Click here to Skip to main content
15,878,852 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more: , +
I have an image coming from a web cam. Its coming in at 640px width, 480px height, format of PixelFormats.Brg32.

I am writing the image to disk as the frames arrive but unfortunately its far to large (I use binaryWriter to do this).

To save on space, I've decided to use compression to convert the image that arrives, into PNG format before writing to the binary writer. This all works fine.

However, when I reload the image and attempt to decompress and write it back into my imagesource it wont work (using binary reader to load back into memory). This technique works when I don't decompress the image.

Here's my code for rendering the image (not decompressed):
C#
 var pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);

if (ImageSource == null)
    ImageSource = new WriteableBitmap(frame.Width, frame.Height, 96, 96, PixelFormats.Bgr32, null);

var stride = frame.Width * PixelFormats.Bgr32.BitsPerPixel / 8;
ImageSource.WritePixels(new Int32Rect(0, 0, frame.Width, frame.Height), pixelData, stride, 0);


This reloads a full size image but when I use the following code after I save the compressed image it wont work:
C#
var pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);

if (ImageSource == null)
    ImageSource = new WriteableBitmap(frame.Width, frame.Height, 96, 96, PixelFormats.Bgr32, null);

var stride = frame.Width * PixelFormats.Bgr32.BitsPerPixel / 8;

byte[] bmpBytes = frame.GetBmpImage(pixelData);

ImageSource.WritePixels(new Int32Rect(0, 0, frame.Width, frame.Height), bmpBytes, stride, 0);
I use the following code to compress my image when saving:
C#
public byte[] GetPngImage(byte[] imageData, System.Windows.Media.PixelFormat format, int width = 640, int height = 480)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        BitmapSource src = ToBitmapSource(imageData, PixelFormats.Bgr32, (int)width, (int)height);

        PngBitmapEncoder encoder = new PngBitmapEncoder();

        encoder.Interlace = PngInterlaceOption.On;
        encoder.Frames.Add(BitmapFrame.Create(src));
        encoder.Save(memoryStream);
        return memoryStream.ToArray();
    }
}

public BitmapSource ToBitmapSource(byte[] data, PixelFormat format, int width, int height)
{       
    return BitmapSource.Create(width, height, 96, 96, format, null, data, width * format.BitsPerPixel/8);
}

And use the following code to decompress:
C#
<pre>public byte[] GetBmpImage(byte[] imageData)
{
    using (MemoryStream memoryStream = new MemoryStream(imageData))
    {
        PngBitmapDecoder decoder = new PngBitmapDecoder(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

        using (MemoryStream output = new MemoryStream())
        {
            BmpBitmapEncoder enc = new BmpBitmapEncoder();


            enc.Frames.Add(decoder.Frames[0]);
            enc.Save(output);
            int stride = enc.Frames[0].Format.BitsPerPixel * (int)enc.Frames[0].Width / 3;
            return output.ToArray();
        }
    }
}

At the line:
C#
ImageSource.WritePixels(new Int32Rect(0, 0, frame.Width, frame.Height), bmpBytes, stride, 0);

I get the error buffer size not sufficient.

I expect my stride to be 2560, my height to be 480, width to be 640 and my byte data length to be 1228800 but the decompressed png doesn't seem to match these attributes.

Can someone point out what I'm doing wrong?

Thanks in advance for any help!
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900