最近要实现一个使用手写板对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"); } }
相关推荐
安卓手写签名,电子签名。安卓手写签名可以显示手写签名动画
windows 下C++实现触摸屏手写签名以及保存签名图片
C# Winform 手写签名,自动保存签名至本地文件夹。 签名流畅无卡顿。 触摸屏上也可以正常使用
移动端手写签名,通过canvas绘制, 最后生成base64图片。移动端手写签名,通过canvas绘制, 最后生成base64图片
C# asp.net开发网页版本手写签名功能,也可以扩展连接手写笔使用
前端使用canvas实现手机端手写签名控件
手写签名,可以保存图片,并页面显示TestDemo 手写签名,可以手写保存图片,并显示在页面上。
手写签名图片,可保存为图片或到数据库 ,简单易懂,涉及控件pictureBox1
由于前一段时间项目需要,做了一个简单的手写签名系统,不是很完善,不过对于一般的需求是可以满足的,主要是针对pdf文件进行的操作,现在拿来给大家分享,希望有好的实现方式,能指点一下,大家共同进步。...
本软件用于在Word,Excel中加入手写签名,批注,印章。可嵌入OA. 作者网站:http://EJunSoft.ik8.com Email:Cyjsir@.163.COM或E_Jun@shou.com QQ:157123678 (注明手写签名软件) 安装(Word示例): 1...
javascript手写电子签名生成图片
index.html是签名板直接显示的版本 dialog是签名板用对话框显示的版本
本资源用于java实现在网页上手写笔迹进行生成图片保存,例如在网页上用鼠标写出自己的名字,生成图片,保存名字。
手写签名,把签名保存,显示签名在控件中,并截屏保存文件,
js实现手写签名,可以在移动端使用!下载直接打开就可以使用,有保存和重置功能!
使用html5 canvas标签实现手写 但是效果不是很好 没有笔锋 后续慢慢改进 感谢实现过程中帮助我的人
该插件用于PC端或移动端的手写签名功能主要应用在电子合同平台。
jquery实现手写输入签名,不需要任何硬件支持。 采用canvas标签处理签名,可以生成 PNG格式、SVG格式的签名图片,并把图片保存成字符串,根据字符串可以回显到页面。
1、支持PAD和PC签名。 2、生成文件为PNG内容。 3、随意画板生成图片。 4、源码100%开源。 5、C#winform签名生成图片
本软件采用ACTIVE技术,用于在Word中加入手写签名。目前版本只支持Word。 试用版,若要正试版,请联系Cyjsir@.163.COM或E_Jun@shou.com qq:157123678(注明手写签名软件) 安装: 1.安装前关闭Word 2.双击...