2

I'm currently working on a vision-based system using Halcon. After successful processing, I'd like the cropped out gray value images in HImage-Format to be converted into Bitmaps. The function I have (in "managed" area) kind of achieves that but the Bitmap turns out to be distorted. How do I solve this issue?

    HImage image_temp;
    HRegion ROI;
    HTuple pointer, type, width, height;
    ROI.GenRectangle1(row1, col1, row2, col2);
    image_temp = sourceImg->ReduceDomain(ROI);
    image_temp = image_temp.CropDomain();
    GetImagePointer1(image_temp, &pointer, &type, &width, &height);

    if (image_temp.CountObj() < 1)
    {
        throw gcnew Exception("ERROR: Failed attempt at HImage2Bitmap");
    }

    Imaging::ColorPalette^ palette;
    Bitmap^ curBitmap = gcnew Bitmap((Int32)width, (Int32)height, Imaging::PixelFormat::Format8bppIndexed);
    Drawing::Rectangle^ rect = gcnew Drawing::Rectangle(0, 0, width, height);
    Imaging::BitmapData^ imageData = curBitmap->LockBits(*rect, Imaging::ImageLockMode::ReadOnly, curBitmap->PixelFormat);
    int PixelSize = Drawing::Bitmap::GetPixelFormatSize(imageData->PixelFormat) / 8;

    //Define the Buffer used to store image data
    auto buffer = gcnew cli::array<byte>(curBitmap->Width * curBitmap->Height);
    //Copy image data into Buffer
    Runtime::InteropServices::Marshal::Copy((IntPtr)&pointer, buffer, 0, buffer->Length);

    //byte* ImgBuf = (byte*)&buffer;
    pin_ptr<byte> ImgBuf = (byte*)&buffer;
    IntPtr^ ptr = gcnew IntPtr(ImgBuf);
    Bitmap^ bitmap = gcnew Drawing::Bitmap(curBitmap->Width, curBitmap->Height, curBitmap->Width, Imaging::PixelFormat::Format8bppIndexed, *ptr);

    palette = bitmap->Palette;
    for (int Index = 0; Index <= byte::MaxValue; Index++)
    {
        palette->Entries[Index] = Drawing::Color::FromArgb(byte::MaxValue, Index, Index, Index);
    }
    bitmap->Palette = palette;
    bitmap->Save("D:\\bitmap_test.bmp");
    return bitmap;

The code tested in C# (by using an unsafe block and fixing the byte-pointer) and the write_image() function of Halcon deliver the following Bitmap, which is how it should look like:

enter image description here

And the bitmap created by the same function in C++/CLI looks like this:

enter image description here

Maestro7
  • 21
  • 2
  • Why you don't use the halcon operator write_image to save the image? – Andrea Mannari Mar 23 '21 at 15:50
  • I think it's better if you split the problem in two parts: first crop the image and save it with write_image. Is it distorted? Second, load the image and convert in bitmap. So you can find if the problem is in the cropping (I don't think so) or in your bitmap convertion. – Andrea Mannari Mar 23 '21 at 15:56
  • @Andrea Mannari Thanks for your comment Andrea! I had already tested the reliability of the cropped image and it works fine. Saving the image was just for debugging. The issue is, the cropped images need to be delivered to a visualization system as Bitmaps and this whole process needs to happen fast, therefore the option of saving the images and loading them again would be runtime costly (especially with parts that have several defects) and could cause some issues, since I'm using a multi-threaded system. Besides, the saved images will take a considerable amount of disk space after a while. – Maestro7 Mar 24 '21 at 11:08
  • @Maestro7 Check if imageData.Stride is equal to the image width. C# might internally use a wider width (rounded to be a multiple of 4 to ensure alignment of rows) than the actual image width. See also: https://stackoverflow.com/questions/2185944/why-must-stride-in-the-system-drawing-bitmap-constructor-be-a-multiple-of-4 – Eph Mar 24 '21 at 13:17
  • @Eph Already checked that before. Stride and the image width are equal and the stride is of course a multiple of 4. My best guess would be that the problem is not necessarily in the Bitmap constructor itself but in the data-management of the buffers/pointers. I tried to pin the source-pointer but the heap still might be interfering with the management of the source-pointer due to the fact that the function is implemented in the "managed" area. – Maestro7 Mar 24 '21 at 14:33
  • @Maestro7 Maybe you could post an image (as it should be and the distorted version), it could help to pinpoint the problem if we can see the distortion. (It also appears that curBitmap is not necessary and UnlockBits is never called, though that should not cause your issue). – Eph Mar 25 '21 at 08:57
  • @Eph I've updated the question with example Bitmaps to illustrate the problem. You're right about the redundancy of curBitmap, which is the remainder of another similar method i've tried but didn't remove but as you've pointed out, it shouldn't be the cause of the issue. – Maestro7 Mar 25 '21 at 11:48

0 Answers0