首先用到的是GhostScript,網絡上有一些C#的使用方法,以下面的連接:html
http://www.codeproject.com/Articles/317700/Convert-a-PDF-into-a-series-of-images-using-Csharp算法
http://www.codeproject.com/Articles/32274/How-To-Convert-PDF-to-Image-Using-Ghostscript-API網絡
http://blog.csdn.net/ljsspace/article/details/6530046less
參考以上的方法,能夠在VC++中使用GhostScript的gsdll32.dll(在ghostscript的安裝路徑下能夠找到)把PDF轉爲圖片,但實際使用中會遇到一些問題,某些PDF轉爲圖片後長寬比例出現錯誤,頂部和底部會出現額外的白邊,用GhostScript去顯示這些PDF,顯示效果也同樣會出現一樣的問題。改用imageMagic去打開PDF,顯示效果同樣,頂部和底部也會出現額外的白邊。我猜想兩個軟件使用了相同的算法,或者使用了同一個庫。ide
後來我改用MuPDF,PDF轉圖片的效果很是好,並且速度比GhostScript更快。函數
一樣,在codeproject上有C#的使用方法:http://www.codeproject.com/Articles/498317/Rendering-PDF-Documents-with-Mupdf-and-P-Invoke-ingoogle
英文很差的朋友,能夠看這裏,有人把文章翻譯並提出了本身的看法:http://www.cnblogs.com/pdfpatcher/archive/2012/11/25/2785154.htmlspa
因爲我是使用C++,對於c開源庫的MuPDF來講,使用起來更直接方便。接下來重點介紹一下MuPDF轉圖片的方法。.net
得到MuPDF開源庫,若是去官方下載MuPDF,編譯後是一些exe及靜態連接庫,地址在這裏:http://code.google.com/p/mupdf/downloads/list線程
很幸運,咱們仍是能方便能找到動態連接庫,有人已經把MuPDF集成到另一個開源的sumatrapdf中,在下面的地址下載,編譯後,在obj-dbg文件夾下能夠找到libmupdf.dll、libmupdf.lib、fitz.h。下載地址:http://code.google.com/p/sumatrapdf/downloads/list
爲了方便你們下載DLL,我貼出CSDN下載地址,不須要積分可下載:http://download.csdn.net/detail/arthurfangmc/4948658
具體怎麼要用哪些函數,及函數的介紹,我就再也不重複介紹,上面2篇文章都作了介紹,我直接貼出幾個重要的代碼。
個人代碼直接從MuPDF源代碼中修改而來,寫了一個簡單的類,變量名基本上沒改,成員變量沒有改爲相似「myValue」或「m_value」,你們隨便看看吧。
MuPDFConvert.h:
#ifndef MY_MUPDF_CONVERT_PDF_PNG #define MY_MUPDF_CONVERT_PDF_PNG extern "C" { #include "mupdf/fitz.h" #include "mupdf/fitz-internal.h" } class CMuPDFConvert { public: CMuPDFConvert(void); ~CMuPDFConvert(void); bool Pdf2Png(const wchar_t* pdfFileName/*,const char* imageOutputPath*/,const char* imageName, int &pageNum); private: void drawpage(fz_context *ctx, fz_document *doc, int pagenum); private: static const fz_matrix fz_identity; static fz_colorspace k_device_rgb; fz_colorspace *fz_device_rgb; fz_document *m_doc; fz_stream *m_pStream; fz_context *m_ctx; int uselist; int alphabits; char output[1024]; float resolution; float rotation; int res_specified; int width; int height; int fit; fz_colorspace *colorspace; int savealpha; int invert; float gamma_value; char filename[1024]; }; #endif
MuPDFConvert.cpp:
#include "StdAfx.h" #include "MuPDFConvert.h" void fz_free_colorspace_imp(fz_context *ctx, fz_storable *cs_) { fz_colorspace *cs = (fz_colorspace *)cs_; if (cs->free_data && cs->data) cs->free_data(ctx, cs); fz_free(ctx, cs); } static void rgb_to_rgb(fz_context *ctx, fz_colorspace *cs, float *rgb, float *xyz) { xyz[0] = rgb[0]; xyz[1] = rgb[1]; xyz[2] = rgb[2]; } const fz_matrix CMuPDFConvert::fz_identity = { 1, 0, 0, 1, 0, 0 }; fz_colorspace CMuPDFConvert::k_device_rgb = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb }; CMuPDFConvert::CMuPDFConvert(void) { fz_device_rgb = &k_device_rgb; uselist = 1; alphabits = 8; //output = NULL; resolution = 72; rotation = 0; res_specified = 0; width = 0; height = 0; fit = 0; colorspace = NULL; savealpha = 0; invert = 0; gamma_value = 1; m_doc = NULL; m_ctx = NULL; } CMuPDFConvert::~CMuPDFConvert(void) { if (m_pStream) { fz_close(m_pStream); m_pStream = NULL; } if (m_doc) { fz_close_document(m_doc); m_doc = NULL; } if (m_ctx) { fz_free_context(m_ctx); m_ctx = NULL; } } bool CMuPDFConvert::Pdf2Png(const wchar_t* wcharPdfFile/*,const char* imageOutputPath*/,const char* imageName, int &pageNum) { char tempPath[1024]; //strcpy_s(tempPath, imageOutputPath); //strcat_s(tempPath, imageName); strcpy_s(tempPath, imageName); strcat_s(tempPath, "%d.png"); strcpy_s(output, (strlen(tempPath)+1)*sizeof(char), tempPath); m_ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT); if (!m_ctx) { #if _DEBUG fprintf(stderr, "mupdf cannot initialise context\n"); #endif return false; } fz_try(m_ctx) { fz_set_aa_level(m_ctx, alphabits); colorspace = fz_device_rgb; m_pStream = fz_open_file_w(m_ctx, wcharPdfFile); if (m_pStream) { m_doc = fz_open_document_with_stream(m_ctx, ".pdf", m_pStream); } if (!m_doc) { #if _DEBUG fprintf(stderr, "mupdf cannot open pdf\n"); #endif return false; } if (fz_needs_password(m_doc)) { #if _DEBUG fprintf(stderr, "mupdf cannot authenticate password\n"); fz_throw(m_ctx, "mupdf cannot authenticate password: %s", filename); #endif return false; } int pn = fz_count_pages(m_doc); pageNum = pn; for (int i=0; i<pn; ++i) { fz_page *page = fz_load_page(m_doc, i); fz_rect bound = fz_bound_page(m_doc, page); //PDF-->PNG drawpage(m_ctx, m_doc, i+1); fz_free_page(m_doc, page); page = NULL; } } fz_catch(m_ctx) { return false; } if (m_pStream) { fz_close(m_pStream); m_pStream = NULL; } if (m_doc) { fz_close_document(m_doc); m_doc = NULL; } if (m_ctx) { fz_free_context(m_ctx); m_ctx = NULL; } return true; } void CMuPDFConvert::drawpage(fz_context *ctx, fz_document *doc, int pagenum) { fz_page *page; fz_display_list *list = NULL; fz_device *dev = NULL; int start; fz_var(list); fz_var(dev); fz_try(ctx) { page = fz_load_page(doc, pagenum - 1); } fz_catch(ctx) { fz_throw(ctx, "cannot load page %d in file '%s'", pagenum, filename); } if (uselist) { fz_try(ctx) { list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, list); fz_run_page(doc, page, dev, fz_identity, NULL); } fz_catch(ctx) { fz_free_device(dev); fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_throw(ctx, "cannot draw page %d in file '%s'", pagenum, filename); } fz_free_device(dev); dev = NULL; } if (output) { float zoom; fz_matrix ctm; fz_rect bounds, bounds2; fz_bbox bbox; fz_pixmap *pix = NULL; int w, h; fz_var(pix); bounds = fz_bound_page(doc, page); zoom = resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_concat(ctm, fz_rotate(rotation)); bounds2 = fz_transform_rect(ctm, bounds); bbox = fz_round_rect(bounds2); /* Make local copies of our width/height */ w = width; h = height; /* If a resolution is specified, check to see whether w/h are * exceeded; if not, unset them. */ if (res_specified) { int t; t = bbox.x1 - bbox.x0; if (w && t <= w) w = 0; t = bbox.y1 - bbox.y0; if (h && t <= h) h = 0; } /* Now w or h will be 0 unless then need to be enforced. */ if (w || h) { float scalex = w/(bounds2.x1-bounds2.x0); float scaley = h/(bounds2.y1-bounds2.y0); if (fit) { if (w == 0) scalex = 1.0f; if (h == 0) scaley = 1.0f; } else { if (w == 0) scalex = scaley; if (h == 0) scaley = scalex; } if (!fit) { if (scalex > scaley) scalex = scaley; else scaley = scalex; } ctm = fz_concat(ctm, fz_scale(scalex, scaley)); bounds2 = fz_transform_rect(ctm, bounds); } bbox = fz_round_rect(bounds2); /* TODO: banded rendering and multi-page ppm */ fz_try(ctx) { pix = fz_new_pixmap_with_bbox(ctx, colorspace, bbox); if (savealpha) fz_clear_pixmap(ctx, pix); else fz_clear_pixmap_with_value(ctx, pix, 255); dev = fz_new_draw_device(ctx, pix); if (list) fz_run_display_list(list, dev, ctm, bbox, NULL); else fz_run_page(doc, page, dev, ctm, NULL); fz_free_device(dev); dev = NULL; if (invert) fz_invert_pixmap(ctx, pix); if (gamma_value != 1) fz_gamma_pixmap(ctx, pix, gamma_value); if (savealpha) fz_unmultiply_pixmap(ctx, pix); if (output) { char buf[512]; sprintf(buf, output, pagenum); if (strstr(output, ".png")) { fz_write_png(ctx, pix, buf, savealpha); } } fz_drop_pixmap(ctx, pix); } fz_catch(ctx) { fz_free_device(dev); fz_drop_pixmap(ctx, pix); fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_rethrow(ctx); } } if (list) fz_free_display_list(ctx, list); fz_free_page(doc, page); fz_flush_warnings(ctx); }
使用方法:
#include "stdafx.h" #include "MuPDFConvert.h" int _tmain(int argc, _TCHAR* argv[]) { CMuPDFConvert pdfConvert; int nNum = 0; pdfConvert.Pdf2Png(L"test.pdf", "test", nNum); return 0; }
這裏生成的圖片是PNG格式,若是你須要其餘格式的圖片,能夠再選擇其它庫,若是編譯器版本支持CImage,可使用CImage來轉其它圖片格式,
另外,在MFC中能夠直接使用CImage來顯示PNG及其它格式圖片,使用方法很是簡單。
定義一個變量
CImage m_img;
導入圖片
if(!m_img.IsNull()) { m_img.Destroy(); } m_img.Load(strImagePath);
在OnPaint()函數中:
if(!m_img.IsNull()) { CPaintDC dc(GetDlgItem(IDC_CHILD_PIC)); dc.SetStretchBltMode(HALFTONE); m_img.Draw(dc.m_hDC, 0, 0, m_nFitWidth, m_nFitHeight, 0, 0, m_nRegionWidth, m_nRegionHeight); //透明顯示PNG圖片 //m_img.TransparentBlt(dc.m_hDC, 0, 0, m_nFitWidth, m_nFitHeight, // 0, 0, m_nRegionWidth, m_nRegionHeight, RGB(255,255,255)); }
使用過程當中,PDF轉圖片仍是須要花費必定的時間,若是你須要實時顯示圖片,而PDF頁數又很是多,最好另開一個線程來作PDF轉圖片的工做。ghostScript和MuPDF我都在項目中使用過,PDF頁數不少或者圖片分辨率很大的時候,MuPDF的速度優點仍是十分明顯的。
附PDF轉PNG圖片下載代碼,辛苦勞動,你們給點分吧,若是你沒分,又須要下載,給我消息,我發給你。
http://download.csdn.net/detail/arthurfangmc/4948833