我怎么能用java像素化jpg?

我正在尝试使用Java 6对JPEG进行像素化并且没有太多运气。 它需要与Java相关 – 而不是像Photoshop这样的图像处理程序,它需要看起来像老学校 – 就像这样:

像素化图像

有谁能够帮我?

使用java.awt.image ( javadoc )和javax.imageio ( javadoc )API,您可以轻松地遍历图像的像素并自己执行像素化。

示例代码如下。 您至少需要这些导入: javax.imageio.ImageIOjava.awt.image.BufferedImagejava.awt.image.Rasterjava.awt.image.WritableRasterjava.io.File

例:

 // How big should the pixelations be? final int PIX_SIZE = 10; // Read the file as an Image img = ImageIO.read(new File("image.jpg")); // Get the raster data (array of pixels) Raster src = img.getData(); // Create an identically-sized output raster WritableRaster dest = src.createCompatibleWritableRaster(); // Loop through every PIX_SIZE pixels, in both x and y directions for(int y = 0; y < src.getHeight(); y += PIX_SIZE) { for(int x = 0; x < src.getWidth(); x += PIX_SIZE) { // Copy the pixel double[] pixel = new double[3]; pixel = src.getPixel(x, y, pixel); // "Paste" the pixel onto the surrounding PIX_SIZE by PIX_SIZE neighbors // Also make sure that our loop never goes outside the bounds of the image for(int yd = y; (yd < y + PIX_SIZE) && (yd < dest.getHeight()); yd++) { for(int xd = x; (xd < x + PIX_SIZE) && (xd < dest.getWidth()); xd++) { dest.setPixel(xd, yd, pixel); } } } } // Save the raster back to the Image img.setData(dest); // Write the new file ImageIO.write(img, "jpg", new File("image-pixelated.jpg")); 

编辑:我想我应该提一下 - 据我所知, double[] pixel只是RGB颜色值。 例如,当我转储一个像素时,它看起来像{204.0, 197.0, 189.0} ,浅棕褐色。

完成@bchociej的答案

我在像素中使用PIX_SIZE定义的区域的主色。 这不是一个完美的解决方案,但它会好一点。

这是一个例子:

原版的:
在此处输入图像描述

旧算法:
在此处输入图像描述

新算法:
在此处输入图像描述

代码示例

 import java.awt.*; import java.awt.image.BufferedImage; import java.util.*; import java.util.List; public final class ImageUtil { public static BufferedImage pixelate(BufferedImage imageToPixelate, int pixelSize) { BufferedImage pixelateImage = new BufferedImage( imageToPixelate.getWidth(), imageToPixelate.getHeight(), imageToPixelate.getType()); for (int y = 0; y < imageToPixelate.getHeight(); y += pixelSize) { for (int x = 0; x < imageToPixelate.getWidth(); x += pixelSize) { BufferedImage croppedImage = getCroppedImage(imageToPixelate, x, y, pixelSize, pixelSize); Color dominantColor = getDominantColor(croppedImage); for (int yd = y; (yd < y + pixelSize) && (yd < pixelateImage.getHeight()); yd++) { for (int xd = x; (xd < x + pixelSize) && (xd < pixelateImage.getWidth()); xd++) { pixelateImage.setRGB(xd, yd, dominantColor.getRGB()); } } } } return pixelateImage; } public static BufferedImage getCroppedImage(BufferedImage image, int startx, int starty, int width, int height) { if (startx < 0) startx = 0; if (starty < 0) starty = 0; if (startx > image.getWidth()) startx = image.getWidth(); if (starty > image.getHeight()) starty = image.getHeight(); if (startx + width > image.getWidth()) width = image.getWidth() - startx; if (starty + height > image.getHeight()) height = image.getHeight() - starty; return image.getSubimage(startx, starty, width, height); } public static Color getDominantColor(BufferedImage image) { Map colorCounter = new HashMap<>(100); for (int x = 0; x < image.getWidth(); x++) { for (int y = 0; y < image.getHeight(); y++) { int currentRGB = image.getRGB(x, y); int count = colorCounter.getOrDefault(currentRGB, 0); colorCounter.put(currentRGB, count + 1); } } return getDominantColor(colorCounter); } private static Color getDominantColor(Map colorCounter) { int dominantRGB = colorCounter.entrySet().stream() .max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1) .get() .getKey(); return new Color(dominantRGB); } } 

如何使用它

 img = ImageIO.read(new File("image.jpg")); BufferedImage imagePixelated = ImageUtil.pixelate(img, PIX_SIZE); ImageIO.write(imagePixelated, "jpg", new File("image-pixelated.jpg")); 

我手边没有代码,但如果您可以将图像大小调整为原始大小的1/4,则将其重新采样回原始大小,它应该可以解决问题。 大多数图像库都可以做到。

搜索“关闭Pixelate”项目,可能这就是您所需要的。

改进@ thibaut-mottet答案,因为我在’getDominantColor’方法上遇到编译器错误(’entry1’和’entry2’未定义)。

 import java.awt.Color; import java.awt.image.BufferedImage; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; public class ImageUtil { public static BufferedImage pixelate(BufferedImage imageToPixelate, int pixelSize) { BufferedImage pixelateImage = new BufferedImage( imageToPixelate.getWidth(), imageToPixelate.getHeight(), imageToPixelate.getType()); for (int y = 0; y < imageToPixelate.getHeight(); y += pixelSize) { for (int x = 0; x < imageToPixelate.getWidth(); x += pixelSize) { BufferedImage croppedImage = getCroppedImage(imageToPixelate, x, y, pixelSize, pixelSize); Color dominantColor = getDominantColor(croppedImage); for (int yd = y; (yd < y + pixelSize) && (yd < pixelateImage.getHeight()); yd++) { for (int xd = x; (xd < x + pixelSize) && (xd < pixelateImage.getWidth()); xd++) { pixelateImage.setRGB(xd, yd, dominantColor.getRGB()); } } } } return pixelateImage; } public static BufferedImage getCroppedImage(BufferedImage image, int startx, int starty, int width, int height) { if (startx < 0) startx = 0; if (starty < 0) starty = 0; if (startx > image.getWidth()) startx = image.getWidth(); if (starty > image.getHeight()) starty = image.getHeight(); if (startx + width > image.getWidth()) width = image.getWidth() - startx; if (starty + height > image.getHeight()) height = image.getHeight() - starty; return image.getSubimage(startx, starty, width, height); } public static Color getDominantColor(BufferedImage image) { Map colorCounter = new HashMap<>(100); for (int x = 0; x < image.getWidth(); x++) { for (int y = 0; y < image.getHeight(); y++) { int currentRGB = image.getRGB(x, y); int count = colorCounter.getOrDefault(currentRGB, 0); colorCounter.put(currentRGB, count + 1); } } return getDominantColor(colorCounter); } @SuppressWarnings("unchecked") private static Color getDominantColor(Map colorCounter) { int dominantRGB = colorCounter.entrySet().stream() .max(new EntryComparator()) .get() .getKey(); return new Color(dominantRGB); } } @SuppressWarnings("rawtypes") class EntryComparator implements Comparator { @SuppressWarnings("unchecked") @Override public int compare(Object o1, Object o2) { Entry entry1 = (Map.Entry) o1; Entry entry2 = (Map.Entry) o2; return (entry1.getValue() > entry2.getValue() ? 1 : -1); } } 

使用方式完全相同:

 img = ImageIO.read(new File("image.jpg")); BufferedImage imagePixelated = ImageUtil.pixelate(img, PIX_SIZE); ImageIO.write(imagePixelated, "jpg", new File("image-pixelated.jpg"));