作者AI3767 (AI3767)
站内java
标题Re: [问题] 还是.bmp档案的问题 ~"~
时间Mon Oct 22 20:52:19 2007
很久以前, 在写图档程式式, 我也遇上了同样的问题
当时对Java只是半熟, 对Java 的image支援部份更是不熟
程式弄个很久, debug老半天就觉得没错,
不清楚为什麽好好的bmp图档进来, pixel的数值却都变了= =
超火大
後来乾脆拿bmp的档案格式, 自己写一个reader,
至今没再去解谜
现在正好又有人遇到同样的问题, 於是想再去试看看
结果, 你的程式基本上的确是对的, 再去debug一次,
仍然是pixel值变了, 所以得到的结果就变成非预期的
於是我想, 不可能这样的事都没人注意到,
更不相信会被放着不管, 一定有至少一个方法可解
所以去try了一些API, 发现
Raster这个东西可以得到我们预期要的东西
也就是 BufferedImage.getData() 这个API
可以得到原图档的pixel值
问题是, Raster下的API只能拿pixel, 却不能改pixel,
所以利用其下的 WritableRaster,
再使用 BufferedImage.setData() 成功达到目标
但至於Java对image所采用的
ColorSpace, ColorModel, Raster, SampleModle等物
我对多媒体并不熟, 倒是希望有在这方面熟悉的大大
可以写一篇完整剖析造福板众 ^^
下面是将原po程式码重新修改後的程式:
import java.io.*;
import java.awt.image.*;
import javax.imageio.*;
public class r96922076_hw2_Modified {
public static void main(String args[]) throws IOException {
File fp = new File("lena.bmp");
File fp2 = new File("test.bmp");
File nfp = new File("oktest.bmp");
BufferedImage imgR = ImageIO.read(fp);
BufferedImage imgW =
new BufferedImage(imgR.getWidth(), imgR.getHeight(), imgR.getType());
BufferedImage imgOK =
new BufferedImage(imgR.getWidth(), imgR.getHeight(), imgR.getType());
//使用回圈,把影像矩阵data,存成test.bmp档
int[][] data = r96922076_hw2_Method(imgR);
imgW.setRGB(0,0, imgR.getWidth(),imgR.getHeight(),
to1DArray(data), 0, imgR.getWidth());
imgOK.setData(toBiRasterForByte(imgR.getData()));
ImageIO.write(imgW, "bmp", fp2);
ImageIO.write(imgOK, "bmp", nfp);
} //{END main}
static int[][] r96922076_hw2_Method(BufferedImage imgR) {
int data[][] = new int[imgR.getHeight()][imgR.getWidth()];
for(int i=0; i<imgR.getHeight(); i++)
for(int j=0; j<imgR.getWidth(); j++)
data[i][j] = toBiPixel(imgR.getRGB(j,i));
return data;
}
private static int[] to1DArray(int[][] src) {
int h = src.length;
if( h<1 ) return new int[0];
int w = src[0].length;
int[] res = new int[h*w];
int shift = 0;
for(int i=0; i<h; i++) {
System.arraycopy(src[i],0, res, shift, w);
shift += w;
}
return res;
} //{END} to1DArray()
public static int toBiPixel(int argb) {
int a = (argb>>24) & 0xff;
int r = (argb>>16) & 0xff;
int g = (argb>> 8) & 0xff;
int b = (argb ) & 0xff;
// 大於128则设定成255; 小於128则设定成0
if( r>=0x80 ) r = 0xff;
else r = 0x00;
return (a<<24)|(r<<16)|(r<<8)|r;
}
static Raster toBiRasterForByte(Raster srcR) {
int w = srcR.getWidth(), h = srcR.getHeight();
WritableRaster tarR =
Raster.createWritableRaster(srcR.getSampleModel(), null);
int[] srcData = srcR.getPixels(0,0, w,h, new int[w*h]);
for(int i=0; i<srcData.length; i++) {
int p = srcData[i];
srcData[i] = (p>=0x80)? 0xff: 0x00;
}
tarR.setPixels(0,0, w,h, srcData);
return tarR;
} //{END} toBiRasterForByte()
} //{END class} r96922076_hw2_Modified
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.123.105.166
1F:推 H45:感谢分享,但是程式码好长,不过我倒没发现 getData 呢... 10/22 21:08
2F:推 shiengchyi:高手~!! 受小弟一拜.... 10/23 01:24