如何用Java案例实现图片马赛克?

wen java案例 2

本文目录导读:

如何用Java案例实现图片马赛克?

  1. 基础马赛克实现
  2. 改进版马赛克(使用像素平均值)
  3. 完整的测试类
  4. 使用方法
  5. 功能特点

我来为您提供一个完整的Java图片马赛克实现方案。

基础马赛克实现

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageMosaicTool {
    /**
     * 给图片添加马赛克效果
     * @param sourcePath 源图片路径
     * @param outputPath 输出图片路径
     * @param startX 马赛克区域起始X坐标
     * @param startY 马赛克区域起始Y坐标
     * @param width 马赛克区域宽度
     * @param height 马赛克区域高度
     * @param blockSize 马赛克块大小
     */
    public static void addMosaic(String sourcePath, String outputPath, 
                                  int startX, int startY, 
                                  int width, int height, 
                                  int blockSize) throws IOException {
        // 读取原始图片
        File inputFile = new File(sourcePath);
        BufferedImage originalImage = ImageIO.read(inputFile);
        // 获取图片尺寸
        int imageWidth = originalImage.getWidth();
        int imageHeight = originalImage.getHeight();
        // 创建新图片
        BufferedImage resultImage = new BufferedImage(
            imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = resultImage.createGraphics();
        g2d.drawImage(originalImage, 0, 0, null);
        // 计算马赛克区域
        int endX = Math.min(startX + width, imageWidth);
        int endY = Math.min(startY + height, imageHeight);
        // 应用马赛克效果
        for (int y = startY; y < endY; y += blockSize) {
            for (int x = startX; x < endX; x += blockSize) {
                // 计算当前块的边界
                int blockEndX = Math.min(x + blockSize, endX);
                int blockEndY = Math.min(y + blockSize, endY);
                // 获取块中心点的颜色
                int centerX = x + blockSize / 2;
                int centerY = y + blockSize / 2;
                // 边界检查
                centerX = Math.min(centerX, imageWidth - 1);
                centerY = Math.min(centerY, imageHeight - 1);
                int pixelColor = originalImage.getRGB(centerX, centerY);
                // 将该块所有像素设为相同颜色
                for (int by = y; by < blockEndY; by++) {
                    for (int bx = x; bx < blockEndX; bx++) {
                        resultImage.setRGB(bx, by, pixelColor);
                    }
                }
            }
        }
        g2d.dispose();
        // 保存结果
        String format = outputPath.substring(outputPath.lastIndexOf(".") + 1);
        ImageIO.write(resultImage, format, new File(outputPath));
        System.out.println("马赛克处理完成!");
    }
}

改进版马赛克(使用像素平均值)

/**
 * 改进版马赛克 - 使用块内像素平均值
 */
public static void addMosaicAdvanced(String sourcePath, String outputPath, 
                                      int startX, int startY, 
                                      int width, int height, 
                                      int blockSize) throws IOException {
    File inputFile = new File(sourcePath);
    BufferedImage originalImage = ImageIO.read(inputFile);
    int imageWidth = originalImage.getWidth();
    int imageHeight = originalImage.getHeight();
    BufferedImage resultImage = new BufferedImage(
        imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = resultImage.createGraphics();
    g2d.drawImage(originalImage, 0, 0, null);
    int endX = Math.min(startX + width, imageWidth);
    int endY = Math.min(startY + height, imageHeight);
    for (int y = startY; y < endY; y += blockSize) {
        for (int x = startX; x < endX; x += blockSize) {
            int blockEndX = Math.min(x + blockSize, endX);
            int blockEndY = Math.min(y + blockSize, endY);
            // 计算块内像素平均值
            long sumRed = 0, sumGreen = 0, sumBlue = 0;
            int pixelCount = 0;
            for (int by = y; by < blockEndY; by++) {
                for (int bx = x; bx < blockEndX; bx++) {
                    Color pixelColor = new Color(originalImage.getRGB(bx, by));
                    sumRed += pixelColor.getRed();
                    sumGreen += pixelColor.getGreen();
                    sumBlue += pixelColor.getBlue();
                    pixelCount++;
                }
            }
            // 计算平均色
            int avgRed = (int)(sumRed / pixelCount);
            int avgGreen = (int)(sumGreen / pixelCount);
            int avgBlue = (int)(sumBlue / pixelCount);
            Color avgColor = new Color(avgRed, avgGreen, avgBlue);
            // 应用平均色
            for (int by = y; by < blockEndY; by++) {
                for (int bx = x; bx < blockEndX; bx++) {
                    resultImage.setRGB(bx, by, avgColor.getRGB());
                }
            }
        }
    }
    g2d.dispose();
    String format = outputPath.substring(outputPath.lastIndexOf(".") + 1);
    ImageIO.write(resultImage, format, new File(outputPath));
}

完整的测试类

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
public class MosaicDemo extends JFrame {
    private JTextField sourcePathField;
    private JTextField outputPathField;
    private JSpinner blockSizeSpinner;
    private JSpinner startXSpinner;
    private JSpinner startYSpinner;
    private JSpinner widthSpinner;
    private JSpinner heightSpinner;
    public MosaicDemo() {
        setTitle("图片马赛克工具");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        // 源文件选择
        gbc.gridx = 0; gbc.gridy = 0;
        add(new JLabel("源图片路径:"), gbc);
        gbc.gridx = 1;
        sourcePathField = new JTextField(30);
        add(sourcePathField, gbc);
        gbc.gridx = 2;
        JButton browseButton = new JButton("浏览");
        browseButton.addActionListener(e -> chooseFile(sourcePathField));
        add(browseButton, gbc);
        // 输出文件路径
        gbc.gridx = 0; gbc.gridy = 1;
        add(new JLabel("输出图片路径:"), gbc);
        gbc.gridx = 1;
        outputPathField = new JTextField(30);
        add(outputPathField, gbc);
        // 马赛克参数
        gbc.gridx = 0; gbc.gridy = 2;
        add(new JLabel("马赛克块大小:"), gbc);
        gbc.gridx = 1;
        blockSizeSpinner = new JSpinner(new SpinnerNumberModel(10, 2, 50, 1));
        add(blockSizeSpinner, gbc);
        gbc.gridx = 0; gbc.gridy = 3;
        add(new JLabel("起始X坐标:"), gbc);
        gbc.gridx = 1;
        startXSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 2000, 10));
        add(startXSpinner, gbc);
        gbc.gridx = 0; gbc.gridy = 4;
        add(new JLabel("起始Y坐标:"), gbc);
        gbc.gridx = 1;
        startYSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 2000, 10));
        add(startYSpinner, gbc);
        gbc.gridx = 0; gbc.gridy = 5;
        add(new JLabel("马赛克宽度:"), gbc);
        gbc.gridx = 1;
        widthSpinner = new JSpinner(new SpinnerNumberModel(200, 10, 2000, 10));
        add(widthSpinner, gbc);
        gbc.gridx = 0; gbc.gridy = 6;
        add(new JLabel("马赛克高度:"), gbc);
        gbc.gridx = 1;
        heightSpinner = new JSpinner(new SpinnerNumberModel(200, 10, 2000, 10));
        add(heightSpinner, gbc);
        // 处理按钮
        gbc.gridx = 0; gbc.gridy = 7; gbc.gridwidth = 3;
        JButton processButton = new JButton("处理图片");
        processButton.addActionListener(e -> processImage());
        processButton.setPreferredSize(new Dimension(200, 40));
        add(processButton, gbc);
        pack();
        setLocationRelativeTo(null);
    }
    private void chooseFile(JTextField textField) {
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            textField.setText(fileChooser.getSelectedFile().getAbsolutePath());
        }
    }
    private void processImage() {
        try {
            String sourcePath = sourcePathField.getText();
            String outputPath = outputPathField.getText();
            if (sourcePath.isEmpty() || outputPath.isEmpty()) {
                JOptionPane.showMessageDialog(this, "请选择源文件和输出路径!");
                return;
            }
            int blockSize = (int) blockSizeSpinner.getValue();
            int startX = (int) startXSpinner.getValue();
            int startY = (int) startYSpinner.getValue();
            int width = (int) widthSpinner.getValue();
            int height = (int) heightSpinner.getValue();
            // 使用改进版马赛克
            ImageMosaicTool.addMosaicAdvanced(
                sourcePath, outputPath, startX, startY, width, height, blockSize
            );
            JOptionPane.showMessageDialog(this, "图片处理完成!");
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, 
                "处理失败:" + ex.getMessage(), 
                "错误", 
                JOptionPane.ERROR_MESSAGE);
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new MosaicDemo().setVisible(true);
        });
    }
}

使用方法

// 命令行使用方式
public class Main {
    public static void main(String[] args) {
        try {
            // 基本用法
            ImageMosaicTool.addMosaic(
                "input.jpg",           // 源图片
                "output.jpg",          // 输出图片
                100, 100,              // 起始位置 (x, y)
                300, 200,              // 马赛克区域大小 (宽, 高)
                15                     // 马赛克块大小
            );
            // 高级用法(使用像素平均)
            ImageMosaicTool.addMosaicAdvanced(
                "input.jpg",
                "output.jpg",
                100, 100,
                300, 200,
                15
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 启动GUI界面
        // MosaicDemo.main(args);
    }
}

功能特点

  1. 基础马赛克:获取块中心像素颜色并填充整个块
  2. 高级马赛克:计算块内所有像素的平均颜色,效果更平滑
  3. 可配置参数:起始位置、大小、块大小均可调整
  4. GUI界面:提供友好的图形界面操作
  5. 错误处理:完善的边界检查和异常处理

这个实现涵盖了马赛克的核心功能,可以根据实际需求调整块大小和位置,实现不同程度的马赛克效果。

抱歉,评论功能暂时关闭!