电子签章

对于菜鸟级别的开发来说(@本人),可能连电子签章还搞不明白是什么东西,直接贴代码,看效果就知道了!

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;

public class SealUtils {
    private static final int CANVAS_SIZE = 300; // 画布宽
    private static final String FONT_FAMILY = "宋体"; // 字体
    //private static final String FOOT_TXT = "电子签约专用章";// 底部文字
    private static final String FOOT_TXT = "别在这里跟我皮";// 底部文字
    private static final String STAR = "★";

    private static int STAR_SIZE = (int) (CANVAS_SIZE / 3.2); // 五角星大小
    private static int FOOT_FONT_SIZE = CANVAS_SIZE / 12; // 底部文字大小

    /**
     * 根据companyName获得合同专用章
     *
     * @param companyName
     * @return
     */
    public static BufferedImage genSealImage(String companyName) {
        BufferedImage bi = new BufferedImage(CANVAS_SIZE, CANVAS_SIZE, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2d = bi.createGraphics();
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0));
        g2d.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);

        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1));
        int circleRadius = CANVAS_SIZE / 2 - 10;
        drawCicle(g2d, circleRadius);
        drawStar(g2d, circleRadius);
        drawFootText(g2d, circleRadius);
        drwaHeadText(companyName, g2d, circleRadius);

        g2d.dispose();
        return bi;
    }

    public static void main(String[] args) {
        try {
            String name="xxx"; //生成签章名称
            byte[] img= SealUtils.genSealData(name);
            byte2File(img,"D:\\test\\",name+".png");
        } catch (IOException e) {
// TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 辅助方法,byte数组保存为本地文件
     * @param buf
     * @param filePath
     * @param fileName
     */
    private static void byte2File(byte[] buf, String filePath, String fileName)
    {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try
        {
            File dir = new File(filePath);
            if (!dir.exists())
            {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (bos != null)
            {
                try
                {
                    bos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (fos != null)
            {
                try
                {
                    fos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 根据companyName获得合同专用章
     *
     * @param companyName
     * @return
     * @throws IOException
     */
    public static byte[] genSealData(String companyName) throws IOException {
        BufferedImage image = genSealImage(companyName);
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", outStream);
        }
        catch (IOException e) {
            throw e;
        }
        finally {
            try {
                outStream.close();
            }
            catch (IOException e) {
            }
        }
        byte[] imageData = outStream.toByteArray();
        return imageData;
    }


    /**
     * 弧形绘制顶部名称
     *
     * @param companyName
     * @param g2d
     * @param circleRadius
     */
    private static void drwaHeadText(String companyName, Graphics2D g2d, int circleRadius) {
        int companyNameLen = companyName.length();
        int headFontSize;
        if (companyNameLen < 8) { // 字体根据画布大小微调出来的
            headFontSize = 47;
        }
        else {
            headFontSize = 43 - (companyNameLen - 8) * 2;
        }


        Font f;
        FontRenderContext context;
        Rectangle2D rectangle;
        f = new Font(FONT_FAMILY, Font.PLAIN, headFontSize);
        context = g2d.getFontRenderContext();
        rectangle = f.getStringBounds(companyName, context);


        double interval; // 文字之间间距
        if (companyNameLen == 1) {
            interval = 0;
        }
        else {
            interval = rectangle.getWidth() / (companyNameLen - 1) * 0.9;
        }


        double newRadius = circleRadius + rectangle.getY() - 10; // bounds.getY()是负数,这样可以将弧形文字固定在圆内了。-10目的是离圆环稍远一点
        double radianPerInterval = 2 * Math.asin(interval / (2 * newRadius)); // 每个间距对应的角度


        // 第一个元素的角度
        double firstAngle;
        if (companyNameLen % 2 == 1) {
            firstAngle = (companyNameLen - 1) * radianPerInterval / 2.0 + Math.PI / 2 + 0.18; // 0.18是浮点计算误差,如果文字不对称,可以微调
        }
        else {
            firstAngle = (companyNameLen / 2.0 - 1) * radianPerInterval + radianPerInterval / 2.0 + Math.PI / 2 + 0.18;
        }


        for (int i = 0; i < companyNameLen; i++) {
            double theta = firstAngle - i * radianPerInterval;
            double thetaX = newRadius * Math.sin(Math.PI / 2 - theta); // 小小的trick,将【0,pi】区间变换到[pi/2,-pi/2]区间
            double thetaY = newRadius * Math.cos(theta - Math.PI / 2); // 同上类似,这样处理就不必再考虑正负的问题了
            AffineTransform transform = AffineTransform.getRotateInstance(Math.PI / 2 - theta);
            Font f2 = f.deriveFont(transform);
            g2d.setFont(f2);
            g2d.drawString(companyName.substring(i, i + 1), (float) (circleRadius + thetaX + 10), (float) (circleRadius - thetaY + 10));
        }
    }


    /**
     * 画底部文字
     *
     * @param g2d
     * @param circleRadius
     */
    private static void drawFootText(Graphics2D g2d, int circleRadius) {
        Font f;
        FontRenderContext context;
        Rectangle2D rectangle;
        f = new Font(FONT_FAMILY, Font.BOLD, FOOT_FONT_SIZE);
        context = g2d.getFontRenderContext();
        rectangle = f.getStringBounds(FOOT_TXT, context);
        int a = 10 * CANVAS_SIZE / 350; // 底部文字距中心的距离,这是调出来的
        g2d.setFont(f);
        g2d.drawString(FOOT_TXT, (float) (circleRadius + a - rectangle.getCenterX()), (float) (circleRadius * 1.5 + a - rectangle.getCenterY()));
    }


    /**
     * 画中心的 ★
     *
     * @param g2d
     * @param circleRadius
     */
    private static void drawStar(Graphics2D g2d, int circleRadius) {
        Font f = new Font(FONT_FAMILY, Font.PLAIN, STAR_SIZE);
        FontRenderContext context = g2d.getFontRenderContext();
        Rectangle2D rectangle = f.getStringBounds(STAR, context);
        g2d.setFont(f);
        g2d.drawString(STAR, (float) (circleRadius + 10 - rectangle.getCenterX()), (float) (circleRadius + 10 - rectangle.getCenterY()));
    }


    /**
     * 画外圈圆
     *
     * @param g2d
     * @param circleRadius
     */
    private static void drawCicle(Graphics2D g2d, int circleRadius) {
        g2d.setPaint(Color.red);
        int lineSize = circleRadius * 2 / (35); // 圆线条粗细是圆直径的1/35
        g2d.setStroke(new BasicStroke(lineSize));
        Shape circle = new Arc2D.Double(10, 10, circleRadius * 2, circleRadius * 2, 0, 360, Arc2D.OPEN);
        g2d.draw(circle);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值