Byte[r,c,c] to Halcon HObject/HImage to byte[] - halcon

I am using Zivid.NET, Halcon.NET and ML.NET together. Zivid provides me with a 3D byte array (row, column, channel), Halcon uses HImages/HObjects, ML.NET functionality expects a 1D byte array (same as File.ReadAllBytes())
So far I used a workaround where:
I save()'d Zivid's imageRGBA as a PNG,
which I read with Halcon's read_image() that gives me a HObject.
After some graphical work I saved the HObject again as a PNG using write_image().
Using File.ReadAllBytes() to read that PNG I get the byte[] that my ML.NET functionalities expect.
But this is far from ideal with larger amounts of data.
What I need is:
a way to convert byte[r,c,c] images to HObject/HImage.
a way to convert HObject/HImage images to byte[].
Halcon's read_image() and write_image() don't seem to have any options for this and I haven't found anything helpful so far.

To create an HImage object from byte, you need a pointer to an array and then it's simple:
public HImage(string type, int width, int height, IntPtr pixelPointer)
To get a pointer and acess the data from HImage, the following function is needed:
IntPtr HImage.GetImagePointer1(out string type, out int width, out int height)

To convert from Zivid.NET's byte[r,c,c] to HImage one can:
var byteArr = imgRGBA.ToByteArray();
byte[,] redByteArray = new byte[1200, 1920];
byte[,] greenByteArray = new byte[1200, 1920];
byte[,] blueByteArray = new byte[1200, 1920];
for (int row = 0; row < 1200; row++)
for (int col = 0; col < 1920; col++)
{
redByteArray[row, col] = byteArr[row, col, 0];
greenByteArray[row, col] = byteArr[row, col, 1];
blueByteArray[row, col] = byteArr[row, col, 2];
}
GCHandle pinnedArray_red = GCHandle.Alloc(redByteArray, GCHandleType.Pinned);
IntPtr pointer_red = pinnedArray_red.AddrOfPinnedObject();
GCHandle pinnedArray_green = GCHandle.Alloc(greenByteArray, GCHandleType.Pinned);
IntPtr pointer_green = pinnedArray_green.AddrOfPinnedObject();
GCHandle pinnedArray_blue = GCHandle.Alloc(blueByteArray, GCHandleType.Pinned);
IntPtr pointer_blue = pinnedArray_blue.AddrOfPinnedObject();
GenImage3(out HObject imgHImage, "byte", 1920, 1200, pointer_red, pointer_green, pointer_blue);
pinnedArray_red.Free();
pinnedArray_green.Free();
pinnedArray_blue.Free();
Still working on the second part..
A better / more efficient method is very welcome.

Related

How to covert Textbox to integer array in c++/cli

I'm trying to convert the textbox to an integer array assuming that every character of the textbox is a digit.
//textbox is named input
int size = this->input->Text->Length;
int * num = new int[size];
int Counter = 0;
//for loop used since textbox inputs like a calculator
//Ex: the number: 234 is inputed: 2, then 23, then 234
for (int i = size; i > 0; i--)
{
num2[Counter] = System::Convert::ToInt32(input->Text[i-1]);
Counter += 1;
}
Array of numbers should be:
num[0] = 4, num[1] = 3, num[2] = 2
Upon research though it seems that it's finding the integer unicode value instead.
Code input->Text[i-1] returns a single Unicode character value of the wchar_t type. That is implicitly cast to Int32, i.e. the symbol code.
You have to convert the char to a string, before converting to the number. You can use the Substring method or the ToString method for this purpose.
You can do it as follows:
String^ text = this->input->Text;
int size = text->Length;
int * num = new int[size];
for (int i = size - 1; i >= 0; i--) {
num[i] = Convert::ToInt32(text->Substring(size - i - 1, 1));
}
However, you should not mix managed and unmanaged code.
There is a better way. Use a generic collection instead of an array.
String^ text = this->input->Text;
int size = text->Length;
List<int>^ nums = gcnew List<int>();
for (int i = size - 1; i >= 0; i--) {
nums->Add(Convert::ToInt32(text[i].ToString()));
}
Don't forget
using namespace System::Collections::Generic;
The list can be accessed by index like an array:
nums[i]
So it is convenient to work with. And most importantly, do not need to worry about freeing memory.

