本文目录导读:

我来为您提供一个完整的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);
}
}
功能特点
- 基础马赛克:获取块中心像素颜色并填充整个块
- 高级马赛克:计算块内所有像素的平均颜色,效果更平滑
- 可配置参数:起始位置、大小、块大小均可调整
- GUI界面:提供友好的图形界面操作
- 错误处理:完善的边界检查和异常处理
这个实现涵盖了马赛克的核心功能,可以根据实际需求调整块大小和位置,实现不同程度的马赛克效果。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播