我有时需要显示
image data in the form of a histogram的表示.我对访问图像数据的方式特别感兴趣.我熟悉JFreeChart,其中包括直方图支持,但我会考虑其他方法.
解决方法
下面的示例使用几种技术来创建任意图像的RGB直方图:
> Raster
方法getSamples()从BufferedImage中提取每个色带的值.
> HistogramDataset
方法addSeries()将每个波段的计数添加到数据集.
> A StandardXYBarPainter
替换ChartFactory默认值,如here所示.
>定制DefaultDrawingSupplier
提供每个系列所需的颜色;它包含半透明的颜色.
> here的变形here用于控制每个频带的可见度;使用ChartMouseListener的补充方法如here所示.
import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.Paint; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.awt.image.Raster; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.DefaultDrawingSupplier; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.StandardXYBarPainter; import org.jfree.chart.renderer.xy.XYBarRenderer; import org.jfree.data.statistics.HistogramDataset; /** * @see https://stackoverflow.com/q/40537278/230513 * @see https://stackoverflow.com/q/11870416/230513 * @see https://stackoverflow.com/a/28519356/230513 */ public class Histogram { private static final int BINS = 256; private final BufferedImage image = getImage(); private HistogramDataset dataset; private XYBarRenderer renderer; private BufferedImage getImage() { try { return ImageIO.read(new URL( "http://i.imgur.com/kxXhIH1.jpg")); } catch (IOException e) { e.printStackTrace(System.err); } return null; } private ChartPanel createChartPanel() { // dataset dataset = new HistogramDataset(); Raster raster = image.getRaster(); final int w = image.getWidth(); final int h = image.getHeight(); double[] r = new double[w * h]; r = raster.getSamples(0,w,h,r); dataset.addSeries("Red",r,BINS); r = raster.getSamples(0,1,r); dataset.addSeries("Green",2,r); dataset.addSeries("Blue",BINS); // chart JFreeChart chart = ChartFactory.createHistogram("Histogram","Value","Count",dataset,PlotOrientation.VERTICAL,true,false); XYPlot plot = (XYPlot) chart.getPlot(); renderer = (XYBarRenderer) plot.getRenderer(); renderer.setBarPainter(new StandardXYBarPainter()); // translucent red,green & blue Paint[] paintArray = { new Color(0x80ff0000,true),new Color(0x8000ff00,new Color(0x800000ff,true) }; plot.setDrawingSupplier(new DefaultDrawingSupplier( paintArray,DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE)); ChartPanel panel = new ChartPanel(chart); panel.setMouseWheelEnabled(true); return panel; } private JPanel createControlPanel() { JPanel panel = new JPanel(); panel.add(new JCheckBox(new VisibleAction(0))); panel.add(new JCheckBox(new VisibleAction(1))); panel.add(new JCheckBox(new VisibleAction(2))); return panel; } private class VisibleAction extends AbstractAction { private final int i; public VisibleAction(int i) { this.i = i; this.putValue(NAME,(String) dataset.getSeriesKey(i)); this.putValue(SELECTED_KEY,true); renderer.setSeriesVisible(i,true); } @Override public void actionPerformed(ActionEvent e) { renderer.setSeriesVisible(i,!renderer.getSeriesVisible(i)); } } private void display() { JFrame f = new JFrame("Histogram"); f.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE); f.add(createChartPanel()); f.add(createControlPanel(),BorderLayout.SOUTH); f.add(new JLabel(new ImageIcon(image)),BorderLayout.WEST); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(() -> { new Histogram().display(); }); } }