另类加水印——根据明暗度分别加不同的水印

来源:互联网 发布:mac media player加速 编辑:程序博客网 时间:2024/06/09 23:05
公司里要求上传的照片都要加上公司的logo,统一打在又下角。但是,由于照片有暗有亮,因此logo分成了2种,1种是在比较亮的情况下打的,1种是在比较暗的情况下打的。这可把我害惨了,如何判断明暗度嘛。奋力Google了1天终于理解,于是写出了实现代码。
由于注释写的比较全,因此不再进行解释,里面也有测试方法,可以进行下测试。
  1. package image;
  2. import java.awt.AlphaComposite;
  3. import java.awt.Color;
  4. import java.awt.Font;
  5. import java.awt.Graphics;
  6. import java.awt.Graphics2D;
  7. import java.awt.Image;
  8. import java.awt.image.BufferedImage;
  9. import java.awt.image.ColorModel;
  10. import java.awt.image.PixelGrabber;
  11. import java.io.File;
  12. import java.io.FileOutputStream;
  13. import javax.imageio.ImageIO;
  14. import com.sun.image.codec.jpeg.JPEGCodec;
  15. import com.sun.image.codec.jpeg.JPEGImageEncoder;
  16. public class WaterMark {
  17.     /**
  18.      * 获取指定矩形中的像素的矩阵
  19.      * 
  20.      * @param imageSrc
  21.      * @param startX
  22.      * @param startY
  23.      * @param w
  24.      * @param h
  25.      * @return
  26.      */
  27.     private int[] getPixArray(Image imageSrc, int startX, int startY,
  28.             int w, int h) {
  29.         int[] pix = new int[(w - startX) * (h - startY)];
  30.         
  31.         /*下面是别人程序中的一段,我不是很理解了*/
  32.         PixelGrabber pg = null;
  33.         try {
  34.             pg = new PixelGrabber(imageSrc, startX, startY, w-startX, h-startY, pix, 0, w-startX);
  35.             if (pg.grabPixels() != true) {
  36.                 try {
  37.                     throw new java.awt.AWTException("pg error" + pg.status());
  38.                 } catch (Exception eq) {
  39.                     eq.printStackTrace();
  40.                 }
  41.             }
  42.         } catch (Exception ex) {
  43.             ex.printStackTrace();
  44.         }
  45.         return pix;
  46.     }
  47.     /**
  48.      * 将1张图片和另1张图片的指定区域重合。可用于制作水印。图片的左上角坐标为0,0
  49.      * 
  50.      * @param lightnessWaterImg
  51.      *            颜色比较亮的水印图片,适合底色比较暗的情况
  52.      * @param darknessWaterImg
  53.      *            颜色比较暗的水印图片,适合底色比较亮的情况,如果不想区分,则输入null,平均灰度边界同时失效。
  54.      * @param targetImg
  55.      *            源图片
  56.      * @param startX
  57.      * @param startY
  58.      * @param x
  59.      * @param y
  60.      * @param alpha
  61.      *            透明度,0f为全透明,1f为完全不透明,0.5f为半透明
  62.      * @param averageGray
  63.      *            平均灰度边界(0-255),大于此值,则打暗的水印图片,小于此值则打亮的水印图片。
  64.      *            默认值128。超过范围,按默认值进行。
  65.      */
  66.     private final void pressImage(String lightnessWaterImg,
  67.             String darknessWaterImg, String targetImg, int startX, int startY,
  68.             int x, int y, float alpha, float averageGray) {
  69.         try {
  70.             // 先判断亮水印和源文件的值是否为null,否则抛出异常
  71.             if (lightnessWaterImg == null || lightnessWaterImg == ""
  72.                     || targetImg == null || targetImg == "") {
  73.                 throw new Exception("亮水印或者源图片的地址不能为空");
  74.             } 
  75.             // 再判断平均灰度边界是否越界
  76.             if (averageGray>255||averageGray<0) {
  77.                 averageGray = 128;
  78.             }
  79.             
  80.             // 装载源图片
  81.             File _file = new File(targetImg);
  82.             // 图片装入内存
  83.             BufferedImage src = ImageIO.read(_file);
  84.             // 获取图片的尺寸
  85.             int width = src.getWidth(null);
  86.             int height = src.getHeight(null);
  87.             // 根据源图片尺寸,设置预装载的一个图片,默认是RGB格式的
  88.             BufferedImage image = new BufferedImage(width, height,
  89.                     BufferedImage.TYPE_INT_RGB);
  90.             Graphics2D graphics = image.createGraphics();
  91.             // 绘制内存中的源图片至指定的矩形内
  92.             graphics.drawImage(src, 00, width, height, null);
  93.             // 在已经绘制的图片中加入透明度通道
  94.             graphics.setComposite(AlphaComposite.getInstance(
  95.                     AlphaComposite.SRC_ATOP, alpha));
  96.             
  97.             // 获取源图片中和设定的同样大小的区域内的像素集合
  98.             int[] pixels = getPixArray(src, startX, startY, x, y);
  99.             //查询此集合的平均灰度
  100.             float average = getAverageGrap(x-startX,y-startY,pixels);
  101.             // 如果平均灰度大于130,则说明此区域比较亮,否则则比较暗
  102.             System.out.println(average);
  103.             
  104.             //装载水印图片所需参数
  105.             File water;
  106.             BufferedImage bufferwater;
  107.             
  108.             // 根据设定的平均灰度边界来装载不同的水印
  109.             if (darknessWaterImg == null||average>=averageGray) {
  110.                 // 装载亮水印文件
  111.                 water = new File(darknessWaterImg);
  112.             }else{
  113.                 // 装载暗水印文件
  114.                 water = new File(lightnessWaterImg);
  115.             }
  116.             // 装入内存
  117.             bufferwater = ImageIO.read(water);
  118.                         
  119.             graphics.drawImage(bufferwater, startX, startY, x-startX, y-startY,
  120.                     null);
  121.             // 水印文件结束
  122.             graphics.dispose();
  123.             FileOutputStream out = new FileOutputStream(targetImg);
  124.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
  125.             // 绘制新的文件
  126.             encoder.encode(image);
  127.             out.close();
  128.             
  129.         } catch (Exception e) {
  130.             e.printStackTrace();
  131.         }
  132.     }
  133.         
  134.     /**
  135.      * 查询某个区域的平均灰度
  136.      * @param width
  137.      * @param height
  138.      * @param pixels
  139.      * @return
  140.      */
  141.     private float getAverageGrap(int width,int height,int[] pixels){
  142.         /* 下面是开始算这个区域的亮度了,灰度等同于亮度 */
  143.         ColorModel colorModel = ColorModel.getRGBdefault();
  144.         int i = 0;
  145.         int j = 0;
  146.         int k = 0;
  147.         int r = 0;
  148.         int g = 0;
  149.         int b = 0;
  150.         int gray = 0;
  151.         float average = 0;// 平均灰度
  152.         for (i = 0; i < height; i++) {
  153.             for (j = 0; j < width; j++) {
  154.                 // 定位像素点
  155.                 k = i * width + j;
  156.                 r = colorModel.getRed(pixels[k]);
  157.                 g = colorModel.getGreen(pixels[k]);
  158.                 b = colorModel.getBlue(pixels[k]);
  159.                 // 计算灰度值
  160.                 gray = (r * 38 + g * 75 + b * 15) >> 7;
  161.                 average = average + gray;
  162.             }
  163.         }
  164.         // 计算平均灰度
  165.         average = average / ((i - 1) * (j - 1));
  166.         return average;
  167.     }
  168.     public static void main(String[] args) {
  169.         WaterMark waterMark = new WaterMark();
  170.         waterMark.pressImage("F://Mine//My Pictures//素材//w2.png""F://Mine//My Pictures//素材//w1.png",
  171.                 "F://Mine//My Pictures//素材//2.jpg"5205009008000.5f, 50);
  172.         System.out.print("添加成功");
  173.     }
  174. }