编辑:所以,我知道发生了什么,我只是不明白为什么。我的Dictionary<string, object>
存储的字体很好,但是有一个特定的函数可以运行,当它运行时,字典会被部分删除。
这些图片之间运行的代码是:
public static int countLines(string a)
{
int count = 0;
string line;
System.IO.StreamReader file;
try
{
file = new System.IO.StreamReader(@a);
}
catch (Exception ex)
{
MessageBox.Show("Missing " + a + "\n\n" + ex.ToString(), "Exception");
return 0;
}
while ((line = file.ReadLine()) != null)
{
if (line.Substring(0, 2) == "10") { count++; }
}
file.Close();
return count;
}
---结束编辑---
当我使用太多自定义字体时,我得到this tracedump。我使用相同的solution listed here,并尝试了投票修复(删除dispose和一个编组调用),这会立即导致GDI +错误。实际上,我有该代码的修改版本,以便我可以调用并获取不同的字体:
#region Font setup
//Setup code for custom fonts
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(byte[] pbFont, int cbFont, IntPtr pdv, out uint pcFonts);
[DllImport("gdi32.dll")]
internal static extern bool RemoveFontMemResourceEx(IntPtr fh);
static private IntPtr m_fh = IntPtr.Zero;
static private PrivateFontCollection m_pfc = null;
public static Font getFont(string fonttype, float size)
{
m_pfc = null;
Font fnt = null;
if (null == m_pfc)
{
Stream stmFont = null;
// First load the font as a memory stream
switch (fonttype)
{
case "MICR":
stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream("QATestFileGenTools.Fonts.MICR.ttf");
break;
case "HAND":
Random rnd = new Random(DateTime.Now.Millisecond);
int rr = rnd.Next(0, 3);
if (rr == 0)
{
stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream("QATestFileGenTools.Fonts.hand1.ttf");
size += rnd.Next(0, 4);
}
if (rr == 1)
{
stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream("QATestFileGenTools.Fonts.hand2.ttf");
size += rnd.Next(2, 6);
}
if (rr == 2)
{
stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream("QATestFileGenTools.Fonts.hand3.ttf");
size += rnd.Next(6, 10);
}
break;
case "SIG":
stmFont = Assembly.GetExecutingAssembly().GetManifestResourceStream("QATestFileGenTools.Fonts.signature.ttf");
break;
default:
MessageBox.Show("Bad call to getFont()", "Error");
break;
}
if (null != stmFont)
{
//
// GDI+ wants a pointer to memory, GDI wants the memory.
// We will make them both happy.
//
// First read the font into a buffer
byte[] rgbyt = new Byte[stmFont.Length];
stmFont.Read(rgbyt, 0, rgbyt.Length);
// Then do the unmanaged font (Windows 2000 and later)
// The reason this works is that GDI+ will create a font object for
// controls like the RichTextBox and this call will make sure that GDI
// recognizes the font name, later.
uint cFonts;
AddFontMemResourceEx(rgbyt, rgbyt.Length, IntPtr.Zero, out cFonts);
// Now do the managed font
IntPtr pbyt = Marshal.AllocCoTaskMem(rgbyt.Length);
if (null != pbyt)
{
Marshal.Copy(rgbyt, 0, pbyt, rgbyt.Length);
m_pfc = new PrivateFontCollection();
m_pfc.AddMemoryFont(pbyt, rgbyt.Length);
Marshal.FreeCoTaskMem(pbyt);
}
}
}
if (m_pfc.Families.Length > 0)
{
// Handy how one of the Font constructors takes a
// FontFamily object, huh? :-)
fnt = new Font(m_pfc.Families[0], size);
}
m_pfc.Dispose();
return fnt;
}
//End setup for fonts
#endregion
如果删除dispose()和FreeCoTaskMem()is this,我不可避免地会遇到GDI +错误。
这两个问题都不会立即发生。看起来我可以在抛出任何异常之前平均运行20-25次。
任何想法都将不胜感激。当我只使用单一字体时,我从未遇到过错误(每次都可能产生1000+)。至少,有趣的是,如果我只调用两种字体,它也不是问题。但当&#34; HAND&#34;被抛入混合物中,这似乎是个问题。
调用它的方法是:
public static byte[] GenCheckImage(string outputPath, string frontBack, string MICRline, string amount, string[] imageOptions, Dictionary<string, object> dictCfgIn, string names = "John Smith", string date = null, string lar = null)//, string payeeName, string date)
{
System.Reflection.Assembly thisExe;
thisExe = System.Reflection.Assembly.GetExecutingAssembly();
if (date == null)
{
date = DateTime.Now.AddDays(-4).ToString("d");
}
if (lar == null)
{
lar = "Some Dollars & xx/100";
}
if (frontBack == "F")
{
//Open the front image to frontImage Image source from embedded resource
System.IO.Stream file;
Random rnd = new Random(DateTime.Now.Millisecond);
int a = rnd.Next(imageOptions.Length);
// if (a == 0) {file = thisExe.GetManifestResourceStream("QATestFileGenTools.checkFront1.bmp");}
// else if (a == 1) {file = thisExe.GetManifestResourceStream("QATestFileGenTools.checkFront2.bmp");}
file = thisExe.GetManifestResourceStream(imageOptions[a]);
Bitmap b;
using (System.Drawing.Image frontImage = System.Drawing.Image.FromStream(file))//;
{
byte[] binaryData = new Byte[file.Length];
long bytesRead = file.Read(binaryData, 0,
(int)file.Length);
Bitmap b2 = new Bitmap(frontImage);
file.Close();
Font micrFont = getFont("MICR", 18);
Font objFont;
if ((bool)dictCfgIn["Handwriting"])
objFont = getFont("HAND", 20);
else
objFont = new System.Drawing.Font("Arial", 20);
Font sigFont = getFont("SIG", 30);
string[] sigName = NSCreateRAW.CreateRaw.genName();
string sigString = sigName[0] + sigName[1] + rnd.Next(1, 6).ToString();
amount = amount.TrimStart('0'); //Insert(2, "XYZ")
amount = amount.Insert((amount.Length - 2), ".");
//Draw something
//Bitmap b = new Bitmap(frontImage);
b = new Bitmap(frontImage);
Graphics graphics = Graphics.FromImage(b);
if (imageOptions[a] == "QATestFileGenTools.checkFront1.bmp") // ProfitStars Check Template
{
graphics.DrawString(date, objFont, Brushes.Black, 690, 150);
graphics.DrawString(lar, objFont, Brushes.Black, 150, 280);
graphics.DrawString(names, objFont, Brushes.Black, 200, 215);
graphics.DrawString(MICRline, micrFont, Brushes.Black, 200, 490);
graphics.DrawString(amount, objFont, Brushes.Black, 985, 230);
graphics.DrawString(sigString, sigFont, Brushes.Black, 680, 400);
}
else if (imageOptions[a] == "QATestFileGenTools.checkFront2.bmp") // TWS Check Template
{
graphics.DrawString(date, objFont, Brushes.Black, 735, 105);
graphics.DrawString(lar, objFont, Brushes.Black, 160, 250);
graphics.DrawString(names, objFont, Brushes.Black, 200, 165);
graphics.DrawString(MICRline, micrFont, Brushes.Black, 200, 490);
graphics.DrawString(amount, objFont, Brushes.Black, 1020, 185);
graphics.DrawString(sigString, sigFont, Brushes.Black, 690, 380);
}
else if (imageOptions[a] == "QATestFileGenTools.checkFront3.bmp") // "Blank" Check Template
{
graphics.DrawString(date, objFont, Brushes.Black, 935, 110);
graphics.DrawString(lar, objFont, Brushes.Black, 180, 275);
graphics.DrawString(names, objFont, Brushes.Black, 220, 210);
graphics.DrawString(MICRline, micrFont, Brushes.Black, 220, 470);
graphics.DrawString(amount, objFont, Brushes.Black, 1000, 210);
graphics.DrawString(sigString, sigFont, Brushes.Black, 690, 395);
}
else
{
//graphics.DrawString(MICRline, micrFont, Brushes.Black, 200, 490);
//graphics.DrawString(amount, objFont, Brushes.Black, 985, 230);
}
if ((bool)dictCfgIn["Bad Images"] && (bool)dictCfgIn["Skew Images"])
{
Point[] destinationPoints = {
new Point(0, 50), // destination for upper-left point of
// original
new Point(1170, 0), // destination for upper-right point of
// original
new Point(30, 585)};
graphics.DrawImage(b, destinationPoints);
}
if ((bool)dictCfgIn["Bad Images"] && (bool)dictCfgIn["Bar Images"])
{
Pen penWide = new Pen(Color.Black, 45);
Pen penNarrow = new Pen(Color.Black, 2);
Point[] points1 =
{
new Point(0 , 250),
new Point(1200, 250)
};
Point[] points2 =
{
new Point (0 , 280),
new Point (1200, 280)
};
graphics.DrawLines(penWide, points1);
graphics.DrawLines(penNarrow, points2);
}
}
//Convert to TIF - requires BitMiracle.LibTiff.Classic
byte[] tiffBytes = GetTiffImageBytes(b, false);
//File.WriteAllBytes("checkfront.tif", tiffBytes);
//Encoding enc = Encoding.GetEncoding(1252);
//string result = enc.GetString(tiffBytes);
//File.Write("check2.tif", result);
return tiffBytes;
}
第二位代码中的using
包装器是新的 - 我认为它可能有所帮助,但它根本没有改变结果。
答案 0 :(得分:0)
最后,事实证明,非托管内存只是一个坏主意。其他进程需要内存,指针变得无效。
我最终使用的是PrivateFontCollection
。我仍然使用该集合中的字典只是因为它使访问更容易,并使我的许多代码以类似的方式工作。我开始使用的代码示例在处理大型数据集时太不稳定了。
我在这里修改了解决方案:http://www.emoticode.net/c-sharp/load-custom-ttf-font-file-and-use-it-on-any-winform-controls.html