无纸化办公中手写签名的实现

阅读更多

  最近要实现一个使用手写板对PDF文档进行手写签名的功能,下面记录一下关键过程。

 

  实现的思路如下:

1、在画板中显示PDF文档的内容

2、用户使用签名版对PDF文档进行签名

3、保存签名后的画板内容到新的PDF中

 

 其中使用pdfbox把PDF文档转成图片,签名后又把签名后的图片转回PDF保存。

  pdfbox(http://pdfbox.apache.org/)是一个处理PDF文档的JAVA库。

 

    import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

class TestDraw extends Canvas {
    Image image;
    boolean init = true;

    public static final int WIDTH = 1024;

    public static final int HEIGHT = 1024;

    public Image screen = createImage(WIDTH, HEIGHT, true);// 双缓冲

    private Graphics graphics = screen.getGraphics();

    public Image resultImage;

    int x1 = -1;
    int y1 = -1;
    int x2 = -1;
    int y2 = -1;

    public TestDraw() {
        this.setBackground(Color.white);
        this.addMouseListener(new MyMouseListener(this));
        this.addMouseMotionListener(new MyMouseMotionListener(this));

        image = pdfToImg("pdf/tests.pdf");

        // 设定初始构造时面板大小
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        // 初始导入一张图片
        ImageIcon icon = new ImageIcon(image);
        resultImage = icon.getImage();

    }

    public void paint(Graphics g) {
        update(g);
    }

    @Override
    public void update(Graphics g) {
        BufferedImage bufferedImage= imageToBufferedImage(resultImage);

        // Copy image to buffered image
        Graphics g2 = bufferedImage.getGraphics();
        g2.setColor(Color.black);
        if (x1 == -1 || y1 == -1) {
            x1 = x2;
            y1 = y2;
        }
        g2.drawLine(x1, y1, x2, y2);
        x1 = x2;
        y1 = y2;
        g2.dispose();

        ImageIcon icon = new ImageIcon(bufferedImage);
        resultImage = icon.getImage();

        graphics.drawImage(resultImage, 0, 0, this);
        g.drawImage(screen, 0, 0, null);// 最后个参数一定要用null,这样可以防止drawImage调用update方法
        g.dispose();
    }


    public static BufferedImage imageToBufferedImage(Image im) {
       BufferedImage bi = new BufferedImage
          (im.getWidth(null),im.getHeight(null),BufferedImage.TYPE_INT_RGB);
       Graphics bg = bi.getGraphics();
       bg.drawImage(im, 0, 0, null);
       bg.dispose();
       return bi;
    }

    /**
     * 生成一个BufferImage
     * 生成一个BufferImage BufferImage是Image的子类,左上角坐标都为 (0, 0)
     * 第三个参数是代码Image图形类型,分为14种,以位数又分为1,2或4位
     *
     * @param width
     * @param height
     * @param flag
     * @return
     */
    final static public BufferedImage createImage(int width, int height,
                                                  boolean flag) {
        if (flag) {
            return new BufferedImage(width, height, 2);
        } else {
            return new BufferedImage(width, height, 1);
        }
    }

    /**
     * 把PDF转成图片
     * @param pdfFileName PDF文件路径
     * @return
     */
    public static Image pdfToImg(String pdfFileName) {
        ImageIcon imageIcon = null;
        try {
            PDDocument doc = PDDocument.load(pdfFileName);
            int pageCount = doc.getNumberOfPages();
            PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
            BufferedImage bufferedImage = page.convertToImage();
            if (bufferedImage != null) {
                imageIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(bufferedImage.getSource()));
            }
            doc.close();
        } catch (IOException ex) {
            Logger.getLogger(ShowJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        return imageIcon.getImage();
    }
}

class MyMouseListener implements MouseListener {
    TestDraw draw;

    public MyMouseListener(TestDraw draw) {
        this.draw = draw;
    }

    /**
     * 点击鼠标时保存新的PDF文件
     * @param e
     */
    public void mouseClicked(MouseEvent e) {
        System.out.println("mouseClicked");

        PDDocument doc = null;
        PDPage page = null;

        try {
            doc = new PDDocument();
            page = new PDPage();

            BufferedImage bufferedImage = toBufferedImage(draw.resultImage);
            File outputfile = new File("saved.png");
               ImageIO.write(bufferedImage, "png", outputfile);

            int w = bufferedImage.getWidth();
            int h = bufferedImage.getHeight();
            BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            AffineTransform at = new AffineTransform();
            at.scale(0.5, 0.5);
            AffineTransformOp scaleOp =
               new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
            after = scaleOp.filter(bufferedImage, after);

            doc.addPage(page);
            PDXObjectImage ximage = new PDJpeg(doc, after);
            PDPageContentStream content = new PDPageContentStream(doc, page, true, true);
//            content.drawImage(ximage, 0, 0);
            content.drawXObject(ximage, 0, 0, 800, 800);
            content.close();
            doc.save("save.pdf");
            doc.close();
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

    // This method returns a buffered image with the contents of an image
    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
            if (hasAlpha) {
                transparency = Transparency.BITMASK;
            }

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

    //Determining If an Image Has Transparent Pixels

    // This method returns true if the specified image has transparent pixels
    public static boolean hasAlpha(Image image) {
        // If buffered image, the color model is readily available
        if (image instanceof BufferedImage) {
            BufferedImage bimage = (BufferedImage) image;
            return bimage.getColorModel().hasAlpha();
        }

        // Use a pixel grabber to retrieve the image's color model;
        // grabbing a single pixel is usually sufficient
        PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
        }

        // Get the image's color model
        ColorModel cm = pg.getColorModel();
        return cm.hasAlpha();
    }

    public void mouseEntered(MouseEvent e) {
        //System.out.println("mouseEntered");
    }

    public void mouseExited(MouseEvent e) {
        //System.out.println("mouseExited");
    }

    public void mousePressed(MouseEvent e) {
        //System.out.println("mousePressed");
        draw.x1 = -1;
        draw.y1 = -1;
    }

    public void mouseReleased(MouseEvent e) {
        //System.out.println("mouseReleased");
        draw.x1 = draw.x2;
        draw.y1 = draw.y2;
    }
}

class MyMouseMotionListener implements MouseMotionListener {
    TestDraw draw;

    public MyMouseMotionListener(TestDraw draw) {
        this.draw = draw;
    }

    public void mouseDragged(MouseEvent e) {
        //System.out.println("mouseDragged");
        draw.x2 = e.getX();
        draw.y2 = e.getY();
        draw.repaint();
    }

    public void mouseMoved(MouseEvent e) {
        //System.out.println("mouseMoved");
    }
}

 

 

你可能感兴趣的:(pdfbox)