use of org.csstudio.javafx.rtplot.ColorMappingFunction in project org.csstudio.display.builder by kasemir.
the class ImageRepresentation method coloringChanged.
/**
* Changes that affect the coloring of the image but not the zoom, size
*/
private void coloringChanged(final WidgetProperty<?> property, final Object old_value, final Object new_value) {
image_plot.setInterpolation(Interpolation.values()[model_widget.propDataInterpolation().getValue().ordinal()]);
final ColorMap colormap = model_widget.propDataColormap().getValue();
final ColorMappingFunction map_function;
if (colormap instanceof PredefinedColorMaps.Predefined)
map_function = NamedColorMappings.getMapping(((PredefinedColorMaps.Predefined) colormap).getName());
else
map_function = value -> ColorMappingFunction.getRGB(colormap.getColor(value));
image_plot.setColorMapping(map_function);
}
use of org.csstudio.javafx.rtplot.ColorMappingFunction in project org.csstudio.display.builder by kasemir.
the class ImageConfigDialog method createContent.
private Node createContent() {
final GridPane layout = new GridPane();
layout.setHgap(5);
layout.setVgap(5);
// Debug layout
// layout.setGridLinesVisible(true);
// Row to use for the next elements
int row = 0;
Label label = new Label("Value Range");
final Font font = label.getFont();
final Font section_font = Font.font(font.getFamily(), FontWeight.BOLD, font.getSize());
label.setFont(section_font);
layout.add(label, 0, ++row);
// Only show the color mapping selector when it's currently a named mapping.
// Suppress when widget has a custom color map.
final ColorMappingFunction selected_mapping = plot.internalGetImagePlot().getColorMapping();
if (selected_mapping instanceof NamedColorMapping) {
label = new Label("Mapping");
layout.add(label, 1, row);
final ComboBox<String> mappings = new ComboBox<>();
mappings.setEditable(false);
mappings.setMaxWidth(Double.MAX_VALUE);
for (NamedColorMapping mapping : NamedColorMappings.getMappings()) mappings.getItems().add(mapping.getName());
mappings.setValue(((NamedColorMapping) selected_mapping).getName());
mappings.setOnAction(event -> {
final NamedColorMapping mapping = NamedColorMappings.getMapping(mappings.getValue());
plot.setColorMapping(mapping);
});
layout.add(mappings, 2, row++);
}
label = new Label("Minimum");
layout.add(label, 1, row);
final TextField min = new TextField(Double.toString(plot.getValueRange().getLow()));
layout.add(min, 2, row);
label = new Label("Maximum");
layout.add(label, 1, ++row);
final TextField max = new TextField(Double.toString(plot.getValueRange().getHigh()));
layout.add(max, 2, row);
final EventHandler<ActionEvent> update_range = event -> {
try {
plot.setValueRange(Double.parseDouble(min.getText().trim()), Double.parseDouble(max.getText().trim()));
plot.internalGetImagePlot().fireChangedValueRange();
} catch (NumberFormatException ex) {
final ValueRange range = plot.getValueRange();
min.setText(Double.toString(range.getLow()));
max.setText(Double.toString(range.getHigh()));
}
};
min.setOnAction(update_range);
max.setOnAction(update_range);
final CheckBox autoscale = new CheckBox("auto-scale");
autoscale.setSelected(plot.isAutoscale());
min.setDisable(autoscale.isSelected());
max.setDisable(autoscale.isSelected());
autoscale.setOnAction(event -> {
plot.setAutoscale(autoscale.isSelected());
min.setDisable(autoscale.isSelected());
max.setDisable(autoscale.isSelected());
plot.internalGetImagePlot().fireChangedAutoScale();
});
layout.add(autoscale, 2, ++row);
final CheckBox show_color_bar = new CheckBox("show color bar");
show_color_bar.setSelected(plot.isShowingColorMap());
show_color_bar.setOnAction(event -> plot.showColorMap(show_color_bar.isSelected()));
layout.add(show_color_bar, 2, ++row);
final CheckBox logscale = new CheckBox("log scale");
logscale.setSelected(plot.isLogscale());
logscale.setOnAction(event -> {
plot.setLogscale(logscale.isSelected());
plot.internalGetImagePlot().fireChangedLogarithmic();
});
layout.add(logscale, 2, ++row);
label = new Label("Horizontal Axis");
label.setFont(section_font);
layout.add(label, 0, ++row);
row = addAxisContent(layout, row, plot.getXAxis());
label = new Label("Vertical Axis");
label.setFont(section_font);
layout.add(label, 0, ++row);
row = addAxisContent(layout, row, plot.getYAxis());
return layout;
}
use of org.csstudio.javafx.rtplot.ColorMappingFunction in project org.csstudio.display.builder by kasemir.
the class ImagePlot method updateImageBuffer.
/**
* Draw all components into image buffer
*/
@Override
protected BufferedImage updateImageBuffer() {
// Would like to use JFX WritableImage,
// but rendering problem on Linux (sandbox.ImageScaling),
// and no way to disable the color interpolation that 'smears'
// the scaled image.
// (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8091877).
// So image is prepared in AWT and then converted to JFX
logger.log(Level.FINE, "updateImageBuffer");
final Rectangle area_copy = area;
if (area_copy.width <= 0 || area_copy.height <= 0)
return null;
final BufferUtil buffer = buffers.getBufferedImage(area_copy.width, area_copy.height);
if (buffer == null)
return null;
final BufferedImage image = buffer.getImage();
final Graphics2D gc = buffer.getGraphics();
gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gc.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
gc.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
gc.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
// Get safe copy of the data
// (not synchronized, i.e. width vs. data may be inconsistent,
// but at least data won't change within this method)
final int data_width = this.data_width, data_height = this.data_height;
final ListNumber numbers = this.image_data;
final boolean unsigned = this.unsigned_data;
double min = this.min, max = this.max;
final VImageType type = this.vimage_type;
final ColorMappingFunction color_mapping = this.color_mapping;
ToDoubleFunction<IteratorNumber> next_sample_func = IteratorNumber::nextDouble;
boolean isRGB = type == VImageType.TYPE_RGB1 || type == VImageType.TYPE_RGB2 || type == VImageType.TYPE_RGB3;
@SuppressWarnings("unchecked") final ToIntFunction<IteratorNumber>[] next_rgb = new ToIntFunction[3];
if (numbers != null) {
if (isRGB) {
if (numbers instanceof ArrayShort) {
if (unsigned) {
next_rgb[0] = (iter) -> getUShortForRGB(iter) << 8 & 0xFF0000;
next_rgb[1] = (iter) -> getUShortForRGB(iter) & 0xFF00;
next_rgb[2] = (iter) -> getUShortForRGB(iter) >>> 8;
} else {
next_rgb[0] = (iter) -> getShortForRGB(iter) << 8 & 0xFF0000;
next_rgb[1] = (iter) -> getShortForRGB(iter) & 0xFF00;
next_rgb[2] = (iter) -> getShortForRGB(iter) >>> 8;
}
}
if (numbers instanceof ArrayInt) {
if (unsigned) {
next_rgb[0] = (iter) -> getUIntForRGB(iter) >>> 8 & 0xFF0000;
next_rgb[1] = (iter) -> getUIntForRGB(iter) >>> 16 & 0xFF00;
next_rgb[2] = (iter) -> getUIntForRGB(iter) >>> 24;
} else {
next_rgb[0] = (iter) -> getIntForRGB(iter) >>> 8 & 0xFF0000;
next_rgb[1] = (iter) -> getIntForRGB(iter) >>> 16 & 0xFF00;
next_rgb[2] = (iter) -> getIntForRGB(iter) >>> 24;
}
} else {
if (!(numbers instanceof ArrayByte))
logger.log(Level.WARNING, "Cannot handle rgb1 image data of type " + numbers.getClass().getName());
if (unsigned) {
next_rgb[0] = (iter) -> getUByteForRGB(iter) << 16;
next_rgb[1] = (iter) -> getUByteForRGB(iter) << 8;
next_rgb[2] = (iter) -> getUByteForRGB(iter);
} else {
next_rgb[0] = (iter) -> getByteForRGB(iter) << 16;
next_rgb[1] = (iter) -> getByteForRGB(iter) << 8;
next_rgb[2] = (iter) -> getByteForRGB(iter);
}
}
} else // is not RGB
{
if (unsigned) {
if (numbers instanceof ArrayShort)
next_sample_func = ImagePlot::getUnsignedShort;
else if (numbers instanceof ArrayByte)
next_sample_func = ImagePlot::getUnsignedByte;
else if (numbers instanceof ArrayInt)
next_sample_func = ImagePlot::getUnsignedInt;
else
logger.log(Level.WARNING, "Cannot handle unsigned data of type " + numbers.getClass().getName());
}
if (autoscale) {
// Compute min..max before layout of color bar
final IteratorNumber iter = numbers.iterator();
min = Double.MAX_VALUE;
max = Double.NEGATIVE_INFINITY;
while (iter.hasNext()) {
final double sample = next_sample_func.applyAsDouble(iter);
if (sample > max)
max = sample;
if (sample < min)
min = sample;
}
logger.log(Level.FINE, "Autoscale range {0} .. {1}", new Object[] { min, max });
}
}
}
// If log, min needs to be 1
if (colorbar_axis.isLogarithmic() && min < 1.0)
min = 1;
colorbar_axis.setValueRange(min, max);
if (need_layout.getAndSet(false))
computeLayout(gc, area_copy, min, max);
// Fill with a 'background' color
gc.setColor(background);
gc.fillRect(0, 0, area_copy.width, area_copy.height);
if (numbers != null) {
// Paint the image
gc.setClip(image_area.x, image_area.y, image_area.width, image_area.height);
final Object image_or_error = !isRGB ? drawData(data_width, data_height, numbers, next_sample_func, min, max, color_mapping) : drawDataRGB(data_width, data_height, numbers, next_rgb, type);
if (image_or_error instanceof BufferedImage) {
final BufferedImage unscaled = (BufferedImage) image_or_error;
// Transform from full axis range into data range,
// using the current 'zoom' state of each axis
final LinearScreenTransform t = new LinearScreenTransform();
AxisRange<Double> zoomed = x_axis.getValueRange();
t.config(min_x, max_x, 0, data_width);
// Round down .. up to always cover the image_area
final int src_x1 = Math.max(0, (int) t.transform(zoomed.getLow()));
final int src_x2 = Math.min(data_width, (int) (t.transform(zoomed.getHigh()) + 1));
// Pixels of the image need to be aligned to their axis location,
// especially when zoomed way in and the pixels are huge.
// Turn pixel back into axis value, and then determine its destination on screen.
final int dst_x1 = x_axis.getScreenCoord(t.inverse(src_x1));
final int dst_x2 = x_axis.getScreenCoord(t.inverse(src_x2));
// For Y axis, min_y == bottom == data_height
zoomed = y_axis.getValueRange();
t.config(min_y, max_y, data_height, 0);
final int src_y1 = Math.max(0, (int) t.transform(zoomed.getHigh()));
final int src_y2 = Math.min(data_height, (int) (t.transform(zoomed.getLow()) + 1));
final int dst_y1 = y_axis.getScreenCoord(t.inverse(src_y1));
final int dst_y2 = y_axis.getScreenCoord(t.inverse(src_y2));
switch(interpolation) {
case NONE:
gc.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
break;
case INTERPOLATE:
gc.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
break;
default:
// If image is smaller than screen area, show the actual pixels
if ((src_x2 - src_x1) < image_area.width && (src_y2 - src_y1) < image_area.height)
gc.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
else
// If image is larger than screen area, use best possible interpolation
// to avoid artifacts from statistically picking some specific nearest neighbor
gc.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
}
gc.drawImage(unscaled, dst_x1, dst_y1, dst_x2, dst_y2, src_x1, src_y1, src_x2, src_y2, /* ImageObserver */
null);
} else {
gc.setColor(Color.RED);
gc.setFont(x_axis.label_font);
gc.drawString(Objects.toString(image_or_error), image_area.x + 10, image_area.y + 20);
}
gc.setClip(0, 0, area_copy.width, area_copy.height);
}
// Axes
y_axis.paint(gc, image_area);
x_axis.paint(gc, image_area);
// Color bar
if (colorbar_area != null) {
final BufferedImage bar = drawColorBar(min, max, color_mapping);
gc.drawImage(bar, colorbar_area.x, colorbar_area.y, colorbar_area.width, colorbar_area.height, null);
colorbar_axis.paint(gc, colorbar_area);
}
// ROI uses X axis font
gc.setFont(x_axis.label_font);
for (RegionOfInterest roi : rois) drawROI(gc, roi);
return image;
}
Aggregations