Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从.DLL获取位图,转换为字节[]并转换为图像_C#_C++_Image_Bitmap_Bytearray - Fatal编程技术网

C# 从.DLL获取位图,转换为字节[]并转换为图像

C# 从.DLL获取位图,转换为字节[]并转换为图像,c#,c++,image,bitmap,bytearray,C#,C++,Image,Bitmap,Bytearray,我收到了一个用于测试的.DLL,该.DLL包含稍后将用于处理来自硬件的实时图像的功能 对于这个简单的.dll,我可以打开一个图像(加载到内存中),获取宽度和高度,以及需要转换为图像的像素。加载、获取宽度和高度都很好,但是获取像素并将其转换为位图或图像是一个问题 我收到的C++示例源代码: ApiFunc->OpenImageFile(this->OpenPictureDialog1->FileName.c_str()); ApiFunc->AllocMemory(); w=ApiFunc->Ge

我收到了一个用于测试的.DLL,该.DLL包含稍后将用于处理来自硬件的实时图像的功能

对于这个简单的.dll,我可以打开一个图像(加载到内存中),获取宽度和高度,以及需要转换为图像的像素。加载、获取宽度和高度都很好,但是获取像素并将其转换为位图或图像是一个问题

我收到的C++示例源代码:

ApiFunc->OpenImageFile(this->OpenPictureDialog1->FileName.c_str());
ApiFunc->AllocMemory();
w=ApiFunc->GetImageWidth();
h=ApiFunc->GetImageHeight();
图像1->宽度=w;
图1->高度=h;
无符号字符*ptr=ApiFunc->GetImagePixels();
彩色参考像素;
int r,g,b;
对于(inty=0;yPixels[y][x]=RGB(r,g,b);
}
ptr+=3*h;
}
在ApiFunc中,可以找到:

void\uu快速调用TAPIFunc::LoadDll(HINSTANCE m\u hMain)
{
//上面还有一些
GET_IMAGE_PIXELS=(func_GET_IMAGE_PIXELS)GetProcAddress(m_hMain,“GET_IMAGE_PIXELS”);
//下面还有一些
}
无符号字符*\uuu快速调用TAPIFunc::GetImagePixels(空)
{
返回GET_IMAGE_PIXELS();
}
现在我已经尝试过了,我尝试过使用byte[]作为返回参数,但这会引发MarshalDirectiveException

[DllImport(“ImageTest.dll”)]
公共静态外部IntPtr GET_IMAGE_PIXELS();
私有void OpenImage(字符串文件名)
{
打开图像文件(文件名);
ALLOC_内存();
int width=GET_IMAGE_width();/=800
int height=GET_IMAGE_height();/=600
IntPtr buffer=GET_IMAGE_PIXELS();
int size=width*height*3;//不确定大小必须是多少,我认为这是问题之一,只是遵循下面一个答案的逻辑。
//但资料来源:https://stackoverflow.com/a/16300450/2901207
byte[]bitmapImageArray=新字节[大小];
Marshal.Copy(缓冲区,bitmapImageArray,0,大小);
位图位图=新位图(宽度、高度、像素格式.Format24bppRgb);
BitmapData bmData=bitmap.LockBits(新系统.绘图.矩形(0,0,bitmap.Width,bitmap.Height),ImageLockMode.ReadWrite,bitmap.PixelFormat);
IntPtr pNative=bmData.Scan0;
封送处理副本(imageData,0,pNative,size);
位图。解锁位(bmData);
保存(Environment.CurrentDirectory+@“\result.bmp”);
使用(var ms=new MemoryStream(bitmapImageArray))
{
//两个抛出异常:参数无效
位图bmp=新位图(毫秒);
Image bitmapImage=Image.FromStream(毫秒);
}
}
答复来源:

为了确保我有一个有效的图像进行测试,我在photoshop中保存了一个图像,带有以下选项:

丑陋的测试图像:

结果:

很美,不是吗?:)

还尝试使用for循环,并一直运行到崩溃。运行直到计数=1441777,在另一个图像上计数=1527793(相同尺寸)

int count=0;
对于(int i=0;i
从错误的结果来看,水平/垂直方向实际上已切换。您的图像是通过逐列组织的像素获得的,而不是按行组织的像素(通常是这样)

您收到的示例源证实了这一点:外部循环转到w(宽度),内部循环转到h(高度),尽管外部变量是y,内部变量是x,这令人困惑

看起来R和B组件也被切换了(这里我没有解释,但相信我)

因此,在使用

byte[]bitmapImageArray=新字节[大小]; Marshal.Copy(缓冲区,bitmapImageArray,0,大小)

你必须重新组织它。分配另一个大小相同的缓冲区
bitmapImageArray2
,在所有像素上循环(按您的喜好逐行或逐列循环,但变量命名正确,不同于示例:x到w,y到h),并将其写入目标数组,如下所示:

bitmapImageArray2[(y * w + x) * 3] = bitmapImageArray[(x * h + y) * 3 + 2];
bitmapImageArray2[(y * w + x) * 3 + 1] = bitmapImageArray[(x * h + y) * 3 + 1];
bitmapImageArray2[(y * w + x) * 3 + 2] = bitmapImageArray[(x * h + y) * 3];

注意:您的
大小值似乎是正确的。

好的,虽然这确实解决了问题,但我仍然不满意,当然我很高兴得到一些结果,但我认为这需要很长时间。从实例化位图到保存前需要:241ms。虽然这看起来很小,但检索像这样需要生成流畅视频的图像有点错误

        for (int y = 0; y < width; y++)
        {
            for (int x = 0; x < height; x++)
            {
                int red = imageData[offset + 3 * x] ;
                int green = imageData[offset + 3 * x + 1];
                int blue = imageData[offset + 3 * x + 2];
                Color color = Color.FromArgb(red, green, blue);
                bitmap.SetPixel(y, x, color);
            }
            offset += 3 * height;
        }
for(int y=0;y
@Dim的回答很有帮助,首先进行转换,然后像以前一样处理,大大提高了速度

因此,结果是:

    private void OpenImage(string filename)
    {
        OPEN_IMAGE_FILE(filename);
        ALLOC_MEMORY();
        int width = GET_IMAGE_WIDTH();
        int height = GET_IMAGE_HEIGHT();
        IntPtr buffer = GET_IMAGE_PIXELS();
        int size = width * height * 3;
        byte[] bitmapImageArray = new byte[size];
        Marshal.Copy(buffer, bitmapImageArray, 0, size);
        Bitmap bitmap3 = ConvertImage3(bitmapImageArray, height, width);
    }

    public Bitmap ConvertImage3(byte[] imageData, int height, int width)
    {
        int size = width * height * 3;
        byte[] bitmapImageArray2 = new byte[size];
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                bitmapImageArray2[(y * width + x) * 3] = imageData[(x * height + y) * 3 + 2];
                bitmapImageArray2[(y * width + x) * 3 + 1] = imageData[(x * height + y) * 3 + 1];
                bitmapImageArray2[(y * width + x) * 3 + 2] = imageData[(x * height + y) * 3];
            }
        }

        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
        IntPtr pNative = bmData.Scan0;
        Marshal.Copy(bitmapImageArray2, 0, pNative, width * height * 3);
        bitmap.UnlockBits(bmData);
        return bitmap;
    }
private void OpenImage(字符串文件名)
{
打开图像文件(文件名);
ALLOC_内存();
int width=GET_IMAGE_width();
int height=GET_IMAGE_height();
IntPtr buffer=GET_IMAGE_PIXELS();
整数大小=宽度*高度*3;
byte[]bitmapImageArray=新字节[大小];
Marshal.Copy(缓冲区,bitmapImageArray,0,大小);
位图bitmap3=ConvertImage3(bitmapImageArray、高度、宽度);
}
公共位图转换器Image3(字节[]imageData,整数高度,整数宽度)
{
整数大小=宽度*高度*3;
byte[]bitmapImageArray2=新字节[大小];
对于(int y=0;y