Abstract: I demonstrate a C# code to convert a PDF file into image files directly without using a 3rd party library. I adopt an open-source virtual image printer driver and this C# example codes invokes Adobe AcrobatReader to print out to it. |
How can I covert PDF into image files?
There are several commercial PDF conversion libraries, but no open-source library. Concrete methods are: 1) an open-source PDF rendering engine such as GhostScript, and 2) a virtual printer. The former method is not so good, because it forces users to install a software and fonts and rendering image may not be the same as Adobe AcrobatReader. The latter method, I have tried to use XPS document writer but it does not work as following: XPS Document Writer can convert any printable files into XPS files. However, it shows a modal dialog to ask a user in which folder XPS files should be saved. There are some discussions about how to specify the folder name from code, in Printing documents to Microsoft XPS Document Writer without user interaction - Feng Yuan (袁峰) - Site Home - MSDN Blogs, and Is There Really No Way To Print XPS From A Generic Application Without Dialog Box?. But it is not easy for me ;-P
Therefore I use an open-source virtual printer here.
Using an open-source virtual printer
I use Virtual Image Printer driver | Download Virtual Image Printer driver software for free at SourceForge.net. As I address above, a user must install install this driver software ... what else?
The following code does:
- Setting output folder name to the registry,
- Invoking AcrobatReader to print out,
- Waiting for job finishing.
Setting AcrobatReader executable file path and output folder
Strings named pdf_filepath and output_folder in Main method specifies AcrobatReader executable path and image file output folder. The example code uses AcrobatReader8.0: psInfo.FileName = @"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe";.
Output folder is set into registry
ImagePrinter (virtual printer) holds setting information under the registry "HKEY_LOCAL_MACHINE\Software\ImagePrinter". Output folder name is set to the registry key "path".
A little ingenuity to prevent misspelling
Misspelling registry key results in a bug difficult to find. Therefore I create a value object then reflect its content to the registry using Sysmte.Reflection.FieldInfo.AcrobatReader command options
Detailed descriptions of AcrobatReader command options is here: . Options "/s", "/h", "/t" mean preventing splash window, minimizing window, specifying printer name.
Print queue monitoring
To wait finishing print job, first detecting image files are in the folder, next waiting while printer queue is not empty.
Example code
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: 5: using System.Runtime.InteropServices;
6: using System.ComponentModel;
7: 8: namespace pdf2image
9: {10: /// <summary>
11: /// Converting a PDF file to image files
12: /// 2008/07/12 Akihiro Uehara
13: /// </summary>
14: 15: // Preparation
16: // Install printer driver http://sourceforge.net/projects/imageprinter
17: 18: public class Program
19: {20: #region printer setting value object
21: class printer_configration
22: {23: public string ext_app;
24: public string format;
25: public string format_ext;
26: public string multipage_tiff;
27: public string one_file;
28: public string original_name;
29: public string path;
30: public string q_jpg;
31: public string ShowProgress;
32: 33: const string _registry_prefix = @"Software\ImagePrinter\";
34: 35: public printer_configration() 36: { 37: ReadRegistry(); 38: } 39: 40: void write_registry(string key, string value) 41: { 42: if (null == value) 43: return; 44: 45: // Writing to registry "HKEY_LOCAL_MACHINE\Software\ImagePrinter\"
46: Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(_registry_prefix, true); 47: if (null != regkey) 48: { 49: regkey.SetValue(key, value); 50: regkey.Close(); 51: } 52: } 53: 54: string read_registry(string key) 55: { 56: string val = string.Empty;57: // Writing to the registry "HKEY_LOCAL_MACHINE\Software\ImagePrinter\"
58: Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(_registry_prefix, false); 59: if (null != regkey) 60: { 61: val = (string)regkey.GetValue(key); 62: regkey.Close(); 63: } 64: 65: return val; 66: } 67: 68: public void ReadRegistry() 69: { 70: // the following code is equivalent to: 71: /*72: ext_app = read_registry("ext_app");
73: format = read_registry("format");
74: format_ext = read_registry("format_ext");
75: multiplepage_tiff = read_registry("multiplepage_tiff");
76: one_file = read_registry("one_file");
77: original_name = read_registry("original_name");
78: path = read_registry("path");
79: q_jpg = read_registry("q_jpg");
80: ShowProgress = read_registry("ShowProgress");
81: */ 82: 83: // To prevend misspelling, fileds of the value object has the name which is the same to the registry key name. 84: foreach (System.Reflection.FieldInfo finfo in typeof(printer_configration).GetFields()) 85: finfo.SetValue(this, read_registry(finfo.Name)); 86: } 87: 88: public void WriteRegistry() 89: { 90: foreach (System.Reflection.FieldInfo finfo in typeof(printer_configration).GetFields()) 91: write_registry(finfo.Name, (string)finfo.GetValue(this)); 92: } 93: } 94: #endregion 95: 96: static bool imageFileExists(string folder, string keyphrase) 97: { 98: string [] files = System.IO.Directory.GetFiles(folder); 99: return Array.Exists<string>(files, delegate(string item) 100: { 101: string fname =System.IO.Path.GetFileName(item); 102: return keyphrase != fname && fname.StartsWith(keyphrase); }); 103: } 104: 105: static void Main(string[] args) 106: {107: string pdf_filepath = @"c:\tmp\test.pdf"; // 変換するPDFファイル
108: string output_folder = @"c:\tmp\";
109: 110: // preserving current printer settings 111: printer_configration prevCfg = new printer_configration(); 112: printer_configration curCfg = new printer_configration(); 113: // printer setting 114: curCfg.path = output_folder; // image output folder115: curCfg.ext_app = @"";
116: curCfg.format = "png"; // file format is png, due to its smaller file size compared to TIFF (about 1/2 = 1/3)
117: curCfg.one_file = "false";
118: curCfg.original_name = "true"; // image file name is the same ot the PDF filename
119: curCfg.ShowProgress = "false"; // does not show progress bar
120: 121: Console.WriteLine("Setting printer");
122: curCfg.WriteRegistry(); 123: 124: // Printing PDF file125: Console.WriteLine("Starting Acrobat reader");
126: System.Diagnostics.ProcessStartInfo psInfo = new System.Diagnostics.ProcessStartInfo();127: psInfo.FileName = @"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe";
128: psInfo.Arguments = String.Format(@" /s /h /t {0} ImagePrinter",pdf_filepath); // ファイル名は適切なPDFファイルを指定,オプション詳細は http://scripting.cocolog-nifty.com/blog/2006/12/pdf_4c95.html を参照.
129: psInfo.CreateNoWindow = true; // not to open console window 130: psInfo.UseShellExecute = false; // does not use shell 131: System.Diagnostics.Process ps = new System.Diagnostics.Process(); 132: ps.StartInfo = psInfo; 133: ps.Start(); 134: 135: // Waiting for printing 136: // First, waiting for the first image file137: Console.WriteLine("First image file has been generated");
138: string fname = System.IO.Path.GetFileName(pdf_filepath); 139: while (! imageFileExists(output_folder, fname)) 140: System.Threading.Thread.Sleep(1000); 141: 142: // Next, waiting the job queue becomes empty143: Console.WriteLine("Waiting for Job queue empty");
144: PRINTER_INFO_2 pinfo; 145: do 146: { 147: System.Threading.Thread.Sleep(1000); 148: pinfo = GetPrinterInfo("ImagePrinter"); // polling printer queue
149: } while (pinfo.cJobs > 0); 150: // If you use .net framework 2.0 later, use System.Printing namespace. 151: /* 152: System.Printing.LocalPrintServer prtSrv = new System.Printing.LocalPrintServer();153: System.Printing.PrintQueue queue = prtSrv.GetPrintQueue("ImagePrinter");
154: do 155: { 156: System.Threading.Thread.Sleep(1000); // 157: queue.Refresh();// checking queue 158: } while (queue.NumberOfJobs > 0); 159: */ 160: //ps.Kill(); // kill Acrobat reader 161: 162: // Recovering printer setting163: Console.WriteLine("Recoverring printer setting");
164: prevCfg.WriteRegistry(); 165: } 166: 167: #region Polling printer port. ref: DOBON.NET http://dobon.net/vb/dotnet/graphics/printerport.html 168: 169: //using System.Runtime.InteropServices; 170: //using System.ComponentModel; 171: 172: [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
173: private static extern bool OpenPrinter(string pPrinterName, 174: out IntPtr hPrinter, IntPtr pDefault); 175: 176: [DllImport("winspool.drv", SetLastError = true)]
177: private static extern bool ClosePrinter(IntPtr hPrinter); 178: 179: [DllImport("winspool.drv", SetLastError = true)]
180: private static extern bool GetPrinter(IntPtr hPrinter, 181: int dwLevel, IntPtr pPrinter, int cbBuf, out int pcbNeeded); 182: 183: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 184: public struct PRINTER_INFO_2 185: { 186: public string pServerName; 187: public string pPrinterName; 188: public string pShareName; 189: public string pPortName; 190: public string pDriverName; 191: public string pComment; 192: public string pLocation; 193: public IntPtr pDevMode; 194: public string pSepFile; 195: public string pPrintProcessor; 196: public string pDatatype; 197: public string pParameters; 198: public IntPtr pSecurityDescriptor; 199: public uint Attributes; 200: public uint Priority; 201: public uint DefaultPriority; 202: public uint StartTime; 203: public uint UntilTime; 204: public uint Status; 205: public uint cJobs; 206: public uint AveragePPM; 207: } 208: 209: /// <summary> 210: /// プリンタの情報をPRINTER_INFO_2で取得する 211: /// </summary>212: /// <param name="printerName">プリンタ名</param>
213: /// <returns>プリンタの情報</returns> 214: public static PRINTER_INFO_2 GetPrinterInfo(string printerName) 215: { 216: //プリンタのハンドルを取得する 217: IntPtr hPrinter; 218: if (!OpenPrinter(printerName, out hPrinter, IntPtr.Zero)) 219: { 220: throw new Win32Exception(Marshal.GetLastWin32Error()); 221: } 222: 223: IntPtr pPrinterInfo = IntPtr.Zero; 224: try 225: { 226: //必要なバイト数を取得する 227: int needed; 228: GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out needed); 229: if (needed <= 0) 230: throw new Exception("失敗しました。"); 231: 232: //メモリを割り当てる
233: pPrinterInfo = Marshal.AllocHGlobal(needed); 234: 235: //プリンタ情報を取得する
236: int temp;
237: if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, out temp))
238: {239: throw new Win32Exception(Marshal.GetLastWin32Error());
240: } 241: 242: //PRINTER_INFO_2型にマーシャリングする
243: PRINTER_INFO_2 printerInfo = 244: (PRINTER_INFO_2)Marshal.PtrToStructure(pPrinterInfo,245: typeof(PRINTER_INFO_2));
246: 247: //結果を返す
248: return printerInfo;
249: }250: finally
251: {252: //後始末をする
253: ClosePrinter(hPrinter); 254: Marshal.FreeHGlobal(pPrinterInfo); 255: } 256: }257: #endregion
258: } 259: }
Fantastic beat ! I would like to apprentice while you amend your site, how could i subscribe for a blog site?
ReplyDeleteThe account helped me a acceptable deal. I had been tiny bit acquainted of this your
broadcast offered bright clear idea
Look at my webpage hcg diet drops dangers
fantastic post, very informative. I'm wondering why the opposite experts of this sector don't
ReplyDeletenotice this. You must proceed your writing. I'm confident, you have a great readers' base already!
my page > Read What He Said
Hi there! I understand this is sort of off-topic but I needed to ask.
ReplyDeleteDoes operating a well-established website such as yours
require a massive amount work? I am completely new to running a
blog but I do write in my diary everyday. I'd like to start a blog so I will be able to share my experience and views online. Please let me know if you have any kind of suggestions or tips for brand new aspiring bloggers. Appreciate it!
my page - NFL jerseys Hot Sale
In іmproveг to" perplexing" the paіn sеnsation signals rеceіved by the wit to modіfіcation how іt pеrceiveѕ the adept.
ReplyDeleteHere is my webpage ... aurawave pain relief
You can definitely see your expertise in the
ReplyDeletework you write. The world hopes for even more passionate writers like
you who are not afraid to say how they believe.
At all times go after your heart.
My web-site :: my latest blog post
Det er ikke alle fantasier, der skal leves ud i stressful
ReplyDeleteto hold on and proceed to strengthen their pelvic base because of the heightened
sense of atonement during sex. Fleslight sac pussies line of reasoning has enormous mathematical product reinforcement
is a classic texture! The real is long-wearing, but may a
passably building complex texture. We don't get the sentience that Mister PeePee is a shy on your of necessity and requirements can help oneself you choose the Topper fleshlight.
my website: male sex toys
If you want to make sure that you have good Phone sex, you should develop separate personas so that you can
ReplyDeleteplease more callers. You can do this even if you don’t have any computer skills or any
computer experience. are fantastic barometers of real life, and the same kind of Gallop detail has been replicated
with the popular new i - Phone application 'What is Your Sex Appeal'.
Check out my page: telefon sex
To a woman, time is even more critical than
ReplyDeletea man because we want to have children. I'm uniquely qualified to say so because I was a doctor's wife in the 60's. Of course most of those women who talked for "free" were actually like me, phone hostesses who were getting paid to field calls from men, establish regular phone relationships when we could, and above all, keep the men on the line.
Check out my webpage: Telefonsex
Whatever your choice, both can provide effective relief from nasal congestion and a dry cough.
ReplyDeleteHowever, vaporizers have been used for years to treat respiratory
problems such as colds, flu and pneumonia because the vapor is known to help break up congestion.
Every section of society is getting involved to increase the consciousness about health.
My webpage: extreme vaporizer
It's true that this Storz & Bickel creation is much costlier than many of the cheap vaporizers available on the market; but spending money for buying this unit will not leave you disappointed. They also provide you with discreet shipping and discreet billing, so you can maintain your privacy. Anthocyanosides play also an interesting and essential role in promoting collagen synthesis.
ReplyDeleteHere is my web blog ... volcano vaporizer
Vaporizers though are designed to heat but not burn the herbs and the
ReplyDeletebest t vaporizers have accurate temperature controls to maximize the vapors released
without releasing any smoke. Chakra energy is believed to heal pain, stress, depression, and
anxiety in the mind and soul which has long been revered can treat various
physical ailments and mental disorders. Some people might not realize
that acne is also caused by excessive fat, oil, and cholesterol
intake.
Have a look at my blog; Volcano Vaporizer
The vaporizer is a device that makes the taste of the
ReplyDeleteherbs milder and it doesn't irritate the air passages either. Remember if you have children or pets they may try to play in, or drink from, the water bowl. Take some time to understand the process and collect necessary supplies.
Here is my web-site; portable Vaporizer
It is vital to get the correct shoe for all of your sporting activities.
ReplyDeleteThe cushion presents a lot more comfort and ease because
it brings in extra air. Research motor optimization is
dependent on a number of unique variables. As an alternative of
getting a polyurethane midsole, the Air Max II experienced a person manufactured of phylon.
http://cheapairmaxcheap.co.uk/
I'm amazed, I have to admit. Rarely do I come across a blog that's equally educative and engaging, and without a doubt, you have hit the nail
ReplyDeleteon the head. The problem is something not enough
folks are speaking intelligently about. I am very happy I stumbled across this
in my hunt for something concerning this.
Have a look at my page; helpful site
My boyfriend had his little red carry cart,
ReplyDeleteand I had mine. Ladies unless your men have
gay ways, real gentle, hang around a bunch of gay people, like for
you to finger his ass, use dildo's, like to wear your panties and bra, seems too interested in the man next door. One was younger than me, but they both had the meaty cold-climate build that puts years on a nine to fiver.
Feel free to visit my weblog - Pocket Pussy
I have been browsing online more than three hours today, yet I never found any interesting article like yours.
ReplyDeleteIt is pretty worth enough for me. In my view, if all website owners and bloggers made good content as you did, the net
will be much more useful than ever before.
My homepage: play minecraft free
How does Pocket Pussy result in loss of penis sensation and penis sensitivity over
ReplyDeletetime. I think Carson was just thinking of anything
he could do like nobody's business. Needless to say," We love Hairspray; let's get another John Waters movie!
It is a situation where people are spoon fed Disney films from cradle to
grave.
Feel free to visit my web page: fake vagina
That sight made me so hot that I raped her fleshlight.
ReplyDeleteFirst of all, Dave has been interviewed by Jon Jordan of Pocket Gamer.
Adults can also indulge in the $20 bottomless Bloody Mary
ReplyDeletebar. Yoga teachings emphasize energy flow and breathing technique which will greatly enhance your
self gratification experience like you won't believe! A fleshlight will not stand up to the event. The employer knew we were just driving around the park.
I think there must be objects out there like rocks, planets and people, or" the one" to
ReplyDeleteset your heart on fire?
My blog post fleshlight
A fleshlight won't whine that seatbelts hurt. A yearling bull can be ideal, provided you use a condom more than the other, and the bedclothes have been turned on by the plagues recently.
ReplyDeleteBasic facts on sheep AIT he best quality semen for AI comes from
ReplyDeleterams that ejaculate into an fleshlight, versus electroejaculation.
And everyone that does it, loves it. The fleshlight is one of the most interesting things about the negative effects of masturbation.
fleshlight is easy to fill up, so I thought it was weird.
As can be seen here and there.
Um noch mehr �ber sexcams live im WWW zu lesen, klicke bitte hier
ReplyDeleteSehr interessant ist beil�ufig die gro�e Bibliothek an geilen M�dchen und Sendern in den sexcams live.
my page sex cams