Convert a System::String into an int

I am trying to read the value from a sensor an plot some figures depending on that value. I want to compare the value from the sensor to an int variable and I think this is my problem. This is what I am doing:
System::String ^leido=this->serialPort1->ReadLine();
Int32 tb1Int;
Int32 cien=0;
bool ret = Int32::TryParse(leido, tb1Int);
//Drawing
if (tb1Int > cien){
PictureBox ^g = gcnew PictureBox;
g->Parent = this;
g->Location = Point(630,20);
g->Size::set(Drawing::Size(900,90));
g->BackColor::set(Color::Aquamarine);}
I am quite sure the problem is the comparision (tb1Int > cien). It should be fulfilled, but the code for drawing is not executed.
Any help??

How do I copy writeablebitmap to clipboard from an elevated trust silverlight application using P/Invoke?

I've got a silverlight 5 application that is running elevated trust in-browser. This allows us to do things that wouldn't ordinarily be possible in silverlight like having more access to the clipboard via P/Invoke.
What I need to be able to do is copy controls to the clipboard so they could be pasted into Word or Outlook. I can convert the controls to an image via WriteableBitmap but copying the data to the clipboard is something I'm having issues with.
Calling code:
WriteableBitmap bmp = new WriteableBitmap(elements[0], new ScaleTransform() { ScaleX = 1.0, ScaleY = 1.0 });
int[] p = bmp.Pixels;
int len = p.Length * 4;
byte[] result = new byte[len];
Buffer.BlockCopy(p, 0, result, 0, len);
CopyToClipboardViaPInvoke(result, ClipboardFormat.CF_BITMAP);
Copy function:
private void CopyToClipboardViaPInvoke(byte[] data, ClipboardFormat format)
{
IntPtr p = IntPtr.Zero;
if (Native.OpenClipboard(p))
{
GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
try
{
Native.EmptyClipboard();
IntPtr result = Native.SetClipboardData(format, pointer);
}
finally
{
Native.CloseClipboard();
pinnedArray.Free();
}
}
}
The result says it's successful, but paste does nothing. IsClipboardFormatAvailable also states that the format is available on the clipboard. I've also tried various ClipboardFormat inputs and other methods of converting the control to an image without any luck.
Update 1
Thanks to suggestions from user629926 I've got what I think is a little closer but I'm still missing something.
Native.EmptyClipboard();
IntPtr bmp = IntPtr.Zero;
GCHandle pinnedArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr bmpPointer = pinnedArray.AddrOfPinnedObject();
Native.StartupInput sin = new Native.StartupInput() { GdiplusVersion = 1 };
Native.StartupOutput sout = new Native.StartupOutput();
IntPtr gdip = IntPtr.Zero;
int startup = Native.GdiplusStartup(out gdip, ref sin, out sout);
int created = Native.GdipCreateBitmapFromScan0(width, height, width * 4, 0x0026200A, bmpPointer, out bmp);
IntPtr result = Native.SetClipboardData(format, bmp);
Native.DeleteObject(bmp);
Native.GdiplusShutdown(ref gdip);
Use GdipCreateBitmapFromScan0 to get HBitmap from you array and pass it to clipboard and the DeleteObject to free it.
[DllImport("gdiplus.dll")]
static extern int GdipCreateBitmapFromScan0(int width, int height, int stride, int format, IntPtr scan0, out IntPtr bitmap);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

How to dump the NTFS $Bitmap file

For a project, I want to get the list of all free/used clusters on an NTFS partition.
For this i have to dump the $Bitmap file and parse its contents.
There are few API's and examples on the web, but however they don't seem to work. Is there a simple way/ code sample to just copy the $Bitmap file somewhere.
Is using FSCTL_GET_VOLUME_BITMAP the only way? Ideally I would like to do it in C#.
NFI.EXE which is (used to be) part of the "oem support tools" can enumerate all NTFS partition items. It might also be capable to dump the content of $Bitmap.
You definitely want to go the easy route and use the IOCTL rather than trying to read $Bitmap directly. Of course, you don't have to do it yourself if somebody has done it for you. It turns out that an MSDN blogger has already written a nice little wrapper for you:
http://blogs.msdn.com/jeffrey_wall/archive/2004/09/13/229137.aspx
The whole class is over 300 lines of code, so I won't post it all, but here's the function that gets the volume bitmap:
/// <summary>
/// Get cluster usage for a device
/// </summary>
/// <param name="DeviceName">use "c:"</param>
/// <returns>a bitarray for each cluster</returns>
static public BitArray GetVolumeMap(string DeviceName)
{
IntPtr pAlloc = IntPtr.Zero;
IntPtr hDevice = IntPtr.Zero;
try
{
hDevice = OpenVolume(DeviceName);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc(i64, GCHandleType.Pinned);
IntPtr p = handle.AddrOfPinnedObject();
// alloc off more than enough for my machine
// 64 megs == 67108864 bytes == 536870912 bits == cluster count
// NTFS 4k clusters == 2147483648 k of storage == 2097152 megs == 2048 gig disk storage
uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1 meg * 64 == 64 megs
uint size = 0;
pAlloc = Marshal.AllocHGlobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl(
hDevice,
FSConstants.FSCTL_GET_VOLUME_BITMAP,
p,
(uint)Marshal.SizeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new Exception(Marshal.GetLastWin32Error().ToString());
}
handle.Free();
/*
object returned was...
typedef struct
{
LARGE_INTEGER StartingLcn;
LARGE_INTEGER BitmapSize;
BYTE Buffer[1];
} VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER;
*/
Int64 StartingLcn = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64));
Debug.Assert(StartingLcn == 0);
pDest = (IntPtr)((Int64)pDest + 8);
Int64 BitmapSize = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64));
Int32 byteSize = (int)(BitmapSize / 8);
byteSize++; // round up - even with no remainder
IntPtr BitmapBegin = (IntPtr)((Int64)pDest + 8);
byte[] byteArr = new byte[byteSize];
Marshal.Copy(BitmapBegin, byteArr, 0, (Int32)byteSize);
BitArray retVal = new BitArray(byteArr);
retVal.Length = (int)BitmapSize; // truncate to exact cluster count
return retVal;
}
finally
{
CloseHandle(hDevice);
hDevice = IntPtr.Zero;
Marshal.FreeHGlobal(pAlloc);
pAlloc = IntPtr.Zero;
}
}

Beginner: Fastest way to cast/copy byte() into single()

I've got a byte() array returned as result of directx sound capture, but for other parts of my program I want to treat the results as single(). Is trundling down the array item by item the fastest way of doing it or is there a clever way to do it ?
The code that gets it is
CType(Me._applicationBuffer.Read(Me._nextCaptureOffset, GetType(Byte), LockFlag.None, LockSize), Byte())
which creates the byte array, can Ctype handle single ? (note, I can't figure out a way to do it!)
public float[] ByteArrayToFloatArray(byte[] byteArray)
{
float[] floatArray = new float[byteArray.Length / 4];
for (int i = 0; i < floatArray.Length; i++)
{
floatArray[i] = BitConverter.ToSingle(byteArray, i * 4);
}
return floatArray;
}
The fastest way to do this (in terms of performance as opposed to how long it takes to write) would probably be to use the CopyMemory API call.
Try
float f = BitConverter.ToSingle(bytearray, 0);
In VB (I think):
Dim single s;
s = BitConverter.ToSingle(bytearray, 0);