I'm currently writing an ASCOM driver which is used to take picture with a SigmaFP camera.
Everything works fine but I'm currently hitting a wall when I have to convert my DNG to a standard image array for ASCOM (https://ascom-standards.org/Help/Developer/html/P_ASCOM_DriverAccess_Camera_ImageArray.htm)
With libraw I convert my DNG file, convert it to a bitmap and save it as a new jpeg file.
But, when I try to conver this jpeg file to an array (using Bitmap and my custom ReadBitmap function) I get this kind of pictures :
Here is the input image
I don't know what I have missed during those steps
Here is my ReadBitmap function :
public int[,] ReadBitmap(Bitmap img)
{
BitmapData data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat);
IntPtr ptr = data.Scan0;
int bytesCount = Math.Abs(data.Stride) * img.Height;
var result = new int[img.Width, img.Height];
byte[] bytesArray = new byte[bytesCount];
Marshal.Copy(ptr, bytesArray, 0, bytesCount);
img.UnlockBits(data);
var width = img.Width;
var height = img.Height;
Parallel.For(0, width * height, rc =>
{
var b = bytesArray[rc * 3];
var g = bytesArray[rc * 3 + 1];
var r = bytesArray[rc * 3 + 2];
int row = rc / width;
int col = rc - width * row;
//var rowReversed = height - row - 1;
result[col, row] = (int)(0.299 * r + 0.587 * g + 0.114 * b);
}
);
return result;
}
Here is the method used to convert DNG to jpeg (which will be used to get the int array)
IntPtr data = LoadRaw(path);
NativeMethods.libraw_dcraw_process(data);
// extract raw data into allocated memory buffer
var errc = 0;
var ptr = NativeMethods.libraw_dcraw_make_mem_image(data, out errc);
// convert pointer to structure to get image info and raw data
var img = PtrToStructure<libraw_processed_image_t>(ptr);
Console.WriteLine("\nImage type: " + img.type);
Console.WriteLine("Image height: " + img.height);
Console.WriteLine("Image width: " + img.width);
Console.WriteLine("Image colors: " + img.colors);
Console.WriteLine("Image bits: " + img.bits);
Console.WriteLine("Data size: " + img.data_size);
Console.WriteLine("Checksum: " + img.height * img.width * img.colors * (img.bits / 8));
// rqeuired step before accessing the "data" array
Array.Resize(ref img.data, (int)img.data_size);
var adr = ptr + OffsetOf(typeof(libraw_processed_image_t), "data").ToInt32();
Copy(adr, img.data, 0, (int)img.data_size);
// calculate padding for lines and add padding
var num = img.width % 4;
var padding = new byte[num];
var stride = img.width * img.colors * (img.bits / 8);
var line = new byte[stride];
var tmp = new List<byte>();
for (var i = 0; i < img.height; i++)
{
Buffer.BlockCopy(img.data, stride * i, line, 0, stride);
tmp.AddRange(line);
tmp.AddRange(padding);
}
// release memory allocated by [libraw_dcraw_make_mem_image]
NativeMethods.libraw_dcraw_clear_mem(ptr);
// create/save bitmap from mem image/array
var bmp = new Bitmap(img.width, img.height, PixelFormat.Format24bppRgb);
var bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
Copy(tmp.ToArray(), 0, bmd.Scan0, (int)img.data_size);
NativeMethods.libraw_close(data);
var outJPEG = path.Replace(Path.GetExtension(path), ".jpg");
Console.WriteLine("Saving image to: " + outJPEG);
bmp.Save(outJPEG, ImageFormat.Jpeg);
CurrentFilePath = outJPEG;