2025年4月12日 星期六 乙巳(蛇)年 正月十三 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Java

图片马赛克处理(Java)

时间:03-22来源:作者:点击数:13
1.需求
  • 给图片的指定区域打码
  • 给整张图片打码
  • 马赛克方格取色支持中心点取色和随机取色
  • 马赛克支持灰度处理
2.源码
  • package com.visy.utils;
  • import javax.imageio.ImageIO;
  • import java.awt.*;
  • import java.awt.image.BufferedImage;
  • import java.io.File;
  • import java.io.IOException;
  • import java.io.InputStream;
  • import java.io.OutputStream;
  • import java.nio.file.Files;
  • import java.util.Random;
  • /**
  • * @author visy.wang
  • * @date 2024/9/19 9:56
  • */
  • public class ImageUtil {
  • /**
  • * 给图片指定区域打马赛克
  • * @param x 打码区域左上角的横坐标
  • * @param y 打码区域左上角的纵坐标
  • * @param width 打码区域的宽度
  • * @param height 打码区域的高度
  • * @param size 马赛克格子尺寸,即每个正方形小方格的边长
  • */
  • public static void mosaic(
  • InputStream source, OutputStream target, int x, int y, int width, int height, int size
  • ) throws IOException {
  • //读取该图片
  • BufferedImage image = ImageIO.read(source);
  • int imgWidth = image.getWidth(), imgHeight = image.getHeight();
  • System.out.println("原图片尺寸:"+imgWidth+"*"+imgHeight);
  • if(size<=0 || width==0 || height==0){
  • //不打马赛克,直接返回原图
  • ImageIO.write(image, "jpg", target);
  • return;
  • }
  • //马赛克区域边界值处理
  • width = width<0||width>imgWidth ? imgWidth : width;
  • height = height<0||height>imgHeight ? imgHeight : height;
  • //起点坐标<0处理
  • x = Math.max(x, 0);
  • y = Math.max(y, 0);
  • //马赛克块大小 不能大于图片宽度和高度,超过时取宽高中小的那一个
  • if (size > imgWidth || size > imgHeight) {
  • size = Math.min(imgWidth, imgHeight);
  • }
  • //创建一张画布(和原图同尺寸,颜色类型选择RGB)
  • BufferedImage canvas = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
  • //获得画布的画笔
  • Graphics gs = canvas.getGraphics();
  • //先将原图片画到画布上
  • gs.drawImage(image, 0, 0, null);
  • //计算横向和纵向绘制马赛克方格的个数
  • int xCount = width/size + (width%size==0 ? 0 : 1); //横绘绘制个数
  • int yCount = height/size + (height%size==0 ? 0 : 1); //纵向绘制个数
  • //遍历指定区域的所有方格并填充
  • int $x = x;//方格左上角x坐标
  • for (int i = 0; i < xCount; i++) {
  • int $y = y;//方格左上角y坐标
  • //方格的宽度,横向最后一个方格的宽需单独处理
  • int $width = i==xCount-1 ? (x+width-$x) : size;
  • for (int j = 0; j < yCount; j++) {
  • //方格的高度,纵向最后一个方格的高需单独处理
  • int $height = j==yCount-1 ? (y+height-$y) : size;
  • //颜色取方格中心像素点RGB值
  • //int rgb = getCenterRgb($x, $y, $width, $height, image);
  • //颜色取方格内随机像素点RGB值
  • int rgb = getRandomRgb($x, $y, $width, $height, image);
  • //设置颜色(灰度处理)
  • //Color color = new Color(toGray(rgb));
  • Color color = new Color(rgb);
  • //设置颜色
  • gs.setColor(color);
  • //填充方格
  • gs.fillRect($x, $y, $width, $height);
  • //方格加边框(用于测试)
  • //gs.setColor(Color.RED);
  • //gs.drawRect($x, $y, $width, $height);
  • $y += size;//计算下一个方格的左上角y坐标
  • }
  • $x += size;//计算下一行方格的左上角x坐标
  • }
  • gs.dispose(); //释放资源
  • ImageIO.write(canvas, "jpg", target); // 保存图片
  • }
  • /**
  • * 给整张图片打马赛克
  • * @param source 原图输入流
  • * @param target 打码后的图片输出流
  • * @param size 马赛克格子尺寸,即每个正方形小方格的边长
  • */
  • public static void mosaicAll(
  • InputStream source, OutputStream target, int size
  • ) throws IOException {
  • mosaic(source, target, 0, 0, -1, -1, size);
  • }
  • /**
  • * 获取马赛克小方格中心点的颜色
  • * @param x 小方格左上角横坐标
  • * @param y 小方格左上角纵坐标
  • * @param width 小方格的宽度
  • * @param height 小方格的高度
  • * @param image 原图
  • * @return 颜色RGB值
  • */
  • private static int getCenterRgb(int x, int y, int width, int height, BufferedImage image){
  • //计算当前方格中心点位置
  • int xCenterIndex = x + (width%2==0 ? width : width-1) / 2;
  • int yCenterIndex = y + (height%2==0 ? height : height-1) / 2;
  • //颜色取中心像素点RGB值
  • return image.getRGB(xCenterIndex, yCenterIndex);
  • }
  • /**
  • * 在马赛克小方格区域内随机取一个像素点的颜色
  • * @param x 小方格左上角横坐标
  • * @param y 小方格左上角纵坐标
  • * @param width 小方格的宽度
  • * @param height 小方格的高度
  • * @param image 原图
  • * @return 颜色RGB值
  • */
  • private static int getRandomRgb(int x, int y, int width, int height, BufferedImage image){
  • //在方格区域内随机取一个点的颜色
  • Random random = new Random();
  • int xIndex = x + random.nextInt(width);
  • int yIndex = y + random.nextInt(height);
  • return image.getRGB(xIndex, yIndex);
  • }
  • /**
  • * 彩色转换成黑白
  • * @param rgb 彩色RGB值
  • * @return 黑白RGB值
  • */
  • private static int toGray(int rgb){
  • int r = (rgb >> 16) & 0xFF;
  • int g = (rgb >> 8) & 0xFF;
  • int b = rgb & 0xFF;
  • // 计算灰度值
  • int gray = (r + g + b) / 3;
  • return (gray << 16) + (gray << 8) + gray;
  • }
  • /**
  • * 创建目标(输出)文件
  • * @param file 源文件
  • * @return 目标文件
  • */
  • private static File createTargetFile(File file){
  • String name = file.getName();
  • String newName = name.substring(0, name.lastIndexOf("."))+"_mosaic.jpg";
  • return new File(file.getParent(), newName);
  • }
  • public static void mosaic(File file, int x, int y, int width, int height, int size) throws IOException {
  • InputStream in = Files.newInputStream(file.toPath());
  • OutputStream out = Files.newOutputStream(createTargetFile(file).toPath());
  • mosaic(in, out, x, y, width, height, size);
  • }
  • public static void mosaicAll(File file, int size) throws IOException {
  • InputStream in = Files.newInputStream(file.toPath());
  • OutputStream out = Files.newOutputStream(createTargetFile(file).toPath());
  • mosaicAll(in, out, size);
  • }
  • public static void main(String[] args) throws IOException {
  • File f = new File("E:\\test\\imgs\\2d6aa7e497a059df30d635667b1ec998.jpeg");
  • //mosaic(f, 20 , 560, 500, 150, 10);
  • mosaic(f,370, 241, 370, 245, 15);
  • System.out.println("处理完成");
  • }
  • }
3.输入输出
  • 处理前
在这里插入图片描述
  • 处理后(中心点取色)
在这里插入图片描述
  • 处理后(灰度处理)
在这里插入图片描述
  • 处理后(随机取色)
在这里插入图片描述
在这里插入图片描述
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