【问题标题】:Graphics fill rect overflow into new rects?图形将矩形溢出填充到新的矩形中?
【发布时间】:2018-11-14 23:38:40
【问题描述】:

我正在尝试制作一个简单的程序来“像素化”图像。 (使它们看起来像 8 位图)。基本上它的工作原理是它循环遍历给定目录中的图像,要求新“像素”大小的宽度百分比,然后“像素化”图像。它通过循环遍历每个新“像素”并找到该正方形区域的平均颜色并将其保存到 2D 颜色数组来实现这一点。然后它遍历 2D 数组并在正确“像素”大小的新图像上绘制矩形。

我在某些像素中遇到了透明度问题,这很重要,因为我希望能够处理具有透明背景的 PNG 文件。这是之前和之后的图片的样子: Before 和 After。显然,居中图像之后的像素应该仍然是透明的。我观察了每个“像素”的颜色,它表明有些是透明的,即使它们在图片的右下角被填充为黑色。这是我的全班:

package pixelator;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;

import javax.imageio.ImageIO;

public class Pixelator {

public static void main(String[] args) throws IOException{
    Scanner scan = new Scanner(System.in);

    File folder = new File(args[0]);

    File[] files = folder.listFiles();

    if(files.length == 0) {
        System.out.println("No files in given directory.");
    }

    for(int i = 0; i < files.length; i ++) {
        if(filterFile(files[i])) {
            BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
            img = ImageIO.read(files[i]);
            System.out.println("File: " + files[i].getName());
            System.out.print("Enter pixelated size percentage(out of 100): ");
            double percent = scan.nextDouble();

            img = pixelate(img, percent);

            File toWrite = new File(args[1] + "\\pixelated_" + files[i].getName());
            ImageIO.write(img, files[i].getName().substring(files[i].getName().indexOf(".") + 1, files[i].getName().length()), toWrite);
            System.out.println("New image saved");
        }
    }



}

/**
 * returns a pixelated version of the original image with the pixels being the given percent
 * if the image's size. Compensates for size of image.
 * @param img
 * @param percent
 * @return BufferedImage
 */
public static BufferedImage pixelate(BufferedImage img, double percent) {
    //find the number of pixels in the new "pixel"
    int newPixelSize = (int)((percent/100.0) * img.getWidth());

    int width = newPixelSize * (img.getWidth() / newPixelSize);
    int height = newPixelSize * (img.getHeight() / newPixelSize);

    System.out.println("Old Width: " + img.getWidth() + "\nOld Height: " + img.getHeight());
    System.out.println("New pixel size: " + newPixelSize + "\nNew Width: " + width + "\nnew Height: " + height);


    BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

    Color[][] pixelArray = new Color[height / newPixelSize][width / newPixelSize];
    for(int i = 0; i < pixelArray.length; i ++) {
        for(int j = 0; j < pixelArray[0].length; j ++) {
            pixelArray[i][j] = findColorAtPixelCoordinates(i, j, newPixelSize, img);
        }
    }

    for(int i = 0; i < pixelArray.length; i ++) {
        for(int j = 0; j < pixelArray[0].length; j ++) {
            newImage = setNewImagePixel(i, j, newPixelSize, newImage, pixelArray[i][j]);
        }
    }

    return newImage;
}

/**
 * gets the average color over a certain rectangle on the original image
 * @param y
 * @param x
 * @param pixelSize
 * @param img
 * @return
 */
public static Color findColorAtPixelCoordinates(int y, int x, int pixelSize, BufferedImage img) {
    int[] averageARGB = {0, 0, 0, 0};

    x = x * pixelSize;
    y = y * pixelSize;

    //loop through a certain "pixel" contained in the img, adding all of the values to the array
    for(int i = y; i < y + pixelSize; i ++) {
        for(int j = x; j < x + pixelSize; j++) {
            Color colorAtPixel = new Color(img.getRGB(j, i), true);
            averageARGB[0] += colorAtPixel.getRed();
            averageARGB[1] += colorAtPixel.getGreen();
            averageARGB[2] += colorAtPixel.getBlue();
            averageARGB[3] += colorAtPixel.getAlpha();
        }
    }

    //calculate the averages
    averageARGB[0] = averageARGB[0] / (pixelSize * pixelSize);
    averageARGB[1] = averageARGB[1] / (pixelSize * pixelSize);
    averageARGB[2] = averageARGB[2] / (pixelSize * pixelSize);
    averageARGB[3] = averageARGB[3] / (pixelSize * pixelSize);

    return new Color(averageARGB[0], averageARGB[1], averageARGB[2], averageARGB[3]);
}

/**
 * sets a new "pixel" rectangle for the new image. Also prints out each new "pixels: coordinates and color
 * for testing
 * @param y
 * @param x
 * @param pixelSize
 * @param newImage
 * @param color
 * @return
 */
public static BufferedImage setNewImagePixel(int y, int x, int pixelSize, BufferedImage newImage, Color color) {
    System.out.println("Row: "+ y + ", Column: " + x + ", Color: [" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ", " + color.getAlpha()+"]");
    x = x * pixelSize;
    y = y * pixelSize;

    // get the graphics then fill the rect with the right color 
    Graphics2D g = (Graphics2D) newImage.getGraphics();
    g.setColor(color);
    g.fillRect(x, y, x + pixelSize, y + pixelSize);


    return newImage;
}

/**
 * return true if the image is a png or jpg file
 * @param fileName
 * @return boolean
 */
public static boolean filterFile(File fileName) {
    //System.out.println(fileName.substring(fileName.indexOf("."), fileName.length())); 
    if(!fileName.isFile()) {
        return false;
    }

    return fileName.getName().substring(fileName.getName().indexOf("."), fileName.getName().length()).equals(".jpg") || 
            fileName.getName().substring(fileName.getName().indexOf("."), fileName.getName().length()).equals(".jpeg") || 
            fileName.getName().substring(fileName.getName().indexOf("."), fileName.getName().length()).equals(".png");
}


}

感谢您提供的任何帮助!

【问题讨论】:

  • 获取图像的一种方法是热链接到在this Q&A 中看到的图像。例如。 This answer 指向嵌入在 this question 中的图像的热链接。
  • 在findColorAtPixelCoordinates 中循环i,j 但不要在循环体中使用这些变量。这是一个明显的错误。但它可能不会导致您的主要错误。
  • 刚刚修复了这个错误,除了让它更模糊(这是意料之中的)之外并没有改变很多。不幸的是,没有解决主要错误。我也不能发布图片,因为我的声誉是 1 大声笑。
  • “刚刚修复了那个错误..” 提示:添加@CrisLuengo(或@ 很重要的任何人)以通知此人的新评论。

标签: java image image-processing


【解决方案1】:

你做错的第一件事是函数setNewImagePixel:

g.fillRect(x, y, x+pixelSize, y+pixelSize);

您提供的是右下角,而不是提供宽度和高度,因此请使用它进行更正

g.fillRect(x, y, pixelSize, pixelSize);

另一件事是你不应该平均函数 findColorAtPixelCoordinates 中的 alpha 分量。你应该写成

Color color = new Color(img.getRGB(x, y), true);
averageARGB[3] = color.getAlpha();

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多