using System;
using System.Collections.Generic;
using System.Text;
using Lumenera.USB;
using ImageRelated;
using System.Drawing;
using System.Drawing.Imaging;
namespace ImageRelated
{
/// <summary>
/// List of function frequently use for image manipulation.
/// </summary>
public static class FrequentOperation
{
/// <summary>
/// Calculate image intensity on RAW data
/// </summary>
/// <param name="pdata">Image byte array.</param>
/// <param name="width">Width of the image.</param>
/// <param name="height">Height of the image.</param>
/// <param name="pf">Pixel format PF8 or PF16.</param>
/// <returns>Image Intensity.</returns>
public static float RawIntensity(ref byte[] pdata, int width, int height, dll.LucamPixelFormat pf)
{
int intensity = 0;
int imageSize = width * height; // Calculate image size.
if (pf == dll.LucamPixelFormat.PF_16) // Chech if 16 bits images.
{
imageSize *= 2; // Double the image size.
}
for (int i = 0; i < imageSize; i++)
{
intensity += pdata[i];
}
return (intensity / imageSize);
}
/// <summary>
/// Calculate image intensity on RAW Data
/// </summary>
/// <param name="pdata">Image byte array.</param>
/// <returns>Image Intensity.</returns>
public static float RawIntensity(ref byte[] pdata)
{
int intensity = 0;
foreach (byte a in pdata)
{
intensity += a;
}
return (intensity / pdata.Length);
}
/// <summary>
/// Calculate image intensity of RAW data
/// </summary>
/// <param name="pdata">Image byte array.</param>
/// <param name="width">Image width</param>
/// <param name="height">Image Height</param>
/// <returns>Image Intensity</returns>
public static float RawIntensity(ref byte[] pdata, int width, int height)
{
int intensity = 0;
int imageSize = width * height; // Calculate image size.
for (int i = 0; i < imageSize; i++)
{
intensity += pdata[i];
}
return (intensity / imageSize);
}
/// <summary>
/// Will take a frame from the live video feed and calculate the image intensity on the RAW data.
/// Then the image intensity is compare with the threshold value.
/// </summary>
/// <param name="camera">Camera Handle.</param>
/// <param name="blackThreshold">Intensity Threshold to validate for failed or pass</param>
/// <param name="ff">Reference to the current frame format.</param>
/// <returns>false -->if image intensity bellow the threshold value or an api called was unsuccessfull.
/// true -->image was not considered black.</returns>
/// <remarks>1) Because of noise and the capability of trying to boost gains when dark images on some image sensor, it is not
/// recommended to use a threshold of 0.</remarks>
public static bool ImageFrameBlackTest(IntPtr camera, int blackThreshold, ref dll.LucamFrameFormat ff)
{
int imageSize = 0;
//Image size calculation.
imageSize = (ff.Width / ff.SubSampleX) * (ff.Height / ff.SubSampleY);
if (ff.PixelFormat == dll.LucamPixelFormat.PF_16)
imageSize *= 2; // Double image size if in 16 bits mode;
// Memory allocation
byte[] pdata = new byte[imageSize];
if (!dll.LucamTakeVideo(camera, 1, pdata)) return (false); // Image Caption.
int intensity = (int) FrequentOperation.RawIntensity( ref pdata); // Calculate image intensity.
if (intensity < blackThreshold)
return (false);
return (true);
}
/// <summary>
/// Will take a frames from the live video feed stream and calculate the image intensity on the RAW data.
/// then the image intensity is compare with the threshold value.
/// </summary>
/// <param name="camera">Camera Handle</param>
/// <param name="nbImage">Number of image to take.</param>
/// <param name="blackThreshold">Intensity threshold to validate for failed or pass</param>
/// <param name="ff">Reference to the current frame format.</param>
/// <param name="ellaspedTimed">Output Time it took to capture the video frames</param>
/// <param name="errorString">List invalid frame number in a string.</param>
/// <returns>Return the number of invalid frames.</returns>
public static int ImageFrameBlackTest(IntPtr camera, int nbImage, int blackThreshold, ref dll.LucamFrameFormat ff, ref TimeSpan ellaspedTimed, ref string errorString)
{
byte[] pdata;
byte[] tmpImage;
int imageSize = 0;
int FrameErrorCounter = 0;
DateTime start = new DateTime();
DateTime stop = new DateTime();
TimeSpan timeAction = new TimeSpan();
start = DateTime.Now;
stop = DateTime.Now;
timeAction = stop - start;
//Image size calculation.
imageSize = (ff.Width / ff.SubSampleX) * (ff.Height / ff.SubSampleY);
if (ff.PixelFormat == dll.LucamPixelFormat.PF_16)
imageSize *= 2; // Double image size if in 16 bits mode;
// Memory allocation
try
{
pdata = new byte[imageSize * nbImage];
tmpImage = new byte[imageSize];
}
catch
{
errorString +="Cannot allocate memory to capture images.";
return(-1);
}
// Image Caption.
start = DateTime.Now;
if (!dll.LucamTakeVideo(camera, nbImage, pdata)) return (nbImage);
stop = DateTime.Now;
ellaspedTimed = stop - start;
ellaspedTimed -=timeAction;
// Calculatine Images intensity
int intensity = 0;
for (int i = 0; i < nbImage; i++)
{
intensity = 0;
// copy image in an array to be copied.
for (int nbByte=0; nbByte<imageSize;nbByte++)
{
tmpImage[nbByte] = pdata[(imageSize*i)+nbByte];
}
intensity = (int)RawIntensity( ref tmpImage);
if (intensity < blackThreshold )
{
FrameErrorCounter++;
errorString += string.Format("{0}, ", i);
}
}
return (FrameErrorCounter);
}
/// <summary>
/// Will take snapshots from the still stream and calculate the image intensity on the RAW data.
/// then the image intensity is compare with the threshold value.
/// </summary>
/// <param name="camera">Camera Handle</param>
/// <param name="nbImage">Number of snapshot to take.</param>
/// <param name="blackThreshold">pass of failed intensity criteria.</param>
/// <param name="snap">Reference to the snapshot data structure.</param>
/// <param name="ellaspedTimed">Image acquisitions time</param>
/// <param name="errorString">List of the invalid frames.</param>
/// <returns></returns>
public static int ImageFrameBlackTest(IntPtr camera, int nbImage, int blackThreshold, ref dll.LucamSnapshot snap, ref TimeSpan ellaspedTimed, ref string errorString)
{
int imageSize = 0;
int FrameErrorCounter = 0;
DateTime start = new DateTime();
DateTime stop = new DateTime();
TimeSpan timeTravel = new TimeSpan();
TimeSpan timeAction = new TimeSpan();
start = DateTime.Now;
stop = DateTime.Now;
timeAction = stop - start;
//Image size calculation.
imageSize = (snap.Format.Width / snap.Format.SubSampleX) * (snap.Format.Height / snap.Format.SubSampleY);
if ( snap.Format.PixelFormat == dll.LucamPixelFormat.PF_16)
imageSize *= 2; // Double image size if in 16 bits mode;
// Memory allocation
byte[][] rawData = new byte[nbImage][];
for (int i = 0; i < nbImage; i++)
{
rawData[i] = new byte[imageSize];
}
// Image Caption.
dll.LucamEnableFastFrames(camera, ref snap);
start = DateTime.Now;
for (int i = 0; i < nbImage; i++)
{
if (!dll.LucamTakeFastFrame(camera, rawData[i]))
{
dll.LucamDisableFastFrames(camera);
return (i);
}
}
stop = DateTime.Now;
timeTravel = (stop - start);
timeTravel -= timeAction;
dll.LucamDisableFastFrames(camera);
int intensity = 0;
for (int i = 0; i < nbImage; i++)
{
intensity = (int)RawIntensity(ref rawData[i]);
if (intensity < blackThreshold)
{
FrameErrorCounter++;
errorString += string.Format("{0}, ", i);
}
}
return (FrameErrorCounter);
}
/// <summary>
/// Capture and image and convert on all useful format
/// </summary>
/// <param name="cam">Camera handle.</param>
/// <param name="rawImage">Buffer that will contain the RAW image.</param>
/// <param name="rgbImage">Buffer that will contain the RGB image.</param>
/// <param name="winImage">Buffer that will contain the Windows Bitmap image.</param>
/// <param name="ff">Lumenera frame format.</param>
/// <param name="conversion">Lumenera color convertion parameters.</param>
/// <param name="ellaspedTimed">Ellasped time between capture.</param>
/// <param name="errorString">buffer that will contain the error message.</param>
/// <returns>true if successful</returns>
public static bool ImageCapture(IntPtr cam, ref byte[] rawImage, ref byte[] rgbImage, ref Bitmap winImage, ref dll.LucamFrameFormat ff, ref dll.LucamConversion conversion, ref TimeSpan ellaspedTimed, ref string errorString)
{
BitmapData myImageData;
Rectangle lockdata;
dll.LucamColorFormat colorFormat = dll.LucamColorFormat.MONO ;
// Image size calculation.
int imageSize = (ff.Width / ff.SubSampleX) * (ff.Height / ff.SubSampleY);
if (ff.PixelFormat == dll.LucamPixelFormat.PF_16)
imageSize *= 2; // Double image size if in 16 bits mode;
int rgbImageSize = imageSize * 3;
// Get the color format of the camera.
try
{
colorFormat =(dll.LucamColorFormat) api.GetProperty(cam, dll.LucamProperty.COLOR_FORMAT);
}
catch
{
errorString += "Cannot read the color format from camera";
return (false);
}
//Memory allocation.
rawImage = new byte[imageSize]; // Resize raw image buffer to the appropriate size.
rgbImage = new byte[rgbImageSize]; // Resize rbg buffer to the appropriate size.
// Image Caption.
if (!dll.LucamTakeVideo(cam, 1, rawImage)) return (false);
//imageDateTime = DateTime.Now;
if (colorFormat != dll.LucamColorFormat.MONO) // Check if this is a color camera.
{
// Color camera.
//RGB Converstion
if (ff.PixelFormat == dll.LucamPixelFormat.PF_8)
{
if (!dll.LucamConvertFrameToRgb24(cam, rgbImage, rawImage, ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, dll.LucamPixelFormat.PF_8, ref conversion)) return (false);
}
else
{
if (!dll.LucamConvertFrameToRgb48(cam, rgbImage, rawImage, ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, dll.LucamPixelFormat.PF_16, ref conversion)) return (false);
}
// Create bitmap with RGB
if (ff.PixelFormat == dll.LucamPixelFormat.PF_8)
winImage = new Bitmap(ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, PixelFormat.Format24bppRgb);
else
winImage = new Bitmap(ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, PixelFormat.Format48bppRgb);
myImageData = new BitmapData();
lockdata = new Rectangle(0, 0, ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY);
myImageData = winImage.LockBits(lockdata, ImageLockMode.ReadWrite, winImage.PixelFormat, myImageData);
System.Runtime.InteropServices.Marshal.Copy(rgbImage, 0, myImageData.Scan0, rgbImageSize);
winImage.UnlockBits(myImageData);
winImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
//setup panel.
//imagePanel.Width= myImage.Width;
//imagePanel.Height = myImage.Height;
//imagePanel.Image = myImage;
}
else
{
//Monochrome camera
if (ff.PixelFormat != dll.LucamPixelFormat.PF_8)
{
// Camera is 16 bit
if (!api.IsFormatLittleEndian(cam))
{
// Convert big endian data to little endian data.
}
winImage = new Bitmap(ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, PixelFormat.Format16bppGrayScale);
}
else
{
// 8 bit image.
if (!dll.LucamConvertFrameToRgb24(cam, rgbImage, rawImage, ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, dll.LucamPixelFormat.PF_8, ref conversion))
{
errorString += "Cannot make rgb convertion of the colorimage.";
return (false);
}
winImage = new Bitmap(ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY, PixelFormat.Format24bppRgb);
}
myImageData = new BitmapData();
lockdata = new Rectangle(0, 0, ff.Width / ff.SubSampleX, ff.Height / ff.SubSampleY);
myImageData = winImage.LockBits(lockdata, ImageLockMode.ReadWrite, winImage.PixelFormat, myImageData);
System.Runtime.InteropServices.Marshal.Copy(rgbImage, 0, myImageData.Scan0, rgbImageSize);
winImage.UnlockBits(myImageData);
//myImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
//imagePanel.Image = myImage;
}
return (true);
}
}
}