我正在尝试实现一个使用 RIOT(激进图像优化工具)进行批量图像优化的应用程序。我可以成功地将riot.dll导入我的应用程序。但我无法弄清楚如何将 Windows DIB(设备独立位图)句柄传递给 RIOT 函数。
这是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Riot_Test
{
public partial class Form1 : Form
{
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern bool RIOT_LoadFromDIB(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName = "", [MarshalAs(UnmanagedType.LPStr)] string iniFile = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
[DllImport("RIOT.dll")]
static extern void RIOT_Show();
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern bool RIOT_LoadFromFile([MarshalAs(UnmanagedType.LPStr)] string filename, int flags = 0);
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RIOT_SaveToFile(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName, [MarshalAs(UnmanagedType.LPStr)] string origFilename = "", ulong byteSize = 0, [MarshalAs(UnmanagedType.LPStr)] string errorText = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
public Form1()
{
InitializeComponent();
//RIOT_Show();
IntPtr hdib = IntPtr.Zero;
IntPtr hwnd = IntPtr.Zero;
string errorText = "";
Bitmap bmp = new Bitmap("dene.jpg");
hdib = bmp.GetHbitmap();
string fn = "optim2.jpg";
string fno = "dene.jpg";
bool result = RIOT_SaveToFile_U(hdib, hwnd, fn);
}
}
}
RIOT_Show()
并且RIOT_Load_From_File()
按预期工作但是当我尝试调用RIOT_SaveToFile()
它时给我这个错误:
System.AccessViolationException 未处理 - 试图读取或写入受保护的内存。这通常表明其他内存已损坏。
所以我的问题是:
- 如何将
System.Bitmap
对象转换为 Windows DIB 句柄? - 如果我无法转换,是否可以使用 C++ 库(如果有)为我完成这项工作并返回 DIB 句柄?
编辑:
我已将代码更改为此,但它给出了相同的错误。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace from_vb
{
public partial class Form1 : Form
{
[DllImport("gdi32.dll", SetLastError = true)]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In] ref GDI32BITMAPINFOHEADER pbmi, uint pila, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
[DllImport("gdi32.dll")]
static extern int GetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan,
uint cScanLines, [Out] byte[] lpvBits, ref GDI32BITMAPINFOHEADER lpbmi, uint uUsage);
[DllImport("gdi32.dll")]
static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
static extern bool GdiFlush();
[DllImport("RIOT.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, SetLastError = true)]
static extern bool RIOT_SaveToFile(IntPtr hDIB, IntPtr hwndParent, [MarshalAs(UnmanagedType.LPStr)] string fileName, [MarshalAs(UnmanagedType.LPStr)] string origFilename = "", ulong byteSize = 0, [MarshalAs(UnmanagedType.LPStr)] string errorText = "", int flags = 0, [MarshalAs(UnmanagedType.LPStr)] string buf = "");
public const int BI_RGB = 0;
public const int DIB_PAL_COLORS = 1;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct GDI32BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public short bmPlanes;
public short bmBitsPixel;
public int bmBits;
}
[StructLayout(LayoutKind.Sequential)]
public struct GDI32BITMAPINFOHEADER
{
public int biSize;
public int biWidth;
public int biHeight;
public short biPlanes;
public short biBitCount;
public int biCompression;
public int biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (int)Marshal.SizeOf(this);
}
}
public Form1()
{
InitializeComponent();
IntPtr hdc = IntPtr.Zero;
IntPtr hSrcBitmap = IntPtr.Zero;
IntPtr pSrcBitmapInfo = IntPtr.Zero;
IntPtr hDestDIBitmap = IntPtr.Zero;
IntPtr hDstOldBitmap = IntPtr.Zero;
IntPtr pDestDIBits = IntPtr.Zero;
IntPtr hSection = IntPtr.Zero;
IntPtr hwnd = IntPtr.Zero;
IntPtr ccDC = IntPtr.Zero;
Bitmap dotNetBitmap;
int XDPI, YDPI;
GDI32BITMAP srcBitmapInfo = new GDI32BITMAP();
//ccDC = CreateCompatibleDC(hdc);
IntPtr hDstMemDC = CreateCompatibleDC(hdc);
GDI32BITMAPINFOHEADER DestDIBMIH = new GDI32BITMAPINFOHEADER();
dotNetBitmap = new Bitmap("dene.jpg");
hSrcBitmap = dotNetBitmap.GetHbitmap();
pSrcBitmapInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(srcBitmapInfo));
GetObject(hSrcBitmap, Marshal.SizeOf(srcBitmapInfo),pSrcBitmapInfo);
srcBitmapInfo = (GDI32BITMAP)Marshal.PtrToStructure(pSrcBitmapInfo, srcBitmapInfo.GetType());
if (pSrcBitmapInfo != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pSrcBitmapInfo);
}
DestDIBMIH.biSize = Marshal.SizeOf(DestDIBMIH);
DestDIBMIH.biWidth = srcBitmapInfo.bmWidth;
DestDIBMIH.biHeight = srcBitmapInfo.bmHeight;
DestDIBMIH.biPlanes = srcBitmapInfo.bmPlanes;
DestDIBMIH.biBitCount = 24;
DestDIBMIH.biCompression = BI_RGB;
hDestDIBitmap = CreateDIBSection(hDstMemDC, ref DestDIBMIH, 0, out pDestDIBits, hSection, 0);
string fn = "optim2.jpg";
string fno = "dene.jpg";
bool hede = RIOT_SaveToFile(hDestDIBitmap, hwnd, fn);
}
}
}