c# - Protected Memory Exception on Images when Fonts are Called -
edit: so, see what's happening, don't understand why. dictionary<string, object>
storing fonts fine, there's particular function runs, , when runs, dictionary gets partly wiped out.
the code running between these images is:
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 " + + "\n\n" + ex.tostring(), "exception"); return 0; } while ((line = file.readline()) != null) { if (line.substring(0, 2) == "10") { count++; } } file.close(); return count; }
---end edit---
i'm getting this tracedump when use many custom fonts. i'm using same solution listed here, , have tried voted fix (removing dispose , 1 marshalling call) leads gdi+ error. actually, have modified version of code, can call , different fonts:
#region font setup //setup code 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 font 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 getfont()", "error"); break; } if (null != stmfont) { // // gdi+ wants pointer memory, gdi wants memory. // make them both happy. // // first read font buffer byte[] rgbyt = new byte[stmfont.length]; stmfont.read(rgbyt, 0, rgbyt.length); // unmanaged font (windows 2000 , later) // reason works gdi+ create font object // controls richtextbox , call make sure gdi // recognizes font name, later. uint cfonts; addfontmemresourceex(rgbyt, rgbyt.length, intptr.zero, out cfonts); // 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 1 of font constructors takes // fontfamily object, huh? :-) fnt = new font(m_pfc.families[0], size); } m_pfc.dispose(); return fnt; } //end setup fonts #endregion
the gdi+ error inevitably if remove dispose() , freecotaskmem() is this.
neither issue occurs immediately. appears can run call on average 20-25 times before either exception thrown.
any thoughts appreciated. when using single font, never had error (could generate 1000+ every time). appears, anecdotally @ least, if i'm ever calling 2 fonts, it's not problem. when "hand" tossed mix, seems issue.
the method calls is:
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 front image frontimage image source embedded resource system.io.stream file; random rnd = new random(datetime.now.millisecond); int = 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 //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 upper-left point of // original new point(1170, 0), // destination 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 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; }
the using
wrapper in second bit of code new - thought might help, didn't change outcome @ all.
in end, turns out unmanaged memory bad idea. other processes needing memory, , pointer becoming invalid.
i ended using privatefontcollection
instead. still used dictionary collection because made access easier , kept lot of code working in similar fashion. code sample started volatile when working large data sets.
i modified solution here: http://www.emoticode.net/c-sharp/load-custom-ttf-font-file-and-use-it-on-any-winform-controls.html
Comments
Post a Comment