2012-07-25 99 views
1

我正在使用我发现的代码将SVG文件栅格化为图像文件。链接是http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24547525.html。我的代码看起来相同的,但我得到一个访问冲突:Gimp gdk_pixbuf_save失败,出现AccessViolationException但我不知道为什么?

“试图读取或写入保护内存这通常是指示其他内存已损坏。”`

为了消除明显:我使用Gimp目录下的svg文件,所以我有一个已知的好文件。我使用e:作为文件保存位置,以便库不会触及任何安全性/权限内容。如果遇到问题,我正在运行具有管理权限的Visual Studio。我的盒子是64位,并且我将Local.testsettings设置为“在64位机器上的64位进程中运行测试”。

任何想法?

我的代码是:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.ComponentModel; 

namespace TA.Rasterizer 
{ 
    /// <summary> 
    /// Takes SVG image file type and converts to PNG image file type. 
    /// Gimp must be installed. Gimp dll location must be in the web.config 
    /// file key "ThreatAnalyzer-DllDirectoryForGimp". 
    /// <summary> 
    /// http://msdn.microsoft.com/en-us/magazine/cc164123.aspx 
    /// http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24547525.html 
    /// </summary> /// </summary> 
    public static class Rasterizer 
    { 
     // C:\Windows\System32 
     [DllImport("kernel32.dll", SetLastError = true)] 
     static extern bool SetDllDirectory(string pathname); 

     [DllImport("libgobject-2.0-0.dll", SetLastError = true)] 
     static extern void g_type_init(); 

     [DllImport("librsvg-2-2.dll", SetLastError = true)] 
     static extern IntPtr rsvg_pixbuf_from_file_at_size(string file_name, int width, int height, out IntPtr error); 

     [DllImport("libgdk_pixbuf-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] 
     static extern bool gdk_pixbuf_save(IntPtr pixbuf, string filename, string type, out IntPtr error, __arglist); 
     //static extern bool gdk_pixbuf_save_to_buffer(

     /// <summary> 
     /// Get location of Gimp installed Dlls from web.config appsettings key/value. 
     /// Key name is found in this.webConfigFileAppSettingsGimp 
     /// </summary> 
     /// <returns></returns> 
     private static string GetGimpDllLocationFromConfigurationFile(bool webapp, string nonDefaultConfigFileName) 
     { 
      // connect to config file 
      Configuration rasterizerConfiguration = new TA.Rasterizer.Configuration(webapp, nonDefaultConfigFileName); 

      // grab config setting 
      return rasterizerConfiguration.Get("ThreatAnalyzer-DllDirectoryForGimp"); 
     } 

     /// <summary> 
     /// http://msdn.microsoft.com/en-us/magazine/cc164123.aspx 
     /// You must check that file exists after call in order to check success. 
     /// </summary> 
     /// <param name="inputFileName">SVG file to be converted</param> 
     /// <param name="outputFileName">PNG file as final product</param> 
     /// <returns></returns> 
     public static void SvgToPng(string inputFileName, string outputFileName, bool webapp, string nonDefaultConfigFileName) 
     { 
      string gimpDllLocation = GetGimpDllLocationFromConfigurationFile(webapp, nonDefaultConfigFileName); 

      bool rasterizeSuccess = ExternRaster.RasterizeSvg(inputFileName, outputFileName, gimpDllLocation); 

      if (!rasterizeSuccess) 
      { 
       Int32 err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); 
       throw new Win32Exception(err); 
      } 
     } 

    /// <summary> 
    /// http://msdn.microsoft.com/en-us/magazine/cc164123.aspx 
    /// http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24547525.html 
    /// </summary> 
    internal sealed class ExternRaster 
    { 

     public static bool RasterizeSvg(string inputFileName, string outputFileName, string gimpDllLocation) 
     { 
      bool callSuccessful = SetDllDirectory(gimpDllLocation); 
      if (!callSuccessful) 
      { 
       throw new Exception("Could not set DLL directory"); 
      } 
      g_type_init(); 
      IntPtr error1; 
      IntPtr result = rsvg_pixbuf_from_file_at_size(@"E:\green.svg", -1, -1, out error1); 
      if (error1 != IntPtr.Zero) 
      { 
       throw new Exception(Marshal.ReadInt32(error1).ToString()); 
      } 

      IntPtr error2; 
      callSuccessful = gdk_pixbuf_save(result, @"E:\green.jpg", "jpg", out error2, __arglist(null)); 
      if (!callSuccessful) 
      { 
       throw new Exception(error2.ToInt32().ToString()); 
      } 

      return true; 
     } 

    } 



    } 
} 

我从MSTest的单元测试访问代码:

/// <summary> 
    ///A test for RasterizeSvg 
    ///</summary> 
    [TestMethod()] 
    public void RasterizeSvgTest() 
    { 
     // arrange 
     string svgFileNameInAppDirectory = "1kijvsrewxxr3mdvlwitjvyu-pie.svg"; 

     string currentClassLibDirectory = Environment.CurrentDirectory.Replace(@"\bin\debug\",""); 
     string pathToAppData = Setup.GetDataPath(); 
     string inputFileName = Path.Combine(pathToAppData, svgFileNameInAppDirectory); 
     string outputFileName = Path.Combine(pathToAppData, svgFileNameInAppDirectory.Replace("svg","png")); 
     bool webapp = false; 
     string nonDefaultConfigFileName = string.Empty; 

     // act 
     Rasterizer.SvgToPng(inputFileName, outputFileName, webapp, nonDefaultConfigFileName); 

     // assert 
     bool fileExists = File.Exists(outputFileName); 
     Assert.IsTrue(fileExists); 

     // cleanup 
     if (fileExists) 
     { 
      File.Delete(outputFileName); 
     } 
    } 
+0

如果您使用“MarshallAs”修改您的导入,如下所述会发生什么情况:http://msdn.microsoft.com/en-us/library/ms182206(v=vs.80).aspx? 此外,这可能不是问题,但它看起来从文档(这里:http://www.gtk.org/api/2.6/gdk-pixbuf/gdk-pixbuf-file-saving.html#gdk -pixbuf-save)保存的默认文件类型是“jpeg”,“png”和“ico”。您保存为“jpg”(不是“e”)。 – GojiraDeMonstah 2013-06-14 20:00:19

回答

1

documentation for rsvg_pixbuf_from_file_at_size

如果发生错误,错误被设置并返回NULL。

对我来说,这可能意味着,如果成功,您的error1变量不会被设置为有效指针。您应该测试返回值result

我认为@GojiraDemonstah对“jpg”与“jpeg”的说法也很重要。

此外,rsvg_pixbuf_from_file_at_size分配一个新的GdkPixbuf,你没有任何代码来释放它。要做到这一点,你应该也有

[DllImport("libgobject-2.0-0.dll", SetLastError = true)] 
static extern void g_object_unref(IntPtr obj); 
在进口

g_object_unref(result); 

呼吁gdk_pixbuf_save,以避免内存泄漏后。

相关问题