Java 如何从 PNG 文件中读取像素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6444869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I read pixels from a PNG file?
提问by
I know how to capture a screenshot by using Robot, Windowtester or FEST. I also know how to read a pixel from the screen by using robot.
我知道如何使用 Robot、Windowtester 或 FEST 截取屏幕截图。我也知道如何使用机器人从屏幕上读取像素。
int x = 10;
int y = 10;
Color px = getPixelColor(int x, int y);
However, I don't know how to read a pixel from an image that is already captured. I'm planning to compare a current image, with an image from file. Lets say both are PNG. Are there any frameworks that I can use to compare images pixel by pixel?
但是,我不知道如何从已捕获的图像中读取像素。我打算将当前图像与文件中的图像进行比较。让我们说两者都是PNG。是否有任何框架可用于逐像素比较图像?
采纳答案by hughes
Is this in Java? If so, you can use ImageIO.read( "yourImage.png" )
to get a BufferedImage
. That will have a getData()
method which will give you a Raster
object, on which you can call getPixel
. See link
这是在 Java 中吗?如果是这样,您可以使用ImageIO.read( "yourImage.png" )
获取BufferedImage
. 这将有一个getData()
方法,该方法将为您提供一个Raster
对象,您可以在该对象上调用getPixel
. 见链接
回答by Mikita Belahlazau
You can read image file: Reading/Loading an Image.
您可以读取图像文件:Reading/Loading an Image。
And then get color using getRGB
method.
然后使用getRGB
方法获取颜色。
回答by Seth
This should work:
这应该有效:
javax.imageio.ImageIO.read(new File("filename.png"))
Then you can walk through the pixels and compare with the images pixel by pixel with this:
然后你可以遍历像素并与图像逐像素进行比较:
java.awt.image.BufferedImage.getRGB(int x, int y).
回答by Andrew Thompson
Load them as BufferedImage
instances and it is relatively easy.
将它们作为BufferedImage
实例加载,相对容易。
Here is part of code that creates images with text, then creates a new image that shows the difference between the image with & without text.
这是创建带有文本的图像的部分代码,然后创建一个新图像,显示带有和不带文本的图像之间的差异。
for (int xx=0; xx<width; xx++) {
for (int yy=0; yy<height; yy++) {
Color originalColor = new Color(originalImage.getRGB(xx,yy));
int r1 = originalColor.getRed();
int g1 = originalColor.getGreen();
int b1 = originalColor.getBlue();
Color newColor = new Color(textImage.getRGB(xx,yy));
int r2 = newColor.getRed();
int g2 = newColor.getGreen();
int b2 = newColor.getBlue();
Color bnw = Color.black;
if (r1==r2 && g1==g2 && b1==b2) {
bnw = Color.white;
}
bnwImage.setRGB(xx, yy, bnw.getRGB());
int rD = Math.abs(r1-r2);
int gD = Math.abs(g1-g2);
int bD = Math.abs(b1-b2);
Color differenceColor = new Color(rD,gD,bD);
differenceImage.setRGB(xx, yy, differenceColor.getRGB());
}
}
Screensot
屏幕截图
Full code
完整代码
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import java.util.Locale;
class ImageWriteTest {
private BufferedImage originalImage;
private BufferedImage textImage;
private BufferedImage differenceImage;
private BufferedImage bnwImage;
private JPanel gui;
private JCheckBox antialiasing;
private JCheckBox rendering;
private JCheckBox fractionalMetrics;
private JCheckBox strokeControl;
private JCheckBox colorRendering;
private JCheckBox dithering;
private JComboBox textAntialiasing;
private JComboBox textLcdContrast;
private JLabel label0_1;
private JLabel label0_4;
private JLabel label0_7;
private JLabel label1_0;
private JTextArea output;
final static Object[] VALUES_TEXT_ANTIALIASING = {
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON,
RenderingHints.VALUE_TEXT_ANTIALIAS_GASP,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB
};
final static Object[] VALUES_TEXT_LCD_CONTRAST = {
new Integer(100),
new Integer(150),
new Integer(200),
new Integer(250)
};
ImageWriteTest() {
int width = 280;
int height = 100;
gui = new JPanel(new BorderLayout(0,4));
originalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
differenceImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
bnwImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
JPanel controls = new JPanel(new GridLayout(0,2,0,0));
antialiasing = new JCheckBox("Anti-aliasing", false);
rendering = new JCheckBox("Rendering - Quality", true);
fractionalMetrics = new JCheckBox("Fractional Metrics", true);
strokeControl = new JCheckBox("Stroke Control - Pure", false);
colorRendering = new JCheckBox("Color Rendering - Quality", true);
dithering = new JCheckBox("Dithering", false);
controls.add(antialiasing);
controls.add(rendering);
controls.add(fractionalMetrics);
controls.add(colorRendering);
textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST);
JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
lcdContrastPanel.add(textLcdContrast);
lcdContrastPanel.add(new JLabel("Text LCD Contrast"));
controls.add(lcdContrastPanel);
controls.add(strokeControl);
textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING);
controls.add(textAntialiasing);
controls.add(dithering);
ItemListener itemListener = new ItemListener(){
public void itemStateChanged(ItemEvent e) {
updateImages();
}
};
antialiasing.addItemListener(itemListener);
rendering.addItemListener(itemListener);
fractionalMetrics.addItemListener(itemListener);
strokeControl.addItemListener(itemListener);
colorRendering.addItemListener(itemListener);
dithering.addItemListener(itemListener);
textAntialiasing.addItemListener(itemListener);
textLcdContrast.addItemListener(itemListener);
Graphics2D g2d = originalImage.createGraphics();
GradientPaint gp = new GradientPaint(
0f, 0f, Color.red,
(float)width, (float)height, Color.orange);
g2d.setPaint(gp);
g2d.fillRect(0,0, width, height);
g2d.setColor(Color.blue);
for (int ii=0; ii<width; ii+=10) {
g2d.drawLine(ii, 0, ii, height);
}
g2d.setColor(Color.green);
for (int jj=0; jj<height; jj+=10) {
g2d.drawLine(0, jj, width, jj);
}
updateImages();
gui.add(controls, BorderLayout.NORTH);
JPanel images = new JPanel(new GridLayout(0,2,0,0));
images.add(new JLabel(new ImageIcon(originalImage)));
images.add(new JLabel(new ImageIcon(textImage)));
images.add(new JLabel(new ImageIcon(differenceImage)));
images.add(new JLabel(new ImageIcon(bnwImage)));
try {
label0_1 = new JLabel(new ImageIcon(getJpegCompressedImage(0.1f, textImage)));
images.add(label0_1);
label0_4 = new JLabel(new ImageIcon(getJpegCompressedImage(0.4f, textImage)));
images.add(label0_4);
label0_7 = new JLabel(new ImageIcon(getJpegCompressedImage(0.7f, textImage)));
images.add(label0_7);
label1_0 = new JLabel(new ImageIcon(getJpegCompressedImage(1.0f, textImage)));
images.add(label1_0);
} catch(IOException ioe) {
}
gui.add(images, BorderLayout.CENTER);
StringBuilder sb = new StringBuilder();
String[] names = {
"java.vendor",
"java.version",
"java.vm.version",
"os.name",
"os.version"
};
for (String name : names) {
addProperty(sb, name);
}
output = new JTextArea(sb.toString(),6,40);
gui.add(new JScrollPane(output), BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
private static void addProperty(StringBuilder builder, String name) {
builder.append( name + " \t" + System.getProperty(name) + "\n" );
}
/** Adapted from SO post by x4u. */
private Image getJpegCompressedImage(float quality, BufferedImage image) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next();
ImageOutputStream ioStream = ImageIO.createImageOutputStream( outStream );
imgWriter.setOutput( ioStream );
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() );
jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
jpegParams.setCompressionQuality( quality );
imgWriter.write( null, new IIOImage( image, null, null ), jpegParams );
ioStream.flush();
ioStream.close();
imgWriter.dispose();
BufferedImage compressedImage = ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));
JLabel label = new JLabel("Quality: " + quality);
label.setBackground(new Color(255,255,255,192));
label.setOpaque(true);
label.setSize(label.getPreferredSize());
label.paint(compressedImage.getGraphics());
return compressedImage;
}
private void updateImages() {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Graphics2D g2dText = textImage.createGraphics();
if (antialiasing.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
}
if (rendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
}
if (fractionalMetrics.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
}
if (strokeControl.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
}
if (dithering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
}
if (colorRendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
}
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
textLcdContrast.getSelectedItem());
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
textAntialiasing.getSelectedItem());
g2dText.drawImage(originalImage, 0,0, null);
g2dText.setColor(Color.black);
g2dText.drawString("The quick brown fox jumped over the lazy dog.", 10,50);
Graphics2D g2dDifference = differenceImage.createGraphics();
Graphics2D g2dBnW = bnwImage.createGraphics();
for (int xx=0; xx<width; xx++) {
for (int yy=0; yy<height; yy++) {
Color originalColor = new Color(originalImage.getRGB(xx,yy));
int r1 = originalColor.getRed();
int g1 = originalColor.getGreen();
int b1 = originalColor.getBlue();
Color newColor = new Color(textImage.getRGB(xx,yy));
int r2 = newColor.getRed();
int g2 = newColor.getGreen();
int b2 = newColor.getBlue();
Color bnw = Color.black;
if (r1==r2 && g1==g2 && b1==b2) {
bnw = Color.white;
}
bnwImage.setRGB(xx, yy, bnw.getRGB());
int rD = Math.abs(r1-r2);
int gD = Math.abs(g1-g2);
int bD = Math.abs(b1-b2);
Color differenceColor = new Color(rD,gD,bD);
differenceImage.setRGB(xx, yy, differenceColor.getRGB());
}
}
gui.repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
ImageWriteTest iwt = new ImageWriteTest();
}
} );
}
}
回答by FrankieTheSkin
In C/C++, if you're comfortable requiring a minimum version of Windows, it's rather easy, you can use GDI+ to load the image and draw it to a memory bitmap, then you can use the returned pointer to get the pixel data.
在 C/C++ 中,如果您愿意要求最低版本的 Windows,这很容易,您可以使用 GDI+ 加载图像并将其绘制到内存位图,然后您可以使用返回的指针来获取像素数据。
Use GdiplusStartup()
and GdiplusShutdown()
to initialise and uninitialise GDI+.
使用GdiplusStartup()
和GdiplusShutdown()
来初始化和取消初始化 GDI+。
Use a GDI+ Image
object, using the overload that takes a filename, to load the image, then use the methods GetWidth()
and GetHeight()
, a BITMAPINFO
structure and the CreateDIBSection()
GDI function to create a memory bitmap.
使用 GDI+Image
对象,使用带文件名的重载来加载图像,然后使用方法GetWidth()
and GetHeight()
、BITMAPINFO
结构和CreateDIBSection()
GDI 函数来创建内存位图。
Then use CreateCompatibleDC()
to create a device context for the bitmap and SelectObject()
to select the bitmap into that device context.
然后CreateCompatibleDC()
用于为位图创建设备上下文并将位图SelectObject()
选择到该设备上下文中。
Then you use a GDI+ Graphics
object, using the overload that takes a device context, and its DrawImage()
method, using the overload that takes x
, y
, width
and height
, to draw the image to the bitmap's device context.
然后,可以使用一个GDI +Graphics
对象,使用采用一个设备上下文,其过载DrawImage()
的方法,使用取过载x
,y
,width
和height
,来绘制图像以位图的设备上下文。
After that, you can get/set the pixel data using the pointer returned by CreateDIBSection()
.
之后,您可以使用返回的指针获取/设置像素数据CreateDIBSection()
。
When you're done, use DeleteDC()
to get rid of the bitmap's device context BEFORE using DeleteObject()
to get rid of the bitmap. GDI+ Image objects can also be used to save images in a supported format, including PNG.
完成后,使用DeleteDC()
清除位图的设备上下文,然后再使用DeleteObject()
清除位图。GDI+ 图像对象还可用于以支持的格式保存图像,包括 PNG。