RGB到灰度,java中的bmp图像

RGB到灰度,java中的bmp图像,java,class,rgb,grayscale,Java,Class,Rgb,Grayscale,我的老师给了我们一个任务,让我们制作一个640x480 bmp彩色图像的课堂,把它转换成灰度图像,我找到了一些有想法的来源,所以我做了。但有一个问题,因为它似乎使它,因为它没有给我错误,但输出没有出现。我想这是我的密码。我的代码是 import java.io.*; public class Grayscale{ FileInputStream image; FileOutputStream img; byte[] datos; int gray; public Grayscale(Str

我的老师给了我们一个任务,让我们制作一个640x480 bmp彩色图像的课堂,把它转换成灰度图像,我找到了一些有想法的来源,所以我做了。但有一个问题,因为它似乎使它,因为它没有给我错误,但输出没有出现。我想这是我的密码。我的代码是

import java.io.*;

public class Grayscale{

FileInputStream image;
FileOutputStream img;
byte[] datos;
int gray;

public Grayscale(String nombre)throws Exception{

    this.image = new FileInputStream(nombre);
    this.img = img;
    this.datos = new byte[image.available()];
    this.gray = gray;
}

public void gray()throws Exception{

    image.read(datos);
    img = new FileOutputStream("grayscaleprueba.bmp");

    for (int i = 0; i<datos.length; i++){
        gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
        datos[i] = (byte)gray;
        datos[i+1] = (byte)gray;
        datos[i+2] = (byte)gray;
    }

    img.write(datos);
}
}
import java.io.*;
公共类灰度{
文件输入流图像;
文件输出流img;
字节[]datos;
内灰色;
公共灰度(字符串名称)引发异常{
this.image=新文件输入流(nombre);
this.img=img;
this.datos=新字节[image.available()];
这个.灰色=灰色;
}
public void grey()引发异常{
图像读取(datos);
img=newfileoutputstream(“grayscaleprueba.bmp”);

对于(int i=0;i,此代码存在一些问题:

  • available
    方法只告诉您有多少字节是立即可用的,而不需要实际从磁盘读取。它很可能返回0
  • read
    方法只读取部分数据。返回值告诉您它实际读取的字节数
  • 您不关闭输出流。如果不关闭输出,则无法保证任何内容都会写入输出文件

  • 除了@joni提到的问题之外,还有一些问题。这个问题比最初看起来的要深一些

    BMP文件格式
    • 有一个标题。在进行图像转换之前,您应该跳过(或可能更新)标题
    • 颜色表:您假设一个“直”调色板:颜色索引与RGB值相同。但这可能不同…(顺便说一句:如果图片使用颜色表,则您只能更改该颜色表以获得灰度图像…)
    • 每像素有多少位?您假设它是每像素24位,在8-8-8分布中。这不是保证…标头提供此信息
    • 压缩:是的,图像可能被压缩了——你必须对它进行解码才能处理像素值本身
    环 每个像素处理3个字节,然后以1的增量循环文件。通过3D眼镜观看生成的图像可能非常有趣,但这意味着会出现一些奇怪的图像

    for (int i = 0; i<datos.length; i+=3){ // increment by 3 instead of 1
        gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
        datos[i] = (byte)gray;
        datos[i+1] = (byte)gray;
        datos[i+2] = (byte)gray;
    }
    

    在你的代码中有很多东西是不起作用的

    • available方法不一定返回文件中的字节数。您应该为从输入文件读取的数据使用动态容器
    • read方法不会读取整个文件。必须在循环中使用此方法,直到它返回不正确的值:

      而((byte=fis.read())!=-1){ //用字节做些什么 }

    • 您可以对文件的每个字节进行转换。我不知道有哪种图片格式可以这样做。即使是最简单的BMP格式,也有标题和填充。您应该了解您想要使用的格式,因为它不会像在整个流中迭代那样简单,并使每个块的平均值为3个字节


    它现在被修改了。@ppeterka 66
        //using double to have some precision
        double temp = datos[i]/3.0d + datos[i+1]/3.0d + datos[i]/3.0d;
        gray = (byte)(Math.round(temp)-128); //rounding to Long, and converting to byt value range