我正在尝试将图像保存为JPEG。当图像宽度是4的倍数时,下面的代码工作正常,但图像是倾斜的。它与填充有关。当我调试时,我能够通过用0填充每一行来正确地将图像保存为位图。但是,JPEG无法解决这个问题。
要记住的要点是我的图像表示为bgr(蓝绿色红色,每个1字节)字节数组,我从本机调用中接收。
byte[] data = captureImage(OpenGLCanvas.getLastFocused().getViewId(), x, y);
if (data.length != 3*x*y)
{
// 3 bytes per pixel
return false;
}
// create buffered image from raw data
DataBufferByte buffer = new DataBufferByte(data, 3*x*y);
ComponentSampleModel csm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, x, y, 3, 3*x, new int[]{0,1,2} );
WritableRaster raster = Raster.createWritableRaster(csm, buffer, new Point(0,0));
BufferedImage buff_image = new BufferedImage(x, y, BufferedImage.TYPE_INT_BGR); // because windows goes the wrong way...
buff_image.setData(raster);
//save the BufferedImage as a jpeg
try
{
File file = new File(file_name);
FileOutputStream out = new FileOutputStream(file);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(buff_image);
param.setQuality(1.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(buff_image);
out.close();
// or JDK 1.4
// ImageIO.write(image, "JPEG", out);
}
catch (Exception ex)
{
// Write permissions on "file_name"
return false;
}
我也看过用C ++创建JPEG,但是那里的材料更少,但它仍然是一个选项。
任何帮助都非常赞赏。 利昂
答案 0 :(得分:1)
感谢您的建议,但我已成功完成了这项工作。
为了捕获我在C ++中使用WINGDIAPI HBITMAP WINAPI CreateDIBSection的图像,然后OpenGL将绘制到该位图。不知道的是,自动向位图添加了填充,宽度不是4的倍数。
因此,Java错误地解释了字节数组。
正确的方法是解释字节是
byte[] data = captureImage(OpenGLCanvas.getLastFocused().getViewId(), x, y);
int x_padding = x%4;
BufferedImage buff_image = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
int val;
for (int j = 0; j < y; j++)
{
for (int i = 0; i < x; i++)
{
val = ( data[(i + j*x)*3 + j*x_padding + 2]& 0xff) +
((data[(i + j*x)*3 + j*x_padding + 1]& 0xff) << 8) +
((data[(i + j*x)*3 + j*x_padding + 0]& 0xff) << 16);
buff_image.setRGB(i, j, val);
}
}
//save the BufferedImage as a jpeg
try
{
File file = new File(file_name);
FileOutputStream out = new FileOutputStream(file);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(buff_image);
param.setQuality(1.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(buff_image);
out.close();
}
答案 1 :(得分:0)
JPEG标准非常复杂。我认为以某种方式填充DCT的输出可能是一个问题。完成DCT以将来自YCrCb 4:2:2的内容转换为信号空间,每个通道具有一个DCT,Y,Cr和Cb。 DCT在“Macroblock”或“最小编码块”上完成,具体取决于您的上下文。 JPEG通常有8x8宏块。当在边缘并且没有足够的像素时,它会夹住边缘值并“将其拖过”并对其进行DCT。
我不确定这是否有帮助,但听起来像是一个非标准的符合文件。我建议您使用JPEGSnoop了解更多信息。关于JPEG压缩如何工作也有几种解释。
一种可能性是采样率可能编码不正确。这可能是异国情调,如4:2:1所以你可能会拉出两倍的X样本,从而扭曲图像。
答案 2 :(得分:0)
这是我从屏幕上捕捉的图像
也许Screen Image类更容易使用。