自学内容网 自学内容网

图片马赛克处理(Java)

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.输入输出
  • 处理前

在这里插入图片描述

  • 处理后(中心点取色)

在这里插入图片描述

  • 处理后(灰度处理)

在这里插入图片描述

  • 处理后(随机取色)

在这里插入图片描述
在这里插入图片描述


原文地址:https://blog.csdn.net/xhom_w/article/details/142380585

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!