生成一個簽章(用java.awt畫一個簽章) 並添加到pdf 公章處

来源:http://www.cnblogs.com/liudongdong666666/archive/2017/11/09/7811523.html
-Advertisement-
Play Games

生成一個簽章(用java.awt畫一個簽章) 並添加到pdf 公章處package com.bjpowernode.p2p.admin.util;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import ...


生成一個簽章(用java.awt畫一個簽章) 並添加到pdf 公章處
package com.bjpowernode.p2p.admin.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;

import com.bjpowernode.p2p.admin.config.SystemConfig;

/**
 * 勾畫圓形公司章
 *
 * @author ldd
 */
public class DrawSeal {
    //生成文件路徑
    public static final String FILE_PATH = SystemConfig.getConfigProperty("seal_img_path");
    
    private final static int WIDTH = 160;
    
    private final static int HEIGHT = 160;
    
    /**
     * 畫圓形章
     * @param name1 章的名字
     * @param name2 公司的名字
     * @param numCode 公司的數字編碼
     * @param width
     * @param height
     * @return
     */
    public static String drawCircularChapter(String name1, String name2, String numCode){
        OutputStream out = null;
        InputStream in = null;
        byte[] data = null;
        //創建緩存
        BufferedImage bufImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        //獲得畫布
        Graphics2D gs = bufImg.createGraphics();
        //設置顏色
        gs.setColor(Color.WHITE);
        //填充區域
        gs.fillRect(0, 0, WIDTH, HEIGHT);
        //設置畫筆顏色
        gs.setColor(new Color(204,41,41));
        //畫五角星
        drawFiveStar(gs, WIDTH/2, HEIGHT/2, HEIGHT/6-3);
        //設置畫筆寬度
        gs.setStroke(new BasicStroke(3));
        //畫圓形邊框
        gs.drawOval(2, 2, WIDTH-4, HEIGHT-4);
        //設置字體
        gs.setFont(new Font("宋體", Font.BOLD, 21));
        //畫數據(合同專用章)
        drawCenterMessage(gs, name1, WIDTH/2+2, HEIGHT * 4 / 5);
        if (StringUtils.isNotEmpty(name2) && name2.length()>11) {
            int len = name2.length();
            int fontSize = 18;
            switch (len) {
            case 12:
                fontSize = 20;
                break;
            case 13:
                fontSize = 19;
                break;
            case 14:
                fontSize = 19;
                break;
            case 15:
                fontSize = 18;
                break;
            case 16:
                fontSize = 17;
                break;
            case 17:
                fontSize = 16;
                break;
            case 18:
                fontSize = 15;
                break;
            case 19:
                fontSize = 14;
                break;
            case 20:
                fontSize = 14;
                break;
            case 21:
                fontSize = 12;
                break;
            case 22:
                fontSize = 12;
                break;
            case 23:
                fontSize = 10;
                break;
            case 24:
                fontSize = 10;
                break;
            case 25:
                fontSize = 9;
                break;
            default :
                fontSize = 18;
                break;
            }
            //設置字體
            gs.setFont(new Font("宋體", Font.PLAIN, fontSize));
        }
        //畫上方的環形字
        drawUpperMessage(gs, name2, WIDTH/2, HEIGHT/2, WIDTH/2-10);
        //設置字體
        gs.setFont(new Font("宋體", Font.BOLD, 9));
        //畫下方的環形數字
        drawBelowNumber(gs, numCode, WIDTH/2, HEIGHT/2, HEIGHT/2);
        //釋放此圖形的上下文以及它使用的所有系統資源
        gs.dispose();
        //輸出圖片
        try {
            StringBuffer fileDir = new StringBuffer();
            fileDir.append(Calendar.getInstance().get(Calendar.YEAR)).append(File.separator).append(Calendar.getInstance().get(Calendar.MONTH)+1).append(File.separator).append(Calendar.getInstance().get(Calendar.DAY_OF_MONTH)).append(File.separator);
            File ff = new File(FILE_PATH + fileDir.toString());
            if (!ff.exists()) {
                ff.mkdirs();
            }
            String imgFile = FILE_PATH + fileDir.toString() + UUID.randomUUID() + ".bmp";
            out = new FileOutputStream(imgFile);
            ImageIO.write(bufImg, "bmp", out);
            
            bufImg.flush();
            out.flush();
            
            /*in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);*/
            
            //對位元組數組Base64編碼
            /*sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
            //返回Base64編碼過的位元組數組字元串
            String encodeStr = encoder.encode(data);
            //將圖片文件刪除
            File file = new File(imgFile);
            if (file.isFile()) {
                file.delete();
            }*/
            return imgFile;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    
    public static void drawCenterMessage(Graphics2D gs, String message, int CENTERX, int CENTERY){
        if (message != null) {
            // 根據輸入字元串得到字元數組
            String[] messages2 = message.split("", 0);
            String[] messages = new String[messages2.length];
            System.arraycopy(messages2, 0, messages, 0, messages2.length);
            // 輸入的字數
            int ilength = messages.length;
            Font f = gs.getFont();
            FontRenderContext context = gs.getFontRenderContext();
            Rectangle2D bounds = f.getStringBounds(message, context);
            // 字元寬度=字元串長度/字元數
            double char_interval = (bounds.getWidth() / ilength) - 1;
            
            int first = 0, second = 0;
            boolean odd = false;
            if (ilength % 2 == 1) {
                first = (ilength - 1) / 2;
                odd = true;
            } else {
                first = (ilength) / 2 - 1;
                second = (ilength) / 2;
                odd = false;
            }
            if (odd) {
                gs.drawString(messages[first],
                        (float)(CENTERX - char_interval / 2 - char_interval / 10),
                        (float) CENTERY);
                // 中心點的右邊
                for (int i = first + 1; i < ilength; i++) {
                    double x = CENTERX + (i - first - 0.6) * char_interval;
                    gs.drawString(messages[i],(float) x,
                            (float) CENTERY);
                }
                // 中心點的左邊
                for (int i = first - 1; i > -1; i--) {
                    double x = CENTERX - (first - i + 0.6) * char_interval;
                    gs.drawString(messages[i],(float) x,
                            (float) CENTERY);
                }
            } else {
                // 中心點的右邊
                for (int i = second; i < ilength; i++) {
                    double x = CENTERX + (i - second - 0.1) * char_interval;
                    gs.drawString(messages[i],(float) x,
                            (float) CENTERY);
                }
                // 中心點的左邊
                for (int i = first; i > -1; i--) {
                    double x = CENTERX - (first + 1 - i + 0.1) * char_interval;
                    gs.drawString(messages[i],(float) x,
                            (float) CENTERY);
                }
    
            }
        }
    }
    
    /**
     * 畫上方圓弧的漢字
     *
     * @param gs
     * @param message
     * @param CENTERX
     * @param CENTERY
     * @param r
     */
    public static void drawUpperMessage(Graphics2D gs, String message, int CENTERX, int CENTERY, int r) {
        if (message != null) {
            // 根據輸入字元串得到字元數組
            String[] messages2 = message.split("", 0);
            String[] messages = new String[messages2.length];
            System.arraycopy(messages2, 0, messages, 0, messages2.length);
            // 輸入的字數
            int ilength = messages.length;
            Font f = gs.getFont();
            FontRenderContext context = gs.getFontRenderContext();
            Rectangle2D bounds = f.getStringBounds(message, context);
            // 字元寬度=字元串長度/字元數
            double char_interval = (bounds.getWidth() / ilength) - 1;
            // 上坡度
            double ascent = -bounds.getY()-2;
            int first = 0, second = 0;
            boolean odd = false;
            if (ilength % 2 == 1) {
                first = (ilength - 1) / 2;
                odd = true;
            } else {
                first = (ilength) / 2 - 1;
                second = (ilength) / 2;
                odd = false;
            }
            double r2 = r - ascent;
            double x0 = CENTERX;
            double y0 = CENTERY - r + ascent;
            // 旋轉角度
            double a = 2 * Math.asin(char_interval / (2 * r2));
    
            if (odd) {
                gs.drawString(messages[first],(float)(x0 - char_interval / 2), (float) y0);
                // 中心點的右邊
                for (int i = first + 1; i < ilength; i++) {
                    double aa = (i - first) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],(float) (x0 + ax - char_interval / 2 * Math.cos(aa)),
                            (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
                }
                // 中心點的左邊
                for (int i = first - 1; i > -1; i--) {
                    double aa = (first - i) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(-aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                    (float) (x0 - ax - char_interval / 2 * Math.cos(aa)),
                    (float) (y0 + ay + char_interval / 2 * Math.sin(aa)));
                }
            } else {
                // 中心點的右邊
                for (int i = second; i < ilength; i++) {
                    double aa = (i - second + 0.3) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 + ax - char_interval / 2 * Math.cos(aa)),
                        (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
                }
                // 中心點的左邊
                for (int i = first; i > -1; i--) {
                    double aa = (first - i + 0.7) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(-aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 - ax - char_interval / 2 * Math.cos(aa)),
                        (float) (y0 + ay + char_interval / 2* Math.sin(aa)));
                }
            }
        }
    }
    
    /**
     * 畫下方圓弧數字編碼
     *
     * @param gs
     * @param message
     * @param CENTERX
     * @param CENTERY
     * @param r
     */
    public static void drawBelowNumber(Graphics2D gs, String message, int CENTERX, int CENTERY, int r) {
        if (message != null) {
            // 根據輸入字元串得到字元數組
            String[] messages2 = message.split("", 0);
            String[] messages = new String[messages2.length - 1];
            System.arraycopy(messages2, 1, messages, 0, messages2.length - 1);
            // 輸入的字數
            int ilength = messages.length;
            Font f = gs.getFont();
            FontRenderContext context = gs.getFontRenderContext();
            Rectangle2D bounds = f.getStringBounds(message, context);
            // 字元寬度=字元串長度/字元數
            double char_interval = (bounds.getWidth() / ilength) + 4;
            // 上坡度
            double ascent = -bounds.getY();
            int first = 0, second = 0;
            boolean odd = false;
            if (ilength % 2 == 1) {
                first = (ilength - 1) / 2;
                odd = true;
            } else {
                first = (ilength) / 2 - 1;
                second = (ilength) / 2;
                odd = false;
            }
            double r2 = r - ascent;
            double x0 = CENTERX;
            double y0 = CENTERY - r + ascent;
            // 旋轉角度
            double a = 2 * Math.asin(char_interval / (2 * r2));
            if (odd) {
                // 中心點的右邊
                for (int i = first + 1; i < ilength; i++) {
                    double aa = (i - first + 0.5) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(2*Math.PI - aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 + ax - char_interval / 2 * Math.cos(aa)),
                        2*CENTERY - (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
                }
                // 中心點的左邊
                for (int i = first; i > -1; i--) {
                    double aa = (first - i - 0.5) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(2*Math.PI + aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 - ax - char_interval / 2 * Math.cos(aa)),
                        2*CENTERY - (float) (y0 + ay + char_interval / 2 * Math.sin(aa)));
                }
            } else {
                // 中心點的右邊
                for (int i = second; i < ilength; i++) {
                    double aa = (i - second + 1) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(2*Math.PI - aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 + ax - char_interval / 2 * Math.cos(aa)),
                        2*CENTERY - (float) (y0 + ay - char_interval / 2 * Math.sin(aa)));
                }
                // 中心點的左邊
                for (int i = first; i > -1; i--) {
                    double aa = (first - i) * a;
                    double ax = r2 * Math.sin(aa);
                    double ay = r2 - r2 * Math.cos(aa);
                    AffineTransform transform = AffineTransform.getRotateInstance(2*Math.PI + aa);
                    Font f2 = f.deriveFont(transform);
                    gs.setFont(f2);
                    gs.drawString(messages[i],
                        (float) (x0 - ax - char_interval / 2 * Math.cos(aa)),
                        2*CENTERY - (float) (y0 + ay + char_interval / 2* Math.sin(aa)));
                }
            }
        }
    }
    
    /**
     * 畫章中間的五角星
     *
     * @param g
     * @param x
     * @param y
     * @param r
     */
    public static void drawFiveStar(Graphics g, int x, int y, int r) {
        double ch=72*Math.PI/180;
        int x1=x,
            x2=(int)(x-Math.sin(ch)*r),
            x3=(int)(x+Math.sin(ch)*r),
            x4=(int)(x-Math.sin(ch/2)*r),
            x5=(int)(x+Math.sin(ch/2)*r);
        int y1=y-r,
            y2=(int)(y-Math.cos(ch)*r),
            y3=y2,
            y4=(int)(y+Math.cos(ch/2)*r),
            y5=y4;
        int bx=(int)(x+Math.cos(ch)*Math.tan(ch/2)*r);
        int by=y2;

        Polygon a=new Polygon();
        Polygon b=new Polygon();
        a.addPoint(x2,y2);
        a.addPoint(x5,y5);
        a.addPoint(bx,by);
        b.addPoint(x1,y1);
        b.addPoint(bx,by);
        b.addPoint(x3,y3);
        b.addPoint(x4,y4);

        g.fillPolygon(a);
        g.fillPolygon(b);
    }
}


//寫入到pdf 公章處
            //pdf模板所在路徑 (通過類名獲取文件路徑)
            String templateFileName = ContractServiceImpl.class.getClassLoader().getResource("sb_loan_contract_borrow.pdf").getFile();
            //使用itext的包讀取pdf模板
            PdfReader pdfReader = new PdfReader(templateFileName);
            
            // 提取pdf中的表單輸入域欄位
            AcroFields form = pdfStamper.getAcroFields();
            // 通過功能變數名稱獲取所在頁(頁數)和坐標,左下角為起點
            int pageNo = form.getFieldPositions("Chapter").get(0).page;
            Rectangle signRect = form.getFieldPositions("Chapter").get(0).position;
            //獲取x y 坐標
            float x = signRect.getLeft();
            float y = signRect.getBottom();

            //生成一個簽章(用java.awt 畫一個章)  章:上需要幾個常量值Constants.CHAPTER_NAME, Constants.CHAPTER_COMPANY_NAME, Constants.CHAPTER_SOCIAL_NUMBER
            String imgPath = DrawSeal.drawCircularChapter(Constants.CHAPTER_NAME, Constants.CHAPTER_COMPANY_NAME, Constants.CHAPTER_SOCIAL_NUMBER);
            
            // 讀圖片
            Image image = Image.getInstance(imgPath);
            // 獲取操作的頁面
            PdfContentByte under = pdfStamper.getOverContent(pageNo);
            // 根據域的大小縮放圖片
            image.scaleToFit(signRect.getWidth(), signRect.getHeight());
            // 添加圖片
            image.setAbsolutePosition(x, y);
            under.addImage(image);
    
            pdfStamper.flush();
            pdfStamper.close();
            pdfReader.close();




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 先分享幾個鏈接:(POI的中文API,別人總結的拿來用特別方便) http://blog.csdn.net/m0_37505412/article/details/71109503 https://www.cnblogs.com/fqfanqi/p/6172223.html 我在項目中做這個功能的時 ...
  • 《Head First 設計模式》學習中 裝飾者模式 動態的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案 類圖 參與者 1.Component(被裝飾對象的基類) 定義一個對象介面,可以給這些對象動態地添加職責。 2.ConcreteComponent(具體被裝飾對象) 定 ...
  • 恢復內容開始 思路:從倒數第二行開始,每個節點的值加上它下一層的左右節點的最大值,然後逐層向上遍歷,直到頂點,迴圈結束,輸出頂點內容 恢復內容結束 ...
  • 合併pdf pom.xml添加Jar依賴 <!-- pdf處理jar依賴 start --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.12</version ...
  • 先附spring各版本jar包下載鏈接http://repo.spring.io/release/org/springframework/spring/ spring.jar 是包含有完整發佈模塊的單個jar 包。但是不包括mock.jar, aspects.jar, spring-portlet. ...
  • The factorial function, n! is defined thus for n a non-negative integer:0! = 1 n! = n×(n−1)! (n > 0)We say that a divides b if there exists an integer ...
  • 功能 功能 把格式化的數據寫入某個字元緩衝區。 所需頭文件 所需頭文件 stdio.h 原型 原型 int sprintf( char *buffer, const char *format, [ argument] … ); 參數列表 參數列表 buffer:char型指針,指向將要寫入的字元串的 ...
  • Python 數字數據類型用於存儲數值。 數據類型是不允許改變的,這就意味著如果改變數字數據類型得值,將重新分配記憶體空間。 以下實例在變數賦值時 Number 對象將被創建: 您也可以使用del語句刪除一些數字對象的引用。 del語句的語法是: 您可以通過使用del語句刪除單個或多個對象的引用,例如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...