• 解析Java核心技术点-生成缩略图

    发布:51Code 时间: 2017-10-09 13:44

  • [ 理论知识] 在java程序开发中,要显示一张图片,主要有两种方式。第一种是基于现成图片,这种方式比较常见也比较简单。第二种是使用java中java.awt包和com.sun.image包中的绘图技术,使...

  • [理论知识]

           在java程序开发中,要显示一张图片,主要有两种方式。第一种是基于现成图片,这种方式比较常见也比较简单。第二种是使用java中java.awt包和com.sun.image包中的绘图技术,使用代码绘制出一张图片,这种技术一般适用于图片并非固定、重复使用率较低的场景,比如验证码、图片加水印、生成缩略图、绘制各种数据分析图(柱状图、饼图、线性图等),这些图片并不是固定的,而是根据数据的改变而随时变化的。

       [步骤解读一]封装图片重定义尺寸的功能类

           本文中,小博老师就为大家解析一下,如何使用java绘图技术来为图片生成缩略图,由于图片修改尺寸的功能比较常用,代码又比较繁琐,因此小博老师先为大家封装一个ImageUtils类,以后要给图片重定义尺寸就可以直接调用它了(图片加水印的功能也在其中),核心代码如下:

    package com.bwf.framework.javaee.imageutils;
    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.geom.AffineTransform;
    import java.awt.image.AffineTransformOp;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    /**
     * 图片工具类, 图片水印,文字水印,缩放,补白等
     * @author 博为峰-小博老师
     */
    public final class ImageUtils {
           /** 图片格式:JPG */
           private static final String PICTRUE_FORMATE_JPG = "jpg";
           private ImageUtils() {}
           /**
            * 添加图片水印
            * @param targetImg 目标图片路径,如:C://myPictrue//1.jpg
            * @param waterImg 水印图片路径,如:C://myPictrue//logo.png
            * @param x 水印图片距离目标图片左侧的偏移量,如果x<0, 则在正中间
            * @param y 水印图片距离目标图片上侧的偏移量,如果y<0, 则在正中间
            * @param alpha 透明度(0.0 -- 1.0, 0.0为完全透明,1.0为完全不透明)
            */
           public final static void pressImage(String targetImg, String waterImg, int x, int y, float alpha) {
                  try {
                         File file = new File(targetImg);
                         Image image = ImageIO.read(file);
                         int width = image.getWidth(null);
                         int height = image.getHeight(null);
                         BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                         Graphics2D g = bufferedImage.createGraphics();
                         g.drawImage(image, 0, 0, width, height, null);
                         Image waterImage = ImageIO.read(new File(waterImg)); // 水印文件
                         int width_1 = waterImage.getWidth(null);
                         int height_1 = waterImage.getHeight(null);
                   g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
                         int widthDiff = width - width_1;
                         int heightDiff = height - height_1;
                         if (x < 0) {
                                x = widthDiff / 2;
                         } else if (x > widthDiff) {
                                x = widthDiff;
                         }
                         if (y < 0) {
                                y = heightDiff / 2;
                         } else if (y > heightDiff) {
                                y = heightDiff;
                         }
                         g.drawImage(waterImage, x, y, width_1, height_1, null); // 水印文件结束
                         g.dispose();
                         ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
                  } catch (IOException e) {
                         e.printStackTrace();
                  }
           }
           /**
            * 添加文字水印
            * @param targetImg 目标图片路径,如:C://myPictrue//1.jpg
            * @param pressText 水印文字, 如:中国证券网
            * @param fontName 字体名称, 如:宋体
            * @param fontStyle 字体样式,如:粗体和斜体(Font.BOLD|Font.ITALIC)
            * @param fontSize 字体大小,单位为像素
            * @param color 字体颜色
            * @param x 水印文字距离目标图片左侧的偏移量,如果x<0, 则在正中间
            * @param y 水印文字距离目标图片上侧的偏移量,如果y<0, 则在正中间
            * @param alpha 透明度(0.0 -- 1.0, 0.0为完全透明,1.0为完全不透明)
            */
           public static void pressText(String targetImg, String pressText, String fontName, int fontStyle, int fontSize,
                         Color color, int x, int y, float alpha) {
                  try {
                         File file = new File(targetImg);
                         Image image = ImageIO.read(file);
                         int width = image.getWidth(null);
                         int height = image.getHeight(null);
                         BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                         Graphics2D g = bufferedImage.createGraphics();
                         g.drawImage(image, 0, 0, width, height, null);
                         g.setFont(new Font(fontName, fontStyle, fontSize));
                         g.setColor(color);
                  g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
                         int width_1 = fontSize * getLength(pressText);
                         int height_1 = fontSize;
                         int widthDiff = width - width_1;
                         int heightDiff = height - height_1;
                         if (x < 0) {
                                x = widthDiff / 2;
                         } else if (x > widthDiff) {
                                x = widthDiff;
                         }
                         if (y < 0) {
                                y = heightDiff / 2;
                         } else if (y > heightDiff) {
                                y = heightDiff;
                         }
                         g.drawString(pressText, x, y + height_1);
                         g.dispose();
                         ImageIO.write(bufferedImage, PICTRUE_FORMATE_JPG, file);
                  } catch (Exception e) {
                         e.printStackTrace();
                  }
           }
     
           /**
            * 获取字符长度,一个汉字作为 1 个字符, 一个英文字母作为 0.5 个字符
            * @param text
            * @return 字符长度,如:text="中国",返回 2;text="test",返回 2;text="中国ABC",返回 4.
            */
           public static int getLength(String text) {
                  int textLength = text.length();
                  int length = textLength;
                  for (int i = 0; i < textLength; i++) {
                         if (String.valueOf(text.charAt(i)).getBytes().length > 1) {
                                length++;
                         }
                  }
                  return (length % 2 == 0) ? length / 2 : length / 2 + 1;
           }
           /**
            * 图片缩放
            * @param filePath 图片路径
            * @param height 高度
            * @param width 宽度
            * @param bb 比例不对时是否需要补白
            */
           public static void resize(String filePath, int height, int width, boolean bb) {
                  try {
                         double ratio = 0; // 缩放比例
                         File f = new File(filePath);
                         BufferedImage bi = ImageIO.read(f);
                         Image itemp = bi.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
                         // 计算比例
                         if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
                                if (bi.getHeight() > bi.getWidth()) {
                                       ratio = (new Integer(height)).doubleValue() / bi.getHeight();
                                } else {
                                       ratio = (new Integer(width)).doubleValue() / bi.getWidth();
                                }
                                AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
                                itemp = op.filter(bi, null);
                         }
                         if (bb) {
                                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                                Graphics2D g = image.createGraphics();
                                g.setColor(Color.white);
                                g.fillRect(0, 0, width, height);
                                if (width == itemp.getWidth(null))
                                       g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null),itemp.getHeight(null), Color.white, null);
                                else
                                       g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),itemp.getHeight(null), Color.white, null);
                                g.dispose();
                                itemp = image;
                         }
                         ImageIO.write((BufferedImage) itemp, "jpg", f);
                  } catch (IOException e) {
                         e.printStackTrace();
                  }
           }
    }
     
       [步骤解读二]制作上传文件的功能

           接下来我们制作一个简单的上传文件页面,我们创建一个jsp,核心代码如下:

    <body>
    <form action="BWFUpload" method="POST" enctype="multipart/form-data">
           上传图片:<input type="file" name="upload"/><br/><br/>
           <input type="submit" value="开始上传"/>
    </form>
    </body>

           访问jsp页面效果如下:

    为了实现上传文件到服务器的功能,并且要求在服务器不但会保存一份原文件,还会自动生成一份缩略图,我们创建一个Servlet来处理用户上传的图片,核心代码如下:

    @WebServlet("/BWFUpload")
    public class BWFUploadServlet extends HttpServlet {
           protected void doPost(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
                  response.setCharacterEncoding("UTF-8");
                  response.setHeader("Content-Type", "text/html; charset=UTF-8");
                  // 实例化 JspSmartUpload对象
                  SmartUpload upload = new SmartUpload();
                  // 初始化 JspSmartUpload对象 参数
                  upload.initialize(getServletConfig(), request, response);
                  try {
                         // 转换request请求中的post报文数据
                         upload.upload();
                         // 获取所有上传文件
                         Files files = upload.getFiles();
                         // 循环所有上传文件
                         for( int i = 0 ; i <= files.getCount() - 1 ; i++ ){
                                // 获取当前循环到的上传文件
                                File file = files.getFile(i);
                                // 使用UUID为上传文件生成随机文件名
                                UUID uuid = UUID.randomUUID();
                                // 上传文件随机文件名  拼接  原文件扩展名 
                                String filename = uuid.toString() + file.getFileName().substring( file.getFileName().lastIndexOf(".") );
                                // 保存上传文件
           file.saveAs( getServletContext().getRealPath("uploads/"+filename) );
                                // 为缩略图生成文件名
                                String small = uuid.toString()+ ".small" + file.getFileName().substring( file.getFileName().lastIndexOf(".") );
                                // 另存一份缩略图
                                file.saveAs( getServletContext().getRealPath("uploads/"+small) );
                                // 将缩略图重定义大小
                         ImageUtils.resize( getServletContext().getRealPath("uploads/"+small), 100 , 100 , false);
                         }
                  } catch (SmartUploadException e) {
                         e.printStackTrace();
                  }
           }
    }

           这样,我们的图片就可以上传到服务器了,并且会自动保存一份缩略图。

           原始图片:

    上传到服务器后,自动生成的缩略图:

  • 上一篇:解析Java核心技术点-图片加水印

    下一篇:解析Java核心技术点-Ajax验证账户名称

网站导航
Copyright(C)51Code软件开发网 2003-2015 , 沪ICP备05003035号