지식 창고
C#에서 메모리에 로드된 이미지를 전달하거나 C++에서 C#으로 전달 받는 방법 본문
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 |