- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我必须编写一个程序来读取 24 位 BMP 图像(没有 ImageIO 或任何外部库)并使其成为 8 位灰度 BMP 图像...我读到我必须更改图像的标题才能使其成为8 位,Source 1和 Source 2 。所以我读了here BitCount 字节位于 header 的 29 和 30 处,并尝试更改它们...
首先,我读取文件并生成字节 vector ,如下所示
FileInputStream image= new FileInputStream(path);
byte[] bytesImage = new byte[image.available()];
image.read(bytesImage);
image.close();
然后我获取图像标题并将其复制到新的 vector
int width = byteToInt(bytesImage[18], bytesImage[19], bytesImage[20], bytesImage[21]);
int height = byteToInt(bytesImage[22], bytesImage[23], bytesImage[24], bytesImage[25]);
int header = byteToInt(bytesImage[14], bytesImage[15], bytesImage[16], bytesImage[17]) + 14; // Add 14 for the header
vecGrey = Arrays.copyOf(bytesImage, bytesImage.length);
然后我更改 header 信息字节,使其成为 8 位 BMP,如下所示:
byte[] values = intToByte(8);
vecGrey[28] = values[0]; // This is the index for the BitCount byte 1
vecGrey[29] = values[1]; // and this one is the index for the second one.
好吧,现在问题来了,由于某种原因,如果我尝试使用不同的 header 编写 vecGrey,则无法编写带有 vecGrey header 的文件,如下所示:
FileOutputStream aGrey = new FileOutputStream(name+ "-gray.bmp");
aGrey.write(vecGrey);
aGrey.close();
// This is a method that displays the resulting image in a frame...
makeInterface(name + "-gray.bmp");
我知道我必须更改 vecGrey 中的值,但这应该可以显示不正确的输出(可能是非灰度图像或根本不是图像)。但是当我尝试读取在 makeInterface() 方法中生成的文件时,我得到了
javax.imageio.iioexception unable to read the image header
所以我认为程序无法正确读取标题,但我不知道为什么!如果我将 BitCount 值更改为 16,它仍然有效,但更改为 1、4 或 8,则不会出现相同的错误...我没有上传我的洞代码,因为它是西类牙语,但如果需要,我可以翻译并在此处进行编辑。
谢谢!
EDIT1:我只使用 640x480 24 位 BMP 图像,因此不需要检查填充。
最佳答案
将 BMP 从 24 位更改为 8 位时,您必须更改 header 中的其他几项内容,首先图像的大小会发生变化(字节 3-6),因为您正在处理 8 位图像,因此有一个每像素字节,因此新大小应变为
headerSize {通常为 54} +(numberOfColors*4){这是用于颜色表/调色板的,我建议将其设置为 256}+width*height < em>{实际像素数}
接下来,您必须指出像素数据的偏移量,它位于颜色表/调色板之后,该值位于字节 11-14 中,新值应为:
标题大小+颜色数*4
接下来您需要修改从字节 15 开始的 BITMAPINFOHEADER,字节 15-18 应包含第二个 header 的大小,通常为 40,如果您只想转换为灰度,您可以忽略并保留一些字节不变,直到你到达字节 29 和 30,修改 bitCount(就像你已经做的那样),然后在字节 35-38 中,据我所知,你必须输入我们已经计算出的新图像大小,字节 47-50 决定了调色板中的颜色,因为您正在进行灰度处理,所以我建议使用 256 种颜色,稍后我将解释原因。字节51-54包含重要颜色的数量,设置为0表示每种颜色都很重要。
接下来,您需要在标题旁边添加颜色表/调色板。我之所以推荐256色,是因为调色板的写法是这样的:[B,G,R,0] 其中BGR是RGB格式的蓝、绿、红颜色值,末尾有一个常量0,有256种颜色您可以制作一个调色板,将 RGB 值写入 R=G=B,这应该会产生灰色阴影。因此,在 header 旁边,您必须按升序添加这一系列新字节:
[0,0,0,0] [1,1,1,0] [2,2,2,0] [3,3,3,0] ... [255,255,255,0]
请注意,256 是计算图像新尺寸所需的颜色数,因为它是调色板中“条目”的数量。
接下来,您需要在表格/调色板之后写入新的像素数据。由于您获得的是 24 位图像,您可以提取像素矩阵并获取每个像素的 RGB 值,只需记住您有一个字节数组,其值从 -128 到 127,您需要确保您得到int 值,因此如果任何 channel 的强度 < 0,则向其添加 256 以获得 int 值,然后您可以应用一个方程来给出灰度强度:
Y' = 0.299R' + 0.587G' + 0.114B'其中Y'是灰色的强度,R G B 是红、绿、蓝的强度。
您可以对方程结果进行四舍五入,然后将其作为字节写入图像,并对原始图像中的每个像素执行相同的操作。
完成后,只需在文件末尾添加两个保留的 0,您就应该拥有 24 位图像的全新 8 位灰度图像。
希望这有帮助。
来源:您提供的来源以及: https://en.wikipedia.org/wiki/BMP_file_format https://en.wikipedia.org/wiki/Grayscale
关于java - 如何将 BMP 图像转换为 8 位灰度图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39405897/
我是一名优秀的程序员,十分优秀!