지식 창고

C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법 본문

프로그래밍/C#

C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법

Lucky-John 2022. 1. 5. 15:55

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=roboinside&logNo=221178543629 

 

C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법 Byte[] <-> Byte*

C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법 C++에서는 OpenCV를 ...

blog.naver.com

 

 C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법
C++에서는 OpenCV를 이용해 변환받고 C#에서는 Bitmap을 통해 이미지를 변환함
C#부분 -------------------------------------------------------------------------------------------------------------------
// 1. C# 상단 구조체 정의
    public struct ImgData 
    { 
        // Indicates that the name field should be marshaled as a C-style 
        // string to the runtime marshaler. 
        public Int32 nDepth; 
        public Int32 nWidth; 
        public Int32 nHeight; 
        public Int32 nChannels; 
        public Int32 nWidthStep; 
        public IntPtr ImageData; 
    }
// 2. DLL Import
        [DllImport("DLL이름.dll", CallingConvention = CallingConvention.Cdecl)] 
        public static extern int ImageIn(byte[] img, int data_len, out ImgData OutImg);
        [DllImport("DLL이름.dll", CallingConvention = CallingConvention.Cdecl)] 
        public static extern int FreeMemory( IntPtr imgPointer );

//- 함수 - 
        private Bitmap GetInOutImage(Bitmap image ) 
        { 
            ImageFormat fmt = new ImageFormat(image.RawFormat.Guid); 
            var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(

                                                codec => codec.FormatID == image.RawFormat.Guid ); 
            if (imageCodecInfo == null)
                fmt = ImageFormat.Jpeg; 

            ImgData OutImg = new ImgData(); 
            using (MemoryStream ms = new MemoryStream()) 
            { 
                MemoryStream convertedImageMemoryStream; 

                image.Save(ms, fmt);  // 이미지를 스트림형으로 변환
                byte[] image_byte_array = ms.ToArray();  // 이미지를 Byte Array 타입으로 변경
                int nLength = image_byte_array.Length;  // 길이 

 

                // 이미지 데이터의 포인터, 길이, 이미지 받을 구조체
                ImageInOut(image_byte_array, nLength, out OutImg);

  
                int columns = OutImg.nWidth; 
                int rows = OutImg.nHeight; 
                long datalength = OutImg.nWidthStep * OutImg.nHeight; 
                byte[] srcData = new byte[OutImg.nWidthStep * OutImg.nHeight]; 
                Marshal.Copy(OutImg.ImageData, srcData, 0, srcData.Length);  // 메모리 카피
                Bitmap im = new Bitmap(columns, rows, OutImg.nWidthStep,PixelFormat.Format24bppRgb, 
               

                // 마샬이용해 메모리에서 Bitmap으로 할당

                Marshal.UnsafeAddrOfPinnedArrayElement(srcData, 0));  
                im.Save("D:\\image21.bmp");  // Bitmap으로 가져온 결과 확인


                // 메모리 해제해주는 코드를 넣어야 함.
                FreeMemory(OutImg.ImageData);
                return im ; 
            } 
        }

C++부분 -------------------------------------------------------------------------------------------------------------------
이미지 구조체 정의 ( C#과 동일한 순서 및 데이터크기로 정의)
struct ImgData 

INT32 nDepth; 
INT32 nWidth; 
INT32 nHeight; 
INT32 nChannels; 
INT32 nWidthStep; 
INT32 ImageData; 
};
extern "C" __declspec(dllexport) int FreeMemory(INT32 pPointer);
extern "C" __declspec(dllexport) int ImageInOut(unsigned char* img_pointer, int data_len, void* const outImg);
extern "C" __declspec(dllexport) int FreeMemory(INT32 pPointer)

    unsigned char* p = (unsigned char*)img_pointer; 
   try { 
         free(p); 
   } 
   catch (const std::exception&) { 
         return 1; 
   } 
return 0; 
}

extern "C" __declspec(dllexport) int ImageInOut(unsigned char* img_pointer, int data_len, void* const outImg)
{
   if (img_pointer == NULL || data_len == 0  || outImg == NULL) 
      return -1; 
   vector<unsigned char> inputImageBytes(img_pointer, img_pointer + data_len); 
   cv::Mat Src = imdecode(inputImageBytes, CV_LOAD_IMAGE_COLOR);  // OpenCV통해 변환
   cv::Mat DstImg; 
   DstImg = Src.clone();  
   imshow("ggg", DstImg);  // 변환확인함.
   ImgData* pOutImg = (ImgData*)outImg; 
   pOutImg->nWidth = DstImg.cols; 
   pOutImg->nHeight = DstImg.rows; 
   pOutImg->nWidthStep = DstImg.step; 
   pOutImg->nChannels = DstImg.channels(); 
   uchar* pimgData = new uchar[pOutImg->nWidth*pOutImg->nHeight*pOutImg->nChannels]; // 나중에 해제 필요
   memcpy(pimgData, DstImg.data, pOutImg->nWidth*pOutImg->nHeight*pOutImg->nChannels); 
   pOutImg->ImageData = ( IntPtr)pimgData;
   return 0;
}

'프로그래밍 > C#' 카테고리의 다른 글

C# 예시 코드로 문법 설명 참고 페이지  (0) 2022.02.23
윈도우즈 서비스 프로그램  (0) 2022.01.06
컬렉션 & 제네릭 사용하기  (0) 2021.11.03
Array  (0) 2021.11.02
데이터 형식 사용하기  (0) 2021.11.02
Comments