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

公司里要求上传的照片都要加上公司的logo,统一打在又下角。但是,由于照片有暗有亮,因此logo分成了2种,1种是在比较亮的情况下打的,1种是在比较暗的情况下打的。这可把我害惨了,如何判断明暗度嘛。奋力Google了1天终于理解,于是写出了实现代码。
由于注释写的比较全,因此不再进行解释,里面也有测试方法,可以进行下测试。


[color=red][b]PS:目标图请做好备份,因为其会直接覆盖目标图[/b][/color]

package image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.FileOutputStream;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class WaterMark {

/**
* 获取指定矩形中的像素的矩阵
*
* @param imageSrc
* @param startX
* @param startY
* @param w
* @param h
* @return
*/
private int[] getPixArray(Image imageSrc, int startX, int startY,
int w, int h) {
int[] pix = new int[(w - startX) * (h - startY)];

/*下面是别人程序中的一段,我实在不明白为何要加这一段,因为我去掉也没有问题,加上还会报错*/
PixelGrabber pg = null;
try {
pg = new PixelGrabber(imageSrc, startX, startY, w-startX, h-startY, pix, 0, w);
if (pg.grabPixels() != true) {
try {
throw new java.awt.AWTException("pg error" + pg.status());
} catch (Exception eq) {
eq.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return pix;
}

/**
* 将1张图片和另1张图片的指定区域重合。可用于制作水印。图片的左上角坐标为0,0
*
* @param lightnessWaterImg
* 颜色比较亮的水印图片,适合底色比较暗的情况
* @param darknessWaterImg
* 颜色比较暗的水印图片,适合底色比较亮的情况,如果不想区分,则输入null,平均灰度边界同时失效。
* @param targetImg
* 源图片
* @param startX
* @param startY
* @param x
* @param y
* @param alpha
* 透明度,0f为全透明,1f为完全不透明,0.5f为半透明
* @param averageGray
* 平均灰度边界(0-255),大于此值,则打暗的水印图片,小于此值则打亮的水印图片。
* 默认值128。超过范围,按默认值进行。
*/
private final void pressImage(String lightnessWaterImg,
String darknessWaterImg, String targetImg, int startX, int startY,
int x, int y, float alpha, float averageGray) {
try {
// 先判断亮水印和源文件的值是否为null,否则抛出异常
if (lightnessWaterImg == null || lightnessWaterImg == ""
|| targetImg == null || targetImg == "") {
throw new Exception("亮水印或者源图片的地址不能为空");
}
// 再判断平均灰度边界是否越界
if (averageGray>255||averageGray<0) {
averageGray = 128;
}


// 装载源图片
File _file = new File(targetImg);
// 图片装入内存
BufferedImage src = ImageIO.read(_file);
// 获取图片的尺寸
int width = src.getWidth(null);
int height = src.getHeight(null);
// 根据源图片尺寸,设置预装载的一个图片,默认是RGB格式的
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
// 绘制内存中的源图片至指定的矩形内
graphics.drawImage(src, 0, 0, width, height, null);
// 在已经绘制的图片中加入透明度通道
graphics.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_ATOP, alpha));


// 获取源图片中和设定的同样大小的区域内的像素集合
int[] pixels = getPixArray(src, startX, startY, x, y);

//查询此集合的平均灰度
float average = getAverageGrap(x-startX,y-startY,pixels);

// 如果平均灰度大于130,则说明此区域比较亮,否则则比较暗
System.out.println(average);


//装载水印图片所需参数
File water;
BufferedImage bufferwater;

// 根据设定的平均灰度边界来装载不同的水印
if (darknessWaterImg == null||average>=averageGray) {
// 装载亮水印文件
water = new File(darknessWaterImg);
}else{
// 装载暗水印文件
water = new File(lightnessWaterImg);
}
// 装入内存
bufferwater = ImageIO.read(water);

graphics.drawImage(bufferwater, startX, startY, x, y,
null);
// 水印文件结束
graphics.dispose();
FileOutputStream out = new FileOutputStream(targetImg);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
// 绘制新的文件
encoder.encode(image);
out.close();

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 查询某个区域的平均灰度
* @param width
* @param height
* @param pixels
* @return
*/
private float getAverageGrap(int width,int height,int[] pixels){
/* 下面是开始算这个区域的亮度了,灰度等同于亮度 */
ColorModel colorModel = ColorModel.getRGBdefault();
int i = 0;
int j = 0;
int k = 0;
int r = 0;
int g = 0;
int b = 0;
int gray = 0;
float average = 0;// 平均灰度
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
// 定位像素点
k = i * width + j;
r = colorModel.getRed(pixels[k]);
g = colorModel.getGreen(pixels[k]);
b = colorModel.getBlue(pixels[k]);

// 计算灰度值
gray = (r * 38 + g * 75 + b * 15) >> 7;

average = average + gray;
}
}
// 计算平均灰度
average = average / ((i - 1) * (j - 1));
return average;
}
public static void main(String[] args) {
WaterMark waterMark = new WaterMark();

waterMark.pressImage("F:\\Mine\\My Pictures\\素材\\w2.png", "F:\\Mine\\My Pictures\\素材\\w1.png",
"F:\\Mine\\My Pictures\\素材\\2.jpg", 520, 500, 900, 800, 0.5f, 50);
System.out.print("添加成功");
}

}
Java实现图片透明效果,从演示截图可看到,上层图片与下层图片互相重叠,也就是上层图片透明了,看到了下层以的图片,具体的代码实现:   public class HalfTransparentImageDemo extends JFrame {    private Container content = getContentPane(); //获得窗口的容器    private JSlider jSlider = new JSlider(JSlider.HORIZONTAL,0,100,75); //改变图像的透明    DisplayPanel displayPanel = new DisplayPanel(); //显示图形面板    public HalfTransparentImageDemo() {    super("半透明图片"); //调用父类构造器    jSlider.setPaintTicks(true); //绘制标志位    jSlider.setMajorTickSpacing(25); //设置标志尺寸    jSlider.setMinorTickSpacing(5);    jSlider.setPaintLabels(true); //绘制出数字    jSlider.setBorder(new TitledBorder(BorderFactory.createEmptyBorder(), "图像的透明(%)")); //设置边框    jSlider.addChangeListener(new ChangeListener() { //滑动条jSlider事件处理    public void stateChanged(ChangeEvent ce) {    float alpha =((float) ((JSlider) ce.getSource()).getValue()) / 100;    displayPanel.alpha = alpha; //改变图像的透明    displayPanel.repaint(); //重绘displayPanel    }    g2d.drawImage(bufImage1, 0, 0, this); //在图形环境绘制缓冲区图像1    g2d.drawString("Destination",5,20); //绘制文字    int compositeRule = AlphaComposite.SRC_OVER; //源排斥目标法合成规则    AlphaComposite alphaComposite=AlphaComposite.getInstance(compositeRule,alpha); //创建AlphaComposite对象    g2d.setComposite(alphaComposite); //设置图形环境的合成方式    g2d.drawImage(bufImage2, 0, 0, this); //在图形环境绘制缓冲区图像2    g2d.drawString("Source",150,20); //绘制文字    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值