2012-06-26 31 views
0

我想實現一個應用程序,它使用RIOT(自由圖像優化工具)批量圖像優化。我可以成功導入riot.dll到我的應用程序。但我無法弄清楚如何將Windows DIB(設備無關位圖)句柄傳遞給RIOT函數。將C#位圖轉換爲用於RIOT的Windows 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 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 was unhandled - Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

所以我的問題是:

  1. 如何將一個System.Bitmap對象到Windows DIB句柄?
  2. 如果我不能轉換是否可以使用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); 
     } 
    } 
} 

回答

0

下面是該方法的 「文檔」:

bool RIOT_SaveToFile(HANDLE hDIB, HWND hwndParent,const char *fileName,const char *origFilename=」", unsigned long byteSize=0,char *errorText=」",int flags=0, char *buf=」") 

Saves the file with the specified parameters. 

Parameters: 
hDIB – handle to a Windows DIB image in memory 
hwndParent – Not Used. Must be NULL. 
fileName – full path to the file to be saved (only JPEG is supported) 
origFilename – Fill this with the original file name if the DIB is not different than the image from the file 
byteSize – filesize of the compressed JPEG image in bytes 
errorText – On error errorText is filled with the error message 
flags – save flags. See bellow 
buf – not used. Leave blank.THe function returns true on success or false on error.If you specify byteSize you can specify any of the save flags, but the quality will not be used. 
If you don’t specify byteSize flags are used. 
If there are no flags or byteSize is 0 an error is thrown.Flags for RIOT_SaveToFile:0×0001 – keep EXIF 
0×0002 – keep IPTC 
0×0004 – keep XMP 
0×0008 – keep Comments 
0×1000 – keep ICC profile0x0800 – save greyscale 
0×2000 – save progressive 
0×10000 – disable chroma subsamplingAlso you can set a quality flag from 1 to 100Ex: flags=JPEG_SUBSAMPLING_444 | JPEG_PROGRESSIVE | 90 
results in a file with no subsampling, progressive with a quality of 90 
If you don’t specify quality 75 is used. 
You must specify JPEG_PROGRESSIVE if you want progressive. 
If you don’t specify JPEG_SUBSAMPLING_444 a default chroma of 4:2:0 is used. 

的第一個問題是errorText。該文檔指出,「錯誤errorText充滿了錯誤信息。」這表明你必須傳遞一個未指定長度的字節數組來填充。這太可怕了。

第二個問題是它說:「如果沒有標誌或字節大小爲0,則會引發錯誤。」

我的猜測是你得到一個錯誤,它試圖將字節複製到errorText中。嘗試傳遞一個大字節[]而不是字符串。

1

您的System.Drawing.Bitmap對象是設備相關位圖(DDB)。您需要一個設備無關位圖(DIB)。我不知道在.Net框架中有任何幫助,但你可以通過p/Invoke CreateDIBSection創建一個。

相關問題