Search in sources :

Example 1 with ColorMappingFunction

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);
}
Also used : Arrays(java.util.Arrays) DisplayModel(org.csstudio.display.builder.model.DisplayModel) PredefinedColorMaps(org.csstudio.display.builder.model.properties.PredefinedColorMaps) Interpolation(org.csstudio.javafx.rtplot.Interpolation) VImageType(org.diirt.vtype.VImageType) Level(java.util.logging.Level) RTImagePlotListener(org.csstudio.javafx.rtplot.RTImagePlotListener) ValueFactory(org.diirt.vtype.ValueFactory) ImageWidget(org.csstudio.display.builder.model.widgets.plots.ImageWidget) RTImagePlot(org.csstudio.javafx.rtplot.RTImagePlot) ArrayInt(org.diirt.util.array.ArrayInt) DirtyFlag(org.csstudio.display.builder.model.DirtyFlag) WidgetProperty(org.csstudio.display.builder.model.WidgetProperty) ModelThreadPool(org.csstudio.display.builder.model.util.ModelThreadPool) AxisWidgetProperty(org.csstudio.display.builder.model.widgets.plots.ImageWidget.AxisWidgetProperty) VNumberArray(org.diirt.vtype.VNumberArray) Pane(javafx.scene.layout.Pane) NamedColorMappings(org.csstudio.javafx.rtplot.NamedColorMappings) ModelResourceUtil(org.csstudio.display.builder.model.util.ModelResourceUtil) Rectangle2D(javafx.geometry.Rectangle2D) ROIWidgetProperty(org.csstudio.display.builder.model.widgets.plots.ImageWidget.ROIWidgetProperty) RegionBaseRepresentation(org.csstudio.display.builder.representation.javafx.widgets.RegionBaseRepresentation) RepresentationUpdateThrottle(org.csstudio.display.builder.representation.RepresentationUpdateThrottle) RegionOfInterest(org.csstudio.javafx.rtplot.RegionOfInterest) VType(org.diirt.vtype.VType) ColorMap(org.csstudio.display.builder.model.properties.ColorMap) ToolkitRepresentation.logger(org.csstudio.display.builder.representation.ToolkitRepresentation.logger) TimeUnit(java.util.concurrent.TimeUnit) Platform(javafx.application.Platform) List(java.util.List) MacroHandler(org.csstudio.display.builder.model.macros.MacroHandler) WidgetPropertyListener(org.csstudio.display.builder.model.WidgetPropertyListener) ArrayDouble(org.diirt.util.array.ArrayDouble) ColorMappingFunction(org.csstudio.javafx.rtplot.ColorMappingFunction) JFXUtil(org.csstudio.display.builder.representation.javafx.JFXUtil) Axis(org.csstudio.javafx.rtplot.Axis) VImage(org.diirt.vtype.VImage) Image(javafx.scene.image.Image) ColorMap(org.csstudio.display.builder.model.properties.ColorMap) PredefinedColorMaps(org.csstudio.display.builder.model.properties.PredefinedColorMaps) ColorMappingFunction(org.csstudio.javafx.rtplot.ColorMappingFunction)

Example 2 with ColorMappingFunction

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;
}
Also used : NamedColorMapping(org.csstudio.javafx.rtplot.NamedColorMapping) EventHandler(javafx.event.EventHandler) FontWeight(javafx.scene.text.FontWeight) Activator(org.csstudio.javafx.rtplot.Activator) NamedColorMappings(org.csstudio.javafx.rtplot.NamedColorMappings) TextField(javafx.scene.control.TextField) Modality(javafx.stage.Modality) Dialog(javafx.scene.control.Dialog) Label(javafx.scene.control.Label) ButtonType(javafx.scene.control.ButtonType) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) Font(javafx.scene.text.Font) ValueRange(org.csstudio.javafx.rtplot.data.ValueRange) ActionEvent(javafx.event.ActionEvent) ComboBox(javafx.scene.control.ComboBox) RTImagePlot(org.csstudio.javafx.rtplot.RTImagePlot) ImageView(javafx.scene.image.ImageView) ColorMappingFunction(org.csstudio.javafx.rtplot.ColorMappingFunction) Axis(org.csstudio.javafx.rtplot.Axis) GridPane(javafx.scene.layout.GridPane) GridPane(javafx.scene.layout.GridPane) ComboBox(javafx.scene.control.ComboBox) ActionEvent(javafx.event.ActionEvent) ColorMappingFunction(org.csstudio.javafx.rtplot.ColorMappingFunction) Label(javafx.scene.control.Label) Font(javafx.scene.text.Font) ValueRange(org.csstudio.javafx.rtplot.data.ValueRange) CheckBox(javafx.scene.control.CheckBox) NamedColorMapping(org.csstudio.javafx.rtplot.NamedColorMapping) TextField(javafx.scene.control.TextField)

Example 3 with ColorMappingFunction

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;
}
Also used : RegionOfInterest(org.csstudio.javafx.rtplot.RegionOfInterest) ColorMappingFunction(org.csstudio.javafx.rtplot.ColorMappingFunction) Rectangle(java.awt.Rectangle) LinearScreenTransform(org.csstudio.javafx.rtplot.internal.util.LinearScreenTransform) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D) ListNumber(org.diirt.util.array.ListNumber) BufferUtil(org.csstudio.javafx.BufferUtil) VImageType(org.diirt.vtype.VImageType) ToIntFunction(java.util.function.ToIntFunction) ArrayByte(org.diirt.util.array.ArrayByte) ArrayInt(org.diirt.util.array.ArrayInt) ArrayShort(org.diirt.util.array.ArrayShort) IteratorNumber(org.diirt.util.array.IteratorNumber)

Aggregations

ColorMappingFunction (org.csstudio.javafx.rtplot.ColorMappingFunction)3 Axis (org.csstudio.javafx.rtplot.Axis)2 NamedColorMappings (org.csstudio.javafx.rtplot.NamedColorMappings)2 RTImagePlot (org.csstudio.javafx.rtplot.RTImagePlot)2 RegionOfInterest (org.csstudio.javafx.rtplot.RegionOfInterest)2 ArrayInt (org.diirt.util.array.ArrayInt)2 VImageType (org.diirt.vtype.VImageType)2 Graphics2D (java.awt.Graphics2D)1 Rectangle (java.awt.Rectangle)1 BufferedImage (java.awt.image.BufferedImage)1 Arrays (java.util.Arrays)1 List (java.util.List)1 TimeUnit (java.util.concurrent.TimeUnit)1 ToIntFunction (java.util.function.ToIntFunction)1 Level (java.util.logging.Level)1 Platform (javafx.application.Platform)1 ActionEvent (javafx.event.ActionEvent)1 EventHandler (javafx.event.EventHandler)1 Rectangle2D (javafx.geometry.Rectangle2D)1 Node (javafx.scene.Node)1