Halcon 이미지와 .NET Bitmap 변환

Halcon Image를 .NET Bitmap으로 변환하는 기능이 없어서(혹은 있는데 못찾아서) 후다닥 간단하게 만들어 봤습니다.
제가 살펴본 버전이 Halcon 10이라서 Halcon 11에는 이미 더 나은 API가 제공되고 있을지도 모르겠네요.

변환 기능만 고려하고 성능, 예외처리 같은 건 고려하지 않았기 때문에 본격적으로 사용하기에는 많이 부족합니다.
필요하다면 아래 소스는 자유롭게 쓰셔도 됩니다.

		/// <summary>
		/// Halcon Image를 .NET Bitmap 형식으로 변환합니다.
		/// </summary>
		/// <param name="halconImage"></param>
		/// <returns></returns>
		public static Bitmap ConvertHalconImageToBitmap(HObject halconImage)
		{
			if (halconImage == null)
			{
				throw new ArgumentNullException("halconImage");
			}

			HTuple pointerRed;
			HTuple pointerGreen;
			HTuple pointerBlue;
			HTuple type;
			HTuple width;
			HTuple height;

			// Halcon 컬러 이미지의 포인터를 얻는다.
			HOperatorSet.GetImagePointer3(halconImage, out pointerRed, out pointerGreen, out pointerBlue, out type, out width, out height);

			// .NET에서 포인터를 사용하기 위해 IntPtr 형식으로 변환
			IntPtr ptrR = new IntPtr(pointerRed);
			IntPtr ptrG = new IntPtr(pointerGreen);
			IntPtr ptrB = new IntPtr(pointerBlue);

			// 24bit RGB 형식을 기본으로 사용함
			Bitmap bitmap = new Bitmap((Int32)width, (Int32)height, PixelFormat.Format24bppRgb);

			BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
			int bytes = Math.Abs(bmpData.Stride) * bitmap.Height;
			byte[] rgbValues = new byte[bytes];

			// Stride 값 보정
			int unmapByes = Math.Abs(bmpData.Stride) - (width * 3);

			// 루프를 돌면서 lock된 bit 배열에 데이터를 써넣음.
			for (int i = 0, offset = 0; i < bytes; i += 3, offset++)
			{
				if ((offset + 1) % width == 0)
				{
					i += unmapByes;
				}

				rgbValues[i] = Marshal.ReadByte(ptrB, offset);
				rgbValues[i + 1] = Marshal.ReadByte(ptrG, offset);
				rgbValues[i + 2] = Marshal.ReadByte(ptrR, offset);
			}

			Marshal.Copy(rgbValues, 0, bmpData.Scan0, bytes);
			bitmap.UnlockBits(bmpData);
			return bitmap;
		}

		/// <summary>
		/// .NET bitmap을 Halcon HImage로 변환합니다.
		/// </summary>
		/// <param name="bitmap"></param>
		/// <returns></returns>
		public static HImage ConvertBitmapToHalconImage(Bitmap bitmap)
		{
			if (bitmap == null)
			{
				throw new ArgumentNullException("bitmap");
			}

			int width = bitmap.Width;
			int height = bitmap.Height;
			int ptrSize = width * height;

			// R/G/B 각 채널에 대해 메모리를 할당
			IntPtr ptrR = Marshal.AllocHGlobal(ptrSize);
			IntPtr ptrG = Marshal.AllocHGlobal(ptrSize);
			IntPtr ptrB = Marshal.AllocHGlobal(ptrSize);

			// Bitmap에서 RGB 값을 읽어서 저장
			int offset = 0;
			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					Color c = bitmap.GetPixel(x, y);
					Marshal.WriteByte(ptrR, offset, c.R);
					Marshal.WriteByte(ptrG, offset, c.G);
					Marshal.WriteByte(ptrB, offset, c.B);
					offset++;
				}
			}

			// Himage로 변환
			HImage halconImage = new HImage();
			halconImage.GenImage3("byte", width, height, ptrR, ptrG, ptrB);

			Marshal.FreeHGlobal(ptrB);
			Marshal.FreeHGlobal(ptrG);
			Marshal.FreeHGlobal(ptrR);

			return halconImage;
		}

Advertisements