I am working with a vimba camera mako G-234PoE and its trigger in asp.net. I wrote the code for the trigger for saving the image and it works very well, the problem now is that I need to save the image with a bit depth of 16-bits.The pixel format of the frame is in Mono12Packed and I wrote this code to pass the bitmap into a 16 bit-depth one but now my problem is to save the bitmap in format .tiff. I've tried several codes but I still cannot save the image. Most of the times the errors are the sames : generic error with GDI+ or that I get out of memory.
This is the function I've tried to convert the frame in Mono12Packed into a bitmap of 16 bit depth with pixel format 16bppGrayScale. The bitmap is filled correctly but it's just the fact that I cannot convert it into a .tiff image.
public Bitmap ConvertFrameTrigger16bits(Frame frame)
{
byte[] packedData = frame.Buffer;
ushort[] unpackedData = new ushort[frame.Width, frame.Height];
for(int i = 0, j = 0; i < packedData.Length; i += 3, j += 2)
{
unpackedData[j] = (ushort)((packedData[i] << 4) | (packedData[i+1] & 0x0F));
unpackedData[j+1] = (ushort)((packedData[i + 2] << 4) | (packedData[i+1] >>4));
}
Bitmap bitmap = new Bitmap((int)frame.Width,(int)frame.Height, PixelFormat.Format16bppGrayScale);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0,0,bitmap.Width, bitmap.Height), ImageLockeMode.WriteOnly, bitmap.PixelFormat);
byte[] byteData = new byte[unpackedData.Length *sizeof(ushort)];
Buffer.BlockCopy(unpackedData,0,byteData,0,byteData.Length);
Marshal.Copy(byteData,0,bitmapData.Scan0,byteData.Length);
bitmap.unlockBits(bitmapData);
return bitmap;
}
Edit 1 :
I managed to solve the problem. What I did was to get a frame from the camera, pass that frame into a bitmap of 16 bppGrayScale and then, to save the image, I used this method in which I specified everything that the image should have.The main difference was that I used Mono12 instead of the packed version since handling the bits was easier with this one. If you ever encounter this problem, feel free to use this code as a guide (keep in mind that you need the vimba library for asp.net, which is AVT.VmbAPINET):
public Bitmap ConvertFrameTrigger16bits(Frame frame)
{
int width = (int)frame.Width;
int height = (int)frame.Height;
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);
// Locks the bits of the bitmap
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, bitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
// Here is maybe the most important part, since
// it was a Mono12 frame, it is already in 16-
// bits format, so we can just copy it.
Marshal.Copy(frame.Buffer, 0, ptr, frame.Buffer.Length);
bitmap.UnlockBits(bmpData);
return bitmap;
}
public void SaveBitmapAsTiff16bits(Bitmap bitmap, string filePath)
{
if (bitmap == null)
{
throw new ArgumentNullException(nameof(bitmap));
}
BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format16bppGrayScale);
//Here we specified everything regarding the bitmap
try
{
BitmapSource bitmapSource = BitmapSource.Create(
bitmapData.Width,
bitmapData.Height,
bitmap.HorizontalResolution,
bitmap.VerticalResolution,
System.Windows.Media.PixelFormats.Gray16,
null,
bitmapData.Scan0,
bitmapData.Stride * bitmapData.Height,
bitmapData.Stride);
// A stream is necessary for memory problems
using (FileStream stream = new FileStream(filePath, FileMode.Create))
{
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.None;
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(stream);
}
}
finally
{
//This is to release resources
bitmap.UnlockBits(bitmapData);
}
}