如何更改存储为二维像素阵列的彩色图像的对比度和亮度

时间:2017-11-24 11:52:46

标签: java image image-processing

我将图像存储为像素值的二维数组。我想更改图像的对比度和亮度,然后将更改的像素图像存储为图像,然后在JFrame中显示原始图像和更改的图像。所以我的问题的基本步骤是:

  1. 将图像转换为二维像素阵列(因此我可以更改像素值)
  2. 更改图像的对比度和亮度
  3. 将改变的像素阵列转换为图像(最好是BufferedImage)
  4. 在JFrame中显示原始图像和更改的图像
  5. 我可以做第4步没问题,我想我也正在做第1步。然而,我无法工作的是第2步和第3步。我尝试过不同的方法,但总是会出现非常扭曲的图像。只是将图像转换为像素阵列然后再次返回图像(不改变像素值)会在不应该的情况下产生非常扭曲的图像。请看下面的图片。 enter image description here

    这是一个学校作业,所以我们必须自己实现这个功能(改变对比度和亮度),否则我会使用一些类似question建议的内置函数。

    任何可以提供帮助的人?在此先感谢您的帮助!

    我的代码

    我已将每一步(第4步除外)放在一个单独的方法中,以便更容易阅读和理解。

    图片 - >二维像素阵列

    /**
     * converts an image to a 2 dimensional pixel-array
     */
    public static int[][] imageToPixelArray() throws IOException {
        File file = new File(filename);
        imageOriginal = ImageIO.read(file);
        Raster raster = imageOriginal.getData();
        int width = raster.getWidth();
        int height = raster.getHeight();
        pixels = new int[width][height];
    
        sampleModel = raster.getSampleModel();
        int color = 3;
    
        for(int i = 0; i < width; i++) {
            for(int j = 0; j < height; j++) {
                for(int c = 0; c < color; c++) {
                    pixels[i][j] = raster.getSample(i, j, c);
                }
            }
        }
        return pixels;
    }
    

    更改像素值

    public static int[][] compute(int[][] pixels) {
        contrast = 20;
        brightness = 20;
        for(int i = 0;  i < pixels.length; i++) {
            for(int j = 0; j < pixels[i].length; j++) {
                pixels[i][j] = pixels[i][j] * contrast + brightness;
            }
        }
        return pixels;
    }
    

    2维pixelarray - &gt;图片

    /**
     * converts a 2 dimensional pixel-array to an image
     */
    public static BufferedImage pixelArrayToImage(int[][] pixels) {
        int width = pixels.length;
        int height = pixels[0].length;
        WritableRaster raster = Raster.createWritableRaster(sampleModel, new Point(0, 0));
    
        for(int i = 0; i < width; i++) {
            for(int j = 0; j < height; j++) {
                raster.setSample(i, j, 0, pixels[i][j]);
            }
        }
    
        imageAltered = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        imageAltered.setData(raster);
        return imageAltered;
    }
    

2 个答案:

答案 0 :(得分:1)

您的整个代码没有意义。我不会谈论语法,因为我的Java非常生疏,我不会给你一个解决方案,因为这会损害你的学习经验。但我会指出一些事情。

for(int i = 0; i < width; i++) {
  for(int j = 0; j < height; j++) {
     for(int c = 0; c < color; c++) {
        pixels[i][j] = raster.getSample(i, j, c);
     }
  }
}

为什么要将一行中的三个不同值分配给同一个整数pixels[i][j]?您可以使用另一个数组来存储每个像素的三个值,也可以找到一些其他方法来编码rgb信息。

public static int[][] compute(int[][] pixels) {
    contrast = 20;
    brightness = 20;
    for(int i = 0;  i < pixels.length; i++) {
        for(int j = 0; j < pixels[i].length; j++) {
            pixels[i][j] = pixels[i][j] * contrast + brightness;
        }
    }
    return pixels;
}

你是如何提出pixels[i][j] = pixels[i][j] * contrast + brightness;的? 这不会改变对比度,只需使图像更亮。对比不是全球因素。我认为您需要掌握一些关于数字图像,结构和值以及最少图像处理术语的基本知识。

如果您将rgb图像缩小为单个频道,则会丢弃无法获取的信息。不幸的是,你并没有真正描述你想要达到的目标,所以我不能给你很多建议。但是你的代码是无稽之谈。

答案 1 :(得分:0)

我设法解决了我的问题(并在此过程中缩短了我的代码)!我的代码通过生成由间隔给出的随机值来改变亮度和对比度。

如果其他人遇到同样的问题,这是代码:)

/**
 * alter the image´s contrast and brightness
 * @throws IOException
 */
public void alterImage() throws IOException {
    imageAltered = new BufferedImage(imageOriginal.getWidth(), imageOriginal.getHeight(), BufferedImage.TYPE_INT_RGB);
    brightness = rand.nextInt(150 + 200 + 1) - 200; //values from 150 to 200
    contrast = 1.5 + (5.0 - 1.5) * rand.nextDouble(); //values from 1.5 to 5.0

    for(int i = 0; i < imageOriginal.getWidth(); i++) {
        for(int j = 0; j < imageOriginal.getHeight(); j++) {
            Color c = new Color(imageOriginal.getRGB(i, j));
            int red = (int) contrast * c.getRed() + brightness;
            int green = (int) contrast * c.getGreen() + brightness;
            int blue = (int) contrast * c.getBlue() + brightness;

            if(red > 255) { // the values of the color components must be between 0-255
                red = 255;
            } else if(red < 0) {
                red = 0;
            }
            if(green > 255) {
                green = 255;
            } else if(green < 0) {
                green = 0;
            }
            if(blue > 255) {
                blue = 255;
            } else if(blue < 0) {
                blue = 0;
            }
            imageAltered.setRGB(i, j, new Color(red, green, blue).getRGB());
        }
    }
}