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;
		}

새 블로그를 시작합니다.

기존에도 사용하던 블로그가 있었지만 제 직업과 관련한 기록에 좀 더 집중할 수 있는 공간이 필요했습니다.

본래 이글루스를 제 일상과 직업을 모두 기록하는 공간으로 삼고 싶었지만,  기술과 트렌드의 변화 그리고 제 자신의 삶의 변화에서 그 공간을 한결같이 유지하기란 쉬운 일이 아니더군요. 더욱이 시콜콜한 일상을 다루기에는 SNS 등 다른 공간이 더욱 적합한 것 같습니다. 그리고 이미 그러한 공간을 잘 활용하고 있기도 하구요. 이글루스는 그냥 스무살의 스냅샷으로 남겨두는 것도 나름 의미가 있겠다 싶었습니다.

이곳 워드프레스에서는 소프트웨어 엔지니어로서의 기록을 남기려 합니다. 저도 결국 양질의 정보를 얻는 곳은 다른 개발자들의 세심한 포스팅이 있는 블로그이더군요. 남들로부터 많이 받고 있으니 저도 조금이라도 줄 수 있도록 노력하는게 마땅하다고 생각을 했습니다. 그래서 이전 블로그에서는 제 자신만을 위해 포스팅을 했지만, 이제는 오시는 분들에게 조금이나마 도움이 될 수 있도록 약간(아주 약간…^^;) 더 신경을 써보려합니다.