我正在尝试使用Java 6对JPEG进行像素化处理而没有太多运气。它需要与Java相关 - 而不是像Photoshop那样的图像处理程序,它需要看起来像老学校 - 就像这样:
有人能帮助我吗?
答案 0 :(得分:16)
使用java.awt.image
(javadoc)和javax.imageio
(javadoc)API,您可以轻松遍历图像的像素并自行执行像素化。
示例代码如下。您至少需要这些导入:javax.imageio.ImageIO
,java.awt.image.BufferedImage
,java.awt.image.Raster
,java.awt.image.WritableRaster
和java.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}
,浅棕褐色。
答案 1 :(得分:2)
完成@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<Integer, Integer> 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<Integer, Integer> 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"));
答案 2 :(得分:1)
我手边没有代码,但如果您可以将图像大小调整为原始大小的1/4,那么将其重新取样回原始大小应该可以解决问题。大多数图像库都可以做到这一点。
答案 3 :(得分:0)
搜索“关闭Pixelate”项目,可能这就是您所需要的。
答案 4 :(得分:0)
改进@ 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<Integer, Integer> 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<Integer, Integer> 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<Integer, Integer> entry1 = (Map.Entry<Integer, Integer>) o1;
Entry<Integer, Integer> entry2 = (Map.Entry<Integer, Integer>) 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"));
答案 5 :(得分:0)
我在Thibaut Mottet的答案中修改了dominantColor函数,因此它代替了最常见的颜色,返回该像素的平均RGB
原文:
public static Color getDominantColor(BufferedImage image) {
int sumR = 0, sumB = 0, sumG = 0, int sum2 = 0;
int color = 0;
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
color = image.getRGB(x, y);
Color c = new Color(color);
sumR += c.getRed();
sumB += c.getBlue();
sumG += c.getGreen();
sum2++;
}
}
return new Color(sumR/sum2, sumG/sum2, sumB/sum2);