java图片动态添加水印(利用Graphics2D)
2014-03-10 20:18
471 查看
大家可能都对水印有了解,但是一般的水印都是事先生成的图片,比如
![](http://img.blog.csdn.net/20140310200329421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5cnVubmVyMDY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
右下角会有一个水印logo,用来标明图片的出处。
但是如果有一个需求是,需要对某个网站的信息进行加密,对于每个信息都需要针对浏览者进行动态水印的添加,也就是浏览的时候才生成,如下图:
![](http://img.blog.csdn.net/20140310200800625?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5cnVubmVyMDY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这时,我们就需要借用java中的2D画笔,来进行这个过程,代码如下:
这个类传入的参数为一个封装好的BO,代码为:
如果是要给新闻添加水印的话,我们会选择将文章word转为pdf,然后再后台先将pdf转为图片,这样就可以保证前面的图片来源了。
附上将pdf转为图片的类:
如果觉得前面进行浏览时,速度跟不上,可以使用多线程和futuretask来帮你快速的完成图片处理。我试过多线程处理响应速度一般也就是1秒多一点点,基本处于可以接受的状态,而且如果觉得这样还不行,你可以考虑使用缓存文件系统,将生成的图片存储起来,下次如果发现有就不用再生成了。
右下角会有一个水印logo,用来标明图片的出处。
但是如果有一个需求是,需要对某个网站的信息进行加密,对于每个信息都需要针对浏览者进行动态水印的添加,也就是浏览的时候才生成,如下图:
这时,我们就需要借用java中的2D画笔,来进行这个过程,代码如下:
public class WordIcon { private static String CSSCOLOR = "#bf8f79"; private static float ALPHA = 0.4f; public static ImgStreamBO createMark(WaterMarkBO waterMarkBO) { BufferedImage bimage = buildGraph2d(waterMarkBO); ImgStreamBO imgStreamBO = outputPic(bimage); String imgName = waterMarkBO.getFileUrl().substring(waterMarkBO.getFileUrl().lastIndexOf("/")+1, waterMarkBO.getFileUrl().length()); imgStreamBO.setFileName(imgName+waterMarkBO.getUserId()); return imgStreamBO; } //构造2d画笔 private static BufferedImage buildGraph2d(WaterMarkBO waterMarkBO){ Color markContentColor = Color.gray; URL url; try { url = new URL(waterMarkBO.getFileUrl()); } catch (MalformedURLException e) { LoggerHelper.err(WordIcon.class, "pic url error"); return null; } ImageIcon imgIcon = new ImageIcon(url); Image theImg = imgIcon.getImage(); //Image可以获得 输入图片的信息 int width = theImg.getWidth(null); int height = theImg.getHeight(null); //为画出图片的大小 BufferedImage bimage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB); //2d 画笔 Graphics2D g = bimage.createGraphics(); g.setColor(markContentColor); g.setBackground(Color.white); //画出图片----------------------------------- g.drawImage(theImg, 0, 0, null); //--------对要显示的文字进行处理-------------- AttributedCharacterIterator iter = buildFont(waterMarkBO.getMarkContent(), waterMarkBO.getFontType(), waterMarkBO.getFontSize()); Color color = Color.decode(CSSCOLOR); g.setColor(color); if (null != waterMarkBO.getDegree()) { // 设置水印旋转 g.rotate(Math.toRadians(waterMarkBO.getDegree()), (double) bimage.getWidth() / 2, (double) bimage .getHeight() / 2); } g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); for(int i=0;i<9;i++){ for(int j = 0;j<6;j++){ g.drawString(iter, (int) (width - (width*j/4)), (int) (height - (height*i/8))); } } //添加水印的文字和设置水印文字出现的内容 ----位置 g.dispose();//画笔结束 return bimage; } //输出文件 private static ImgStreamBO outputPic(BufferedImage bimage) { ByteArrayOutputStream out = null; ImgStreamBO imgStreamBO = new ImgStreamBO(); try { //输出 文件 到指定的路径 out = new ByteArrayOutputStream(); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage); param.setQuality(1, true); encoder.encode(bimage, param); byte[] buff = out.toByteArray(); imgStreamBO.setInput(new ByteArrayInputStream(buff)); imgStreamBO.setLength((long)buff.length); return imgStreamBO; } catch (Exception e) { LoggerHelper.err(WordIcon.class, "get inputStream error"); return null; }finally{ if(out!=null){ try { out.close(); } catch (IOException e) { LoggerHelper.err(WordIcon.class, "close outputStream error"); } } } } //形成字体属性 private static AttributedCharacterIterator buildFont(String markContent, String fontType, int fontSize) { AttributedString ats = new AttributedString(markContent); Font f = new Font(fontType, Font.PLAIN, fontSize); ats.addAttribute(TextAttribute.FONT, f, 0, markContent.length()); AttributedCharacterIterator iter = ats.getIterator(); return iter; } }
这个类传入的参数为一个封装好的BO,代码为:
public class WaterMarkBO { private String fileUrl; private String markContent; private String fontType; private int fontSize; private Integer degree; private Long userId; public WaterMarkBO(){ } public WaterMarkBO(String fileUrl, String markContent, String fontType, int fontSize, Integer degree,Long userId){ this.fileUrl = fileUrl; this.markContent = markContent; this.fontType = fontType; this.fontSize = fontSize; this.degree = degree; this.userId = userId; } ……省略get,set方法 }这样的话,就可以动态的给图片添加水印。
如果是要给新闻添加水印的话,我们会选择将文章word转为pdf,然后再后台先将pdf转为图片,这样就可以保证前面的图片来源了。
附上将pdf转为图片的类:
public class PDFchangToImage { public static List<String> changePdfToImg(String serverPath,String filePath,long articleId) { List<String> picUrl = new ArrayList<String>(); try { String path = serverPath + File.separatorChar; File file = new File(filePath); RandomAccessFile raf = new RandomAccessFile(file, "r"); FileChannel channel = raf.getChannel(); MappedByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); PDFFile pdffile = new PDFFile(buf); for (int i = 1; i <= pdffile.getNumPages(); i++) { PDFPage page = pdffile.getPage(i); Rectangle rect = new Rectangle(0, 0, ((int) page.getBBox().getWidth()), ((int) page.getBBox().getHeight())); int n = 2;/**图片清晰度(n>0且n<7)【pdf放大参数】*/ Image img = page.getImage(rect.width * n, rect.height * n, rect, /**放大pdf到n倍,创建图片。*/null, /**null for the ImageObserver */true, /** fill background with white */true /** block until drawing is done */); BufferedImage tag = new BufferedImage(rect.width * n, rect.height * n, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(img, 0, 0, rect.width * n, rect.height * n, null); /** File imgfile = new File("D:\\work\\mybook\\FilesNew\\img\\" + i + ".jpg"); if(imgfile.exists()){ if(imgfile.createNewFile()) { System.out.println("创建图片:"+"D:\\work\\mybook\\FilesNew\\img\\" + i + ".jpg"); } else { System.out.println("创建图片失败!"); } } */ String singleFilePath = path + articleId + i +".jpg"; FileOutputStream out = new FileOutputStream(singleFilePath); /** 输出到文件流*/ picUrl.add(singleFilePath); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param2 = encoder.getDefaultJPEGEncodeParam(tag); param2.setQuality(1f, true);/**1f~0.01f是提高生成的图片质量 */encoder.setJPEGEncodeParam(param2); encoder.encode(tag);/** JPEG编码 */out.close(); } channel.close(); raf.close(); unmap(buf);/**如果要在转图片之后删除pdf,就必须要这个关闭流和清空缓冲的方法*/ }catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return picUrl; } private static void unmap(final Object buffer) { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]); getCleanerMethod.setAccessible(true); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(buffer, new Object[0]); cleaner.clean(); } catch (Exception e) { e.printStackTrace(); } return null; } }); } }
如果觉得前面进行浏览时,速度跟不上,可以使用多线程和futuretask来帮你快速的完成图片处理。我试过多线程处理响应速度一般也就是1秒多一点点,基本处于可以接受的状态,而且如果觉得这样还不行,你可以考虑使用缓存文件系统,将生成的图片存储起来,下次如果发现有就不用再生成了。
相关文章推荐
- C# :实现水印与图片合成,并利用Graphics 压缩图像质量 , (委托实现listBox的动态添加提示)
- C# :实现水印与图片合成,并利用Graphics 压缩图像质量 , (委托实现listBox的动态添加提示)。。。。。。。。。。。。
- C# :实现水印与图片合成,并利用Graphics 压缩图像质量 , (委托实现listBox的动态添加提示)
- Java 实现 pdf文件添加 图片水印 itextpdf 5.5.2
- java给图片添加水印文字
- Java给图片添加图片、文字水印
- 使用Java添加图片水印和文字水印
- java给图片添加水印
- java图片添加水印实例代码分享
- java 添加水印 保留原图片的像素
- java程序给指定的图片添加水印文字并完美消除文字锯齿
- JAVA 给图片添加水印
- 利用iTextSharp组件给PDF文档添加图片水印,文字水印
- java 实现给图片添加水印
- 用java实现给图片增加图片水印或者文字水印(也支持视频图像帧添加水印)
- java.imageIo给图片添加水印
- 利用canvas添加图片水印--直接上代码
- 利用java的Graphics2D在图片上写字
- JAVA利用Gif4j将GIF图片加水印
- java实现给图片添加水印、透明度