311 lines
11 KiB
Java
311 lines
11 KiB
Java
package com.shenghua.utils;
|
|
|
|
|
|
import java.awt.*;
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.util.*;
|
|
import java.util.List;
|
|
|
|
public class EliminateImageUtil {
|
|
|
|
/**
|
|
* 坐标嘞
|
|
*/
|
|
private static class Coordinate {
|
|
private int x;
|
|
|
|
private int y;
|
|
|
|
public Coordinate(int x, int y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
public int getX() {
|
|
return x;
|
|
}
|
|
|
|
public void setX(int x) {
|
|
this.x = x;
|
|
}
|
|
|
|
public int getY() {
|
|
return y;
|
|
}
|
|
|
|
public void setY(int y) {
|
|
this.y = y;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
Coordinate that = (Coordinate) o;
|
|
return x == that.x &&
|
|
y == that.y;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(x, y);
|
|
}
|
|
|
|
}
|
|
|
|
private static class CoordinateWithCenter extends Coordinate implements Comparable<CoordinateWithCenter> {
|
|
|
|
private Coordinate center;
|
|
|
|
private int distance;
|
|
|
|
public int getDistance() {
|
|
return distance;
|
|
}
|
|
|
|
public void setDistance(int distance) {
|
|
this.distance = distance;
|
|
}
|
|
|
|
public CoordinateWithCenter(int x, int y) {
|
|
super(x,y);
|
|
this.center = new Coordinate(0,0);
|
|
}
|
|
public CoordinateWithCenter(int x, int y,Coordinate center) {
|
|
super(x,y);
|
|
this.center = center;
|
|
this.distance = Math.abs(this.getX()-center.getX())+Math.abs(this.getY()-center.getY());
|
|
}
|
|
@Override
|
|
public int compareTo(CoordinateWithCenter o) {
|
|
//负整数是小于
|
|
//0为等于
|
|
return Integer.compare(o.distance, this.distance); //正整数是大于
|
|
}
|
|
}
|
|
|
|
private static int RANGE = 5;
|
|
private static int WEIGHT = 1;
|
|
|
|
|
|
public static String imageEliminate(String primaryBase64,String eraseBase64){
|
|
BufferedImage bufferedImage = ImageUtil.bufferedImage(primaryBase64);
|
|
BufferedImage bufferedMask = ImageUtil.bufferedImage(eraseBase64);
|
|
/*获取涂抹中心区域*/
|
|
Coordinate wipeCenter = getWipeCenter(bufferedMask);
|
|
/* 被涂抹的坐标,需要处理 */
|
|
List<CoordinateWithCenter> coordinateWithCenters = getWipeCoordinate(bufferedMask, wipeCenter);
|
|
|
|
System.out.println("大小:"+bufferedImage.getWidth() + "x" + bufferedImage.getHeight());
|
|
//平均颜色
|
|
Color colorAvg = getBorderAvgColor(bufferedImage, bufferedMask);
|
|
//Color colorAvg = getMostColor(bufferedImage,bufferedMask);
|
|
//已处理的坐标
|
|
Set<Coordinate> hasDoneSet = new HashSet<>();
|
|
for (CoordinateWithCenter c : coordinateWithCenters) {
|
|
/* 获取像素点周围平均像素点 */
|
|
Color color = getAvgColor(bufferedImage, bufferedMask, c.getX(), c.getY(),colorAvg,hasDoneSet);
|
|
bufferedImage.setRGB(c.getX(), c.getY(), color.getRGB());
|
|
Coordinate coordinate = new Coordinate(c.getX(), c.getY());
|
|
hasDoneSet.add(coordinate);
|
|
}
|
|
return ImageUtil.imageToBase64(bufferedImage);
|
|
}
|
|
|
|
private static List<CoordinateWithCenter> getWipeCoordinate(BufferedImage bufferedMask, Coordinate wipeCenter) {
|
|
List<CoordinateWithCenter> list = new ArrayList<>();
|
|
int height = bufferedMask.getHeight();
|
|
int width = bufferedMask.getWidth();
|
|
for (int j = 0; j < height; j++) {
|
|
for (int i = 0; i < width; i++) {
|
|
if (bufferedMask.getRGB(i, j) != -1) {
|
|
list.add(new CoordinateWithCenter(i, j, wipeCenter));
|
|
}
|
|
}
|
|
}
|
|
Collections.sort(list);
|
|
return list;
|
|
}
|
|
|
|
/***
|
|
*获取周围的像素点的平均像素
|
|
* @param bufferedImage
|
|
* @param bufferedMask
|
|
* @param x 像素点坐标x
|
|
* @param y 像素点坐标y
|
|
* @param colorAvg 填充颜色
|
|
* @return
|
|
*/
|
|
private static Color getAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask, int x, int y, Color colorAvg,Set<Coordinate> hasDoneSet) {
|
|
int count = 0;
|
|
int aRed = 0, aBlue = 0, aGreen = 0;
|
|
|
|
for (int a = x - RANGE; a < x + RANGE; a++) {
|
|
for (int b = y - RANGE; b < y + RANGE; b++) {
|
|
//越界
|
|
if (a <= 0 || a > (bufferedImage.getWidth() - 1)
|
|
|| b < 0 || b > (bufferedImage.getHeight() - 1)
|
|
|| (a == x && b == y)) {
|
|
continue;
|
|
}
|
|
//没涂抹的区域,或者已经处理过
|
|
if (bufferedMask.getRGB(a, b) == -1 ||hasDoneSet.contains(new Coordinate(a, b))) {
|
|
int ragb = bufferedImage.getRGB(a, b);
|
|
Color color = new Color(ragb, true);
|
|
int blue = color.getBlue();
|
|
int red = color.getRed();
|
|
int green = color.getGreen();
|
|
aRed = aRed + red * WEIGHT;
|
|
aBlue = aBlue + blue * WEIGHT;
|
|
aGreen = aGreen + green * WEIGHT;
|
|
count = count + WEIGHT;
|
|
}
|
|
}
|
|
}
|
|
if (count == 0) {
|
|
|
|
return colorAvg;
|
|
}
|
|
|
|
return new Color(aRed / count, aGreen / count, aBlue / count);
|
|
}
|
|
|
|
/***
|
|
* 获取掩码涂抹的中心位置
|
|
* @param bufferedMask 掩码图
|
|
* @return 返回中心坐标
|
|
*/
|
|
private static Coordinate getWipeCenter(BufferedImage bufferedMask) {
|
|
int width = bufferedMask.getWidth();
|
|
int height = bufferedMask.getHeight();
|
|
int top = height - 1, bottom = 0, left = height - 1, right = 0;
|
|
for (int j = 0; j < height; j++) {
|
|
for (int i = 0; i < width; i++) {
|
|
if (bufferedMask.getRGB(i, j) != -1) {
|
|
right = Math.max(right, i);
|
|
left = Math.min(left, i);
|
|
bottom = Math.max(bottom, j);
|
|
top = Math.min(top, j);
|
|
}
|
|
}
|
|
}
|
|
return new Coordinate((left + right) / 2, (top + bottom) / 2);
|
|
}
|
|
|
|
/***
|
|
* 获取掩码未涂抹的平均颜色,如果全部涂抹,返回整个图的平均颜色,用于填充涂抹区域
|
|
* @param bufferedImage 原图
|
|
* @param bufferedMask 掩码图
|
|
* @return 返回平均颜色
|
|
*/
|
|
private static Color getAllAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
|
|
int aRed = 0, aBlue = 0, aGreen = 0, count = 0, bRed = 0, bBlue = 0, bGreen = 0;
|
|
int width = bufferedMask.getWidth();
|
|
int height = bufferedMask.getHeight();
|
|
for (int j = 0; j < height; j++) {
|
|
for (int i = 0; i < width; i++) {
|
|
int ragb = bufferedImage.getRGB(i, j);
|
|
Color color = new Color(ragb, true);
|
|
if (bufferedMask.getRGB(i, j) == -1) {//未被涂抹区域
|
|
aRed = aRed + color.getRed();
|
|
aBlue = aBlue + color.getBlue();
|
|
aGreen = aGreen + color.getGreen();
|
|
count++;
|
|
}
|
|
bRed = bRed + color.getRed();
|
|
bBlue = bBlue + color.getBlue();
|
|
bGreen = bGreen + color.getGreen();
|
|
}
|
|
}
|
|
//全部涂抹
|
|
if (count == 0) {
|
|
count = width*height;
|
|
return new Color(bRed / count, bGreen / count, bBlue / count);
|
|
} else {
|
|
return new Color(aRed / count, aGreen / count, aBlue / count);
|
|
}
|
|
}
|
|
|
|
|
|
/***
|
|
* 获取边界平均颜色
|
|
* @param bufferedImage
|
|
* @param bufferedMask
|
|
* @return
|
|
*/
|
|
private static Color getBorderAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
|
|
int aRed = 0, aBlue = 0, aGreen = 0, count = 0, bRed = 0, bBlue = 0, bGreen = 0;
|
|
Set<Coordinate> coordinates = new HashSet<>();
|
|
int width = bufferedMask.getWidth();
|
|
int height = bufferedMask.getHeight();
|
|
for (int j = 0; j < height; j++) {
|
|
for (int i = 0; i < width; i++) {
|
|
int ragb = bufferedImage.getRGB(i, j);
|
|
Color color = new Color(ragb, true);
|
|
if (bufferedMask.getRGB(i,j)==-1){//没被涂抹
|
|
for (int a = i - 1; a < i + 1; a++) {
|
|
for (int b = j - 1; b < j + 1; b++) {
|
|
//越界
|
|
if (a <= 0 || a > (bufferedImage.getWidth() - 1)
|
|
|| b < 0 || b > (bufferedImage.getHeight() - 1)
|
|
|| (a == i && b == j)) {
|
|
continue;
|
|
}
|
|
if (bufferedMask.getRGB(a,b)!=-1) {//是边界点
|
|
if (coordinates.add(new Coordinate(i,j))) {
|
|
aRed = aRed + color.getRed();
|
|
aBlue = aBlue + color.getBlue();
|
|
aGreen = aGreen + color.getGreen();
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bRed = bRed + color.getRed();
|
|
bBlue = bBlue + color.getBlue();
|
|
bGreen = bGreen + color.getGreen();
|
|
}
|
|
}
|
|
//全部涂抹
|
|
if (coordinates.size() == 0) {//全部涂抹,取平均色
|
|
count = width*height;
|
|
return new Color(bRed / count, bGreen / count, bBlue / count);
|
|
} else {
|
|
return new Color(aRed / count, aGreen / count, aBlue / count);
|
|
}
|
|
}
|
|
|
|
/***
|
|
* 获取颜色最多的
|
|
* @param bufferedImage 原图
|
|
* @param bufferedMask 掩码图
|
|
* @return 返回最多的颜色
|
|
*/
|
|
private static Color getMostColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
|
|
int countArgb = 0, retArgb = 0;
|
|
int width = bufferedMask.getWidth();
|
|
int height = bufferedMask.getHeight();
|
|
HashMap<Integer, Integer> map = new HashMap();
|
|
for (int j = 0; j < height; j++) {
|
|
for (int i = 0; i < width; i++) {
|
|
if (bufferedMask.getRGB(i, j) == -1) {//未被涂抹区域
|
|
int ragb = bufferedImage.getRGB(i, j);
|
|
map.put(ragb, map.get(ragb) == null ? 0 : map.get(ragb) + 1);
|
|
}
|
|
}
|
|
}
|
|
for (Integer key : map.keySet()) {
|
|
if (map.get(key) > countArgb) {
|
|
countArgb = map.get(key);
|
|
retArgb = key;
|
|
}
|
|
}
|
|
return new Color(retArgb);
|
|
}
|
|
|
|
|
|
}
|