我正在使用我发现的代码将SVG文件栅格化为图像文件。链接是http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_24547525.html。我的代码看起来完全相同,但我的访问权限违反了:
“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”`
为了消除明显的:我使用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 :(得分: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
以避免内存泄漏。