use of org.diirt.util.array.ListNumber in project org.csstudio.display.builder by kasemir.
the class WaveformValueDataProvider method setValue.
/**
* Update the waveform value.
* @param value New value
* Fires event to listeners (plot)
*/
public void setValue(final VType value) {
final ListNumber new_numbers;
if (value instanceof VNumberArray)
new_numbers = ((VNumberArray) value).getData();
else
new_numbers = new ArrayDouble(VTypeHelper.toDouble(value));
lock.writeLock().lock();
try {
numbers = new_numbers;
} finally {
lock.writeLock().unlock();
}
}
use of org.diirt.util.array.ListNumber 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;
}
use of org.diirt.util.array.ListNumber in project org.csstudio.display.builder by kasemir.
the class FormatOptionHandler method getLongString.
/**
* @param value Array of numbers
* @return String based on character for each array element
*/
private static String getLongString(final VNumberArray value) {
final ListNumber data = value.getData();
final byte[] bytes = new byte[data.size()];
// Copy bytes until end or '\0'
int len = 0;
while (len < bytes.length) {
final byte b = data.getByte(len);
if (b == 0)
break;
else
bytes[len++] = b;
}
// Use actual 'len', not data.size()
return new String(bytes, 0, len, UTF8);
}
use of org.diirt.util.array.ListNumber in project org.csstudio.display.builder by kasemir.
the class FormatOptionHandler method format.
/**
* Format value as string
*
* @param value Value to format
* @param option How to format the value
* @param precision Precision to use. -1 will try to fetch precision from VType
* @param show_units Include units?
* @return Formatted value
*/
public static String format(final VType value, final FormatOption option, int precision, final boolean show_units) {
precision = actualPrecision(value, precision);
if (value == null)
return "<null>";
if (value instanceof VNumber) {
final VNumber number = (VNumber) value;
final String text = formatNumber(number.getValue(), number, option, precision);
if (show_units && !number.getUnits().isEmpty())
return text + " " + number.getUnits();
return text;
} else if (value instanceof VString)
return ((VString) value).getValue();
else if (value instanceof VEnum)
return formatEnum((VEnum) value, option);
else if (value instanceof VNumberArray) {
final VNumberArray array = (VNumberArray) value;
if (option == FormatOption.STRING)
return getLongString(array);
final ListNumber data = array.getData();
if (data.size() <= 0)
return "[]";
final StringBuilder buf = new StringBuilder("[");
buf.append(formatNumber(data.getDouble(0), array, option, precision));
for (int i = 1; i < data.size(); ++i) {
buf.append(", ");
buf.append(formatNumber(data.getDouble(i), array, option, precision));
}
buf.append("]");
if (show_units && !array.getUnits().isEmpty())
buf.append(" ").append(array.getUnits());
return buf.toString();
} else if (value instanceof VEnumArray) {
final List<String> labels = ((VEnumArray) value).getLabels();
final StringBuilder buf = new StringBuilder("[");
for (int i = 0; i < labels.size(); ++i) {
if (i > 0)
buf.append(", ");
buf.append(labels.get(i));
}
buf.append("]");
return buf.toString();
} else if (value instanceof VStringArray)
return StringList.join(((VStringArray) value).getData());
else if (value instanceof VImage) {
final VImage image = (VImage) value;
return "VImage(" + image.getWidth() + " x " + image.getHeight() + ")";
} else if (value instanceof VTable)
return formatTable((VTable) value);
return "<" + value.getClass().getName() + ">";
}
Aggregations