java生成圖片


前言:

  后台生成圖片,我能想到的有可能有以下幾種方式:

  1,使用圖片相關api畫圖;

  2,使用pdf畫圖,然后pdf -> 圖片;

  3,使用html畫圖(freemarker),然后html -> 圖片;

  4,使用html畫圖(freemarker),然后html -> pdf -> 圖片;

 

實現:

  本文章采用第4種方式畫圖

  1,讀取企業證書圖片的ftl模板

import freemarker.template.Configuration;
import freemarker.cache.TemplateLoader;
import org.springframework.ui.freemarker.SpringTemplateLoader;
import org.springframework.core.io.DefaultResourceLoader;
import freemarker.template.Template;
Configuration configuration = new Configuration();
// war包下,WEB-INFO/classes/
TemplateLoader templateLoader = new SpringTemplateLoader(new DefaultResourceLoader(), "注釋目錄下的某個文件夾,比如名叫:template");
configuration.setTemplateLoader(templateLoader);
configuration.setDefaultEncoding("utf-8");
// 讀取war包下/WEB-INFO/classes/template/xxxtemplate.ftl,生成模板對象
Template template = configuration.getTemplate("xxxtemplate.ftl");

  2,ftl模板 -> html文件

File htmlFile = new File("html文件.html");
FileWriter htmlWriter = new FileWriter(htmlFile);
template.process(需要渲染進ftl模板的數據(Map類型), htmlWriter);
htmlWriter.flush();
templateLoader.closeTemplateSource(template);

  3,html -> pdf(不帶背景圖片)

import org.xhtmlrenderer.pdf.ITextRenderer;
import com.suning.secis.service.monitor.enterprisereport.impl.Base64ImgReplacedElementFactory;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import com.itextpdf.text.pdf.BaseFont;
File pdfFile = new File("pdf不帶背景圖片.pdf");
FileOutputStream os = new FileOutputStream(pdfFile);
ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);
String url = htmlFile.toURI().toURL().toString();
renderer.setDocument(url);
ITextFontResolver fontResolver = renderer.getFontResolver();
ClassLoader classLoaderToUse = ClassUtils.getDefaultClassLoader();
// war包下/WEB-INFO/classes/
Enumeration<URL> fontUrls = classLoaderToUse.getResources("font/simsun.ttf");
URL fontUrl;
if (fontUrls.hasMoreElements()) {
fontUrl = fontUrls.nextElement();
} else {
throw new 業務Exception(業務code, "獲取pdf字體文件失敗!");
}
// 字體文件如果運維人員安裝好了,指定那個目錄;如果放在項目的classes目錄里,則打包時指定utf-8編碼,可能會亂碼;也可以從HttpServletRequest里面獲得ip+port,然后網絡請求這個文件;
fontResolver.addFont(fontUrl對應的路徑, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
os.flush();

  4,pdf(不帶背景圖片) -> pdf(帶背景圖片)

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfContentByte;
File pdfWithBackgroundFile = new File("pdf帶背景圖片.pdf");
PdfReader pdfReader = new PdfReader(pdfFile.getCanonicalPath());
FileOutputStream osWithBackground = new FileOutputStream(pdfWithBackgroundFile);
PdfStamper pdfStamper = new PdfStamper(pdfReader, osWithBackground);
Enumeration<URL> backgroundPngUrls = classLoaderToUse.getResources("背景圖片目錄/background.png");
URL backgroundPngUrl;
if (backgroundPngUrls.hasMoreElements()) {
backgroundPngUrl = backgroundPngUrls.nextElement();
} else {
throw new 業務Exception(業務code, "獲取背景圖片失敗!");
}
com.itextpdf.text.Image tImgCover = com.itextpdf.text.Image.getInstance(backgroundPngUrl);
tImgCover.setAbsolutePosition(-33, -42);
tImgCover.scaleAbsolute(660, 927);
// 兩個pdf圖層,哪個在上哪個在下,可以通過一下方法:getUnderContent(頁數)、getOverContent(頁數)
PdfContentByte content = pdfStamper.getUnderContent(1);
content.addImage(tImgCover);
content.stroke();
osWithBackground.flush();
pdfStamper.close();
pdfReader.close();

  5,pdf(帶背景圖片) -> png

import org.icepdf.core.pobjects.Document;
import java.awt.image.BufferedImage;
import org.icepdf.core.util.GraphicsRenderingHints;
File imageFile = new File("目標圖片.png");
Document document = new Document();
document.setFile(pdfWithBackgroundFile.getCanonicalPath());
BufferedImage image = (BufferedImage) document.getPageImage(0, GraphicsRenderingHints.SCREEN, 1, 0f, 2.5f);
ImageIO.write(image, "png", imageFile);
image.flush();

  6,finally刪除中間文件、關閉流

 

總結:

  1,在ftl文件里面,如下設置,能保證windows系統和linux系統的大小一致(按照你設置的大小),方便本地windows調試;

<style>
@page {
size: 210mm 297mm;
}
</style>

  2,在ftl的style里面也可以使用變量,如下;按需調整字體大小等;

.class名稱 {
font-size: ${變量名?default(27)};
}

  3,itexpdf只認識html較少的標簽和樣式;

  如文字居中,使用:text-align: center;

  font-family: SimSun;需要和字體文件對應;

  如粗體、浮動效果都不行;浮動效果需要使用table標簽:

 

  如要實現這個布局,不能使用浮動,使用table;

 

 

 
        
 
        
 
        

 

 

 
        
 
        
 
        
 
        
 
        
 
        






  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM