Changed Camera devices to better support Prosilica
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ch.psi</groupId>
|
||||
<artifactId>prosilica</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<name>prosilica</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>pshell</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Generate jar with dependencies -->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/src.xml</descriptor>
|
||||
</descriptors>
|
||||
<!--
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
-->
|
||||
<!-- Copy to PShell folder -->
|
||||
<outputDirectory>../../pshell/home/extensions</outputDirectory>
|
||||
</configuration>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
|
||||
-->
|
||||
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
|
||||
<!-- TODO: a jarjar format would be better -->
|
||||
<id>jar-with-dependencies</id>
|
||||
<formats>
|
||||
<format>jar</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<!-- This is not to include the dependencies of dependencies -->
|
||||
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>true</unpack>
|
||||
<scope>runtime</scope>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,897 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
|
||||
*/
|
||||
package ch.psi.pshell.prosilica;
|
||||
|
||||
import ch.psi.pshell.device.Camera;
|
||||
import ch.psi.pshell.device.CameraBase;
|
||||
import ch.psi.pshell.device.ReadonlyRegister.ReadonlyRegisterArray;
|
||||
import ch.psi.pshell.device.ReadonlyRegisterBase;
|
||||
import ch.psi.pshell.imaging.Source.EmbeddedCameraSource;
|
||||
import ch.psi.pshell.imaging.SourceBase;
|
||||
import ch.psi.pshell.imaging.Renderer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Logger;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import javax.swing.JFrame;
|
||||
import ch.psi.utils.Chrono;
|
||||
import ch.psi.utils.NamedThreadFactory;
|
||||
import ch.psi.utils.State;
|
||||
import ch.psi.utils.Sys;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import prosilica.Pv;
|
||||
|
||||
public class Prosilica extends SourceBase implements EmbeddedCameraSource {
|
||||
|
||||
final long uid;
|
||||
final HashMap<String, Object> pars;
|
||||
final boolean monitor;
|
||||
|
||||
volatile boolean opened;
|
||||
volatile boolean started;
|
||||
|
||||
Pv.tHandle handle;
|
||||
Pv.tFrame[] frames;
|
||||
ByteBuffer brgBuffer;
|
||||
boolean cameraTimeout;
|
||||
long currentUid = -1;
|
||||
String format;
|
||||
|
||||
final int IMAGE_BUFFER_SIZE = 5;
|
||||
|
||||
// constructor
|
||||
public Prosilica(String name, long uid, String pars) {
|
||||
super(name);
|
||||
this.uid = uid;
|
||||
this.monitor = "monitor".equalsIgnoreCase(pars);
|
||||
this.pars = new LinkedHashMap<>();
|
||||
if ((pars != null) && (pars.trim().length() != 0) && !monitor) {
|
||||
for (String token : pars.split(";")) {
|
||||
String[] entry = token.split("=");
|
||||
if ((entry.length == 2) && (!entry[0].trim().isEmpty()) && (!entry[1].trim().isEmpty())) {
|
||||
String parName = entry[0].trim();
|
||||
Object parVal = entry[1].trim();
|
||||
try {
|
||||
parVal = Integer.parseInt((String) parVal);
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
parVal = Float.parseFloat((String) parVal);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
this.pars.put(parName, parVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
setMonitored(true);
|
||||
}
|
||||
|
||||
void writePars() throws IOException {
|
||||
for (String par : pars.keySet()) {
|
||||
writeParameter(par, pars.get(par));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Monitoring
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static ScheduledExecutorService schedulerWatchDog;
|
||||
ScheduledFuture watchDogScheduledFuture;
|
||||
boolean timedOut;
|
||||
|
||||
public void startWatchDogTimer(long timeout) {
|
||||
if (schedulerWatchDog == null) {
|
||||
schedulerWatchDog = Executors.newSingleThreadScheduledExecutor(
|
||||
new NamedThreadFactory("Prosilica watchdog scheduler"));
|
||||
}
|
||||
watchDogScheduledFuture = schedulerWatchDog.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
if (started || timedOut) {
|
||||
Integer age = getAge();
|
||||
if ((age == null) || (age > timeout)) {
|
||||
if (!timedOut) {
|
||||
getLogger().warning("Detected camera timeout - Reinitializing");
|
||||
}
|
||||
timedOut = true;
|
||||
initialize();
|
||||
timedOut = false;
|
||||
getLogger().warning("Camera was successfully reinitialized");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
getLogger().log(Level.FINER, null, ex);
|
||||
}
|
||||
}, timeout, timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void stopWatchDogTimer() {
|
||||
if (watchDogScheduledFuture != null) {
|
||||
watchDogScheduledFuture.cancel(true);
|
||||
watchDogScheduledFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
protected void doInitialize() throws IOException, InterruptedException {
|
||||
super.doInitialize();
|
||||
instances++;
|
||||
doClose();
|
||||
loadPvapi();
|
||||
opened = true;
|
||||
|
||||
try {
|
||||
waitCamera(uid, 5000);
|
||||
|
||||
if (uid > 0) {
|
||||
openCamera(uid);
|
||||
} else {
|
||||
HashMap[] info = getCameras();
|
||||
if (info.length == 0) {
|
||||
throw new IOException("No camera detected");
|
||||
}
|
||||
openCamera((Long) info[0].get("uid"));
|
||||
}
|
||||
setState(State.Ready);
|
||||
writePars();
|
||||
camera.initialize();
|
||||
start();
|
||||
} catch (IOException ex) {
|
||||
getLogger().warning("Error opening the camera: " + ex.getMessage());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doClose() throws IOException {
|
||||
try {
|
||||
if (opened) {
|
||||
opened = false;
|
||||
started = false;
|
||||
instances--;
|
||||
try {
|
||||
stop();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
closeCamera();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
try {
|
||||
camera.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
if (instances == 0) {
|
||||
disposePvapi();
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
super.doClose();
|
||||
}
|
||||
|
||||
private boolean isStreaming() {
|
||||
return (handle != null) && Pv.CaptureQuery(handle);
|
||||
}
|
||||
|
||||
public void start() throws IOException, InterruptedException {
|
||||
assertInitialized();
|
||||
if (started) {
|
||||
return;
|
||||
}
|
||||
pushImage(null);
|
||||
Thread.sleep(1);
|
||||
cameraTimeout = false;
|
||||
this.format = null;
|
||||
Pv.tUint32 width = new Pv.tUint32();
|
||||
Pv.tUint32 height = new Pv.tUint32();
|
||||
Pv.tUint32 length = new Pv.tUint32();
|
||||
Pv.tString format = new Pv.tString();
|
||||
|
||||
if (Pv.AttrUint32Get(handle, "TotalBytesPerFrame", length) != Pv.tError.eSuccess
|
||||
|| Pv.AttrUint32Get(handle, "Width", width) != Pv.tError.eSuccess
|
||||
|| Pv.AttrUint32Get(handle, "Height", height) != Pv.tError.eSuccess
|
||||
|| Pv.AttrEnumGet(handle, "PixelFormat", format) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Error configuring camera");
|
||||
}
|
||||
this.format = format.Value;
|
||||
int imageType;
|
||||
switch (this.format) {
|
||||
case "Mono8":
|
||||
imageType = BufferedImage.TYPE_BYTE_GRAY;
|
||||
case "Mono16":
|
||||
imageType = BufferedImage.TYPE_USHORT_GRAY;
|
||||
default:
|
||||
imageType = BufferedImage.TYPE_3BYTE_BGR;
|
||||
}
|
||||
|
||||
createImageBuffer(IMAGE_BUFFER_SIZE, (int) width.Value, (int) height.Value, imageType);
|
||||
createFrameBuffer(IMAGE_BUFFER_SIZE, (int) length.Value);
|
||||
|
||||
brgBuffer = (imageType == BufferedImage.TYPE_3BYTE_BGR) ? ByteBuffer.allocateDirect((int) width.Value * (int) height.Value * 3 + 5000) : null;
|
||||
|
||||
if (Pv.CaptureStart(handle) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Error starting camera");
|
||||
}
|
||||
|
||||
for (int i = 0; i < IMAGE_BUFFER_SIZE; i++) {
|
||||
if (Pv.CaptureQueueFrame(handle, frames[i], frameListener) != Pv.tError.eSuccess) {
|
||||
//Retry with new buffer
|
||||
Logger.getLogger(Prosilica.class.getName()).warning("Error setting frame queue: retrying with new buffer");
|
||||
frames[i] = new Pv.tFrame();
|
||||
frames[i].ImageBuffer = ByteBuffer.allocateDirect((int) length.Value);
|
||||
if (Pv.CaptureQueueFrame(handle, frames[i], frameListener) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Error setting frame queue");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Pv.CommandRun(handle, "AcquisitionStart") != Pv.tError.eSuccess) {
|
||||
throw new IOException("Error startic acquisition");
|
||||
}
|
||||
started = true;
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
assertInitialized();
|
||||
started = false;
|
||||
currentFrame = null;
|
||||
if (isStreaming()) {
|
||||
Pv.CommandRun(handle, "AcquisitionStop");
|
||||
Pv.CaptureQueueClear(handle);
|
||||
Pv.CaptureEnd(handle);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return started;
|
||||
}
|
||||
|
||||
public HashMap getInfoDict() throws IOException {
|
||||
if (currentUid > 0) {
|
||||
Pv.tCameraInfo info = new Pv.tCameraInfo();
|
||||
Pv.CameraInfo(currentUid, info);
|
||||
return getInfo(info);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static private HashMap getInfo(Pv.tCameraInfo info) {
|
||||
HashMap ret = new HashMap();
|
||||
ret.put("uid", info.UniqueId);
|
||||
ret.put("serial", info.SerialString);
|
||||
ret.put("partno", info.PartNumber);
|
||||
ret.put("version", info.PartVersion);
|
||||
ret.put("access", info.PermittedAccess);
|
||||
ret.put("intid", info.InterfaceId);
|
||||
ret.put("name", info.DisplayName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//PvAPI initialization
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private static int instances = 0;
|
||||
private static boolean loadedPvapi = false;
|
||||
|
||||
private static void loadPvapi() throws IOException {
|
||||
if (loadedPvapi == false) {
|
||||
Logger.getLogger(Prosilica.class.getName()).info("Loading PvAPI");
|
||||
|
||||
if (Pv.Initialize() == Pv.tError.eSuccess) {
|
||||
loadedPvapi = true;
|
||||
} else {
|
||||
throw new IOException("Error loading PvAPI");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void disposePvapi() {
|
||||
if (loadedPvapi) {
|
||||
Logger.getLogger(Prosilica.class.getName()).info("Disposing PvAPI");
|
||||
try {
|
||||
Pv.UnInitialize();
|
||||
loadedPvapi = false;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void waitCamera(Long uid, int timeout) throws IOException, InterruptedException {
|
||||
Chrono chrono = new Chrono();
|
||||
while (true) {
|
||||
for (HashMap info : getCameras()) {
|
||||
if ((uid == null) || uid.equals(info.get("uid"))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((timeout > 0) && chrono.isTimeout(timeout)) {
|
||||
throw new IOException("No camera detected");
|
||||
}
|
||||
Thread.sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Camera selection
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
public static HashMap[] getCameras() {
|
||||
if (loadedPvapi == false) {
|
||||
try {
|
||||
loadPvapi();
|
||||
waitCamera(null, 500);
|
||||
Thread.sleep(100);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
ArrayList<HashMap> ret = new ArrayList<>();
|
||||
|
||||
Pv.tCameraInfo[] cameras = new Pv.tCameraInfo[10];
|
||||
int cameras_count = Pv.CameraList(cameras, 10);
|
||||
for (int i = 0; i < cameras_count; i++) {
|
||||
ret.add(getInfo(cameras[i]));
|
||||
}
|
||||
return ret.toArray(new HashMap[0]);
|
||||
}
|
||||
|
||||
public void openCamera(long uid) throws IOException, InterruptedException {
|
||||
currentUid = uid;
|
||||
if (handle != null) {
|
||||
closeCamera();
|
||||
Thread.sleep(250);
|
||||
}
|
||||
if (uid > 0) {
|
||||
getLogger().info("Open camera " + String.valueOf(uid));
|
||||
if (handle == null) {
|
||||
handle = new Pv.tHandle();
|
||||
}
|
||||
int flags = monitor ? Pv.tAccessFlags.eMonitor : Pv.tAccessFlags.eMaster;
|
||||
if (Pv.CameraOpen(uid, flags, handle) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Error setting camera: " + currentUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void closeCamera() throws IOException {
|
||||
if (handle != null) {
|
||||
getLogger().info("Close camera " + String.valueOf(this.currentUid));
|
||||
try {
|
||||
stop();
|
||||
} catch (Exception ex) {
|
||||
getLogger().log(Level.WARNING, null, ex);
|
||||
}
|
||||
Pv.tError ret = Pv.tError.eUnavailable;
|
||||
ret = Pv.CameraClose(handle);
|
||||
handle = null;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Parameters access
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
public void writeParameter(String name, Object value) throws IOException {
|
||||
if (handle == null) {
|
||||
throw new IOException("Camera not initialized");
|
||||
}
|
||||
if (Pv.AttrExists(handle, name) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Invalid parameter: " + name);
|
||||
}
|
||||
if ((value instanceof Float) || (value instanceof Double)) {
|
||||
Pv.AttrFloat32Set(handle, name, ((Number) value).floatValue());
|
||||
} else if (value instanceof Number) {
|
||||
Pv.AttrUint32Set(handle, name, ((Number) value).intValue());
|
||||
} else if (value instanceof String) {
|
||||
Pv.AttrStringSet(handle, name, (String) value);
|
||||
} else {
|
||||
throw new IOException("Unsuporter type: " + value.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public Object readParameter(String name) throws IOException {
|
||||
if (handle == null) {
|
||||
throw new IOException("Camera not initialized");
|
||||
}
|
||||
if (Pv.AttrExists(handle, name) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Invalid parameter: " + name);
|
||||
}
|
||||
Pv.tFloat32 float_val = new Pv.tFloat32();
|
||||
if (Pv.AttrFloat32Get(handle, name, float_val) == Pv.tError.eSuccess) {
|
||||
return Double.valueOf(float_val.Value);
|
||||
}
|
||||
Pv.tUint32 int_val = new Pv.tUint32();
|
||||
if (Pv.AttrUint32Get(handle, name, int_val) == Pv.tError.eSuccess) {
|
||||
return Integer.valueOf((int) int_val.Value);
|
||||
}
|
||||
Pv.tString str_val = new Pv.tString();
|
||||
if (Pv.AttrStringGet(handle, name, str_val) == Pv.tError.eSuccess) {
|
||||
return str_val.Value;
|
||||
}
|
||||
throw new IOException("Invalid parameter: " + name);
|
||||
}
|
||||
|
||||
public Object readParameterRange(String name) throws IOException {
|
||||
if (handle == null) {
|
||||
throw new IOException("Camera not initialized");
|
||||
}
|
||||
if (Pv.AttrExists(handle, name) != Pv.tError.eSuccess) {
|
||||
throw new IOException("Invalid parameter: " + name);
|
||||
}
|
||||
Pv.tRangeFloat32 rangef = new Pv.tRangeFloat32();
|
||||
if (Pv.AttrRangeFloat32(handle, name, rangef) == Pv.tError.eSuccess) {
|
||||
return new float[]{rangef.Min, rangef.Max};
|
||||
}
|
||||
Pv.tRangeUint32 rangei = new Pv.tRangeUint32();
|
||||
if (Pv.AttrRangeUint32(handle, name, rangei) == Pv.tError.eSuccess) {
|
||||
return new long[]{rangei.Min, rangei.Max};
|
||||
}
|
||||
Pv.tStringsList range = new Pv.tStringsList();
|
||||
if (Pv.AttrRangeEnum(handle, name, range) == Pv.tError.eSuccess) {
|
||||
return range.Array;
|
||||
}
|
||||
throw new IOException("Invalid parameter: " + name);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Image buffer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private BufferedImage[] imageBuffer = null;
|
||||
volatile int imageBufferIndex = 0;
|
||||
|
||||
public HashMap getImageProperties() {
|
||||
HashMap ret = new HashMap();
|
||||
ret.put("buffer", imageBuffer.length);
|
||||
ret.put("width", imageBuffer[0].getWidth());
|
||||
ret.put("height", imageBuffer[0].getHeight());
|
||||
ret.put("type", imageBuffer[0].getType());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void createFrameBuffer(int size, int frame_length) {
|
||||
if ((frames == null) || (frames.length == 0) || (frames.length != size)) {
|
||||
frames = new Pv.tFrame[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
frames[i] = new Pv.tFrame();
|
||||
frames[i].ImageBuffer = ByteBuffer.allocateDirect(frame_length);
|
||||
}
|
||||
} else if (frames[0].ImageBuffer.capacity() < frame_length) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
frames[i].ImageBuffer = ByteBuffer.allocateDirect(frame_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createImageBuffer(int size, int width, int height, int type) {
|
||||
imageBufferIndex = 0;
|
||||
imageBuffer = new BufferedImage[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
imageBuffer[i] = new BufferedImage(width, height, type);
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage getImageFromBuffer() {
|
||||
BufferedImage img = imageBuffer[imageBufferIndex];
|
||||
imageBufferIndex++;
|
||||
if (imageBufferIndex >= imageBuffer.length) {
|
||||
imageBufferIndex = 0;
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Frame event callback
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
volatile Pv.tFrame currentFrame;
|
||||
final Pv.FrameListener frameListener = new Pv.FrameListener() {
|
||||
@Override
|
||||
public void onFrameEvent(Pv.tFrame frame) {
|
||||
synchronized (Prosilica.this) {
|
||||
if (started && (frame.Status != Pv.tError.eCancelled)) {
|
||||
BufferedImage img = getImageFromBuffer();
|
||||
if (convertFrameToImage(frame, img)) {
|
||||
currentFrame = frame;
|
||||
pushImage(img);
|
||||
} else {
|
||||
currentFrame = null;
|
||||
pushImage(null);
|
||||
}
|
||||
Pv.CaptureQueueFrame(handle, frame, this);
|
||||
cameraTimeout = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean convertFrameToImage(Pv.tFrame frame, BufferedImage image) {
|
||||
boolean ret = true;
|
||||
|
||||
if (frame.Format == Pv.tImageFormat.eMono8 || frame.Format == Pv.tImageFormat.eBgr24) {
|
||||
DataBufferByte buffer = (DataBufferByte) image.getRaster().getDataBuffer();
|
||||
byte[] data = buffer.getData();
|
||||
|
||||
if (frame.ImageBuffer.hasArray()) {
|
||||
System.arraycopy(frame.ImageBuffer.array(), 0, data, 0, (int) frame.ImageSize);
|
||||
} else {
|
||||
frame.ImageBuffer.get(data, 0, (int) frame.ImageSize);
|
||||
frame.ImageBuffer.rewind();
|
||||
}
|
||||
} else if (frame.Format == Pv.tImageFormat.eMono16) {
|
||||
DataBufferUShort buffer = (DataBufferUShort) image.getRaster().getDataBuffer();
|
||||
short[] data = buffer.getData();
|
||||
int Shift = frame.BitDepth - 8;
|
||||
|
||||
frame.ImageBuffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
for (int i = 0, j = 0; i < frame.ImageSize; i += 2, j++) {
|
||||
data[j] = (short) (frame.ImageBuffer.getShort(i) << Shift);
|
||||
}
|
||||
|
||||
frame.ImageBuffer.rewind();
|
||||
} else {
|
||||
DataBufferByte buffer = (DataBufferByte) image.getRaster().getDataBuffer();
|
||||
byte[] data = buffer.getData();
|
||||
if (brgBuffer != null) {
|
||||
ret = Pv.FrameToBGRBuffer(frame, brgBuffer) == Pv.tError.eSuccess;
|
||||
if (ret) {
|
||||
brgBuffer.get(data, 0, data.length);
|
||||
brgBuffer.rewind();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Camera interface
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
public Camera getCamera() {
|
||||
return camera;
|
||||
}
|
||||
|
||||
final Camera camera = new CameraBase(Prosilica.this.getName() + " camera") {
|
||||
@Override
|
||||
protected void doStart() throws IOException, InterruptedException {
|
||||
Prosilica.this.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws IOException, InterruptedException {
|
||||
Prosilica.this.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getStarted() throws IOException, InterruptedException {
|
||||
return Prosilica.this.isStarted();
|
||||
}
|
||||
|
||||
class ProsilicaData extends ReadonlyRegisterBase implements ReadonlyRegisterArray {
|
||||
|
||||
@Override
|
||||
protected Object doRead() throws IOException, InterruptedException {
|
||||
if (currentFrame != null) {
|
||||
if (currentFrame.ImageBuffer.hasArray()) {
|
||||
return currentFrame.ImageBuffer.array();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
if (currentFrame != null) {
|
||||
return (int) currentFrame.ImageSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
final ProsilicaData data = new ProsilicaData();
|
||||
|
||||
@Override
|
||||
public ReadonlyRegisterArray getDataArray() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInfo() throws IOException, InterruptedException {
|
||||
HashMap infoDict = getInfoDict();
|
||||
return infoDict == null ? "" : infoDict.get("name") + " - uid: " + infoDict.get("uid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSensorSize() throws IOException, InterruptedException {
|
||||
return new int[]{(Integer) readParameter("SensorWidth"), (Integer) readParameter("SensorHeight")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBinningX(int value) throws IOException, InterruptedException {
|
||||
writeParameter("BinningX", value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBinningX() throws IOException, InterruptedException {
|
||||
return (Integer) readParameter("BinningX");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBinningY(int value) throws IOException, InterruptedException {
|
||||
writeParameter("BinningY", value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBinningY() throws IOException, InterruptedException {
|
||||
return (Integer) readParameter("BinningY");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setROI(int x, int y, int w, int h) throws IOException, InterruptedException {
|
||||
writeParameter("RegionX", 0);
|
||||
writeParameter("RegionY", 0);
|
||||
writeParameter("Height", h);
|
||||
writeParameter("Width", w);
|
||||
writeParameter("RegionX", x);
|
||||
writeParameter("RegionY", y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getROI() throws IOException, InterruptedException {
|
||||
return new int[]{(Integer) readParameter("RegionX"), (Integer) readParameter("RegionY"),
|
||||
(Integer) readParameter("Width"), (Integer) readParameter("Height"),};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGain(double value) throws IOException, InterruptedException {
|
||||
writeParameter("GainValue", (int) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGain() throws IOException, InterruptedException {
|
||||
return (Integer) readParameter("GainValue");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDataType(DataType type) throws IOException, InterruptedException {
|
||||
setPixelFormat(getColorMode(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType() throws IOException, InterruptedException {
|
||||
//TODO: Color mode is linked to EPICS.
|
||||
switch ((String) readParameter("PixelFormat")) {
|
||||
case "Mono8":
|
||||
case "Bayer8":
|
||||
return DataType.UInt8;
|
||||
case "Mono16":
|
||||
case "Bayer16":
|
||||
return DataType.UInt16;
|
||||
case "Rgb24":
|
||||
case "Brg24":
|
||||
return DataType.Int24;
|
||||
case "Rgba32":
|
||||
case "Brga32":
|
||||
return DataType.Int32;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelFormat(ColorMode mode, DataType type) throws IOException {
|
||||
String pixelFormat = null;
|
||||
switch (mode) {
|
||||
case Mono:
|
||||
pixelFormat = "Mono";
|
||||
break;
|
||||
case RGB1:
|
||||
pixelFormat = "Rgb";
|
||||
break;
|
||||
case RGB2:
|
||||
pixelFormat = "Brg";
|
||||
break;
|
||||
case RGB3:
|
||||
pixelFormat = "Bayer";
|
||||
break;
|
||||
}
|
||||
switch (type.getSize()) {
|
||||
case 1:
|
||||
pixelFormat += "8";
|
||||
break;
|
||||
case 2:
|
||||
pixelFormat += "16";
|
||||
break;
|
||||
case 3:
|
||||
pixelFormat += "24";
|
||||
break;
|
||||
case 4:
|
||||
pixelFormat += "a32";
|
||||
break;
|
||||
}
|
||||
writeParameter("PixelFormat", pixelFormat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorMode(ColorMode mode) throws IOException, InterruptedException {
|
||||
setPixelFormat(mode, getDataType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorMode getColorMode() throws IOException, InterruptedException {
|
||||
switch ((String) readParameter("PixelFormat")) {
|
||||
case "Mono8":
|
||||
case "Mono16":
|
||||
return ColorMode.Mono;
|
||||
case "Rgb24":
|
||||
case "Rgba32":
|
||||
return ColorMode.RGB1;
|
||||
case "Brga24":
|
||||
case "Brga32":
|
||||
return ColorMode.RGB2;
|
||||
case "Bayer8":
|
||||
case "Bayer16":
|
||||
return ColorMode.RGB3;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getImageSize() throws IOException, InterruptedException {
|
||||
return new int[]{(Integer) readParameter("Width"), (Integer) readParameter("Height")};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExposure(double value) throws IOException, InterruptedException {
|
||||
writeParameter("ExposureValue", (int) (value * 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExposure() throws IOException, InterruptedException {
|
||||
return ((Integer) readParameter("ExposureValue")).floatValue() / 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAcquirePeriod(double value) throws IOException, InterruptedException {
|
||||
writeParameter("FrameRate", 1000.0 / (value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getAcquirePeriod() throws IOException, InterruptedException {
|
||||
return 1000.0 / ((Double) readParameter("FrameRate"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNumImages(int value) throws IOException, InterruptedException {
|
||||
writeParameter("AcquisitionFrameCount", value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumImages() throws IOException, InterruptedException {
|
||||
return (Integer) readParameter("AcquisitionFrameCount");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIterations(int value) throws IOException, InterruptedException {
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIterations() throws IOException, InterruptedException {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImagesComplete() throws IOException, InterruptedException {
|
||||
return (Integer) readParameter("StatFramesCompleted");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGrabMode(GrabMode value) throws IOException, InterruptedException {
|
||||
String acquisitionMode;
|
||||
switch (value) {
|
||||
case Continuous:
|
||||
acquisitionMode = "Continuous";
|
||||
break;
|
||||
case Single:
|
||||
acquisitionMode = "SingleFrame";
|
||||
break;
|
||||
case Multiple:
|
||||
acquisitionMode = "MultiFrame";
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Not supported mode: " + value);
|
||||
}
|
||||
writeParameter("AcquisitionMode", acquisitionMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrabMode getGrabMode() throws IOException, InterruptedException {
|
||||
switch ((String) readParameter("AcquisitionMode")) {
|
||||
case "Continuous":
|
||||
return GrabMode.Continuous;
|
||||
case "SingleFrame":
|
||||
return GrabMode.Single;
|
||||
case "MultiFrame":
|
||||
return GrabMode.Multiple;
|
||||
case "Recorder":
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTriggerMode(TriggerMode value) throws IOException, InterruptedException {
|
||||
String triggerMode = null;
|
||||
switch (value) {
|
||||
case Free_Run:
|
||||
triggerMode = "Freerun";
|
||||
break;
|
||||
case External:
|
||||
triggerMode = "SyncIn1";
|
||||
break;
|
||||
case Software:
|
||||
triggerMode = "Software";
|
||||
break;
|
||||
case Fixed_Rate:
|
||||
triggerMode = "FixedRate";
|
||||
break;
|
||||
}
|
||||
writeParameter("FrameStartTriggerMode", triggerMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggerMode getTriggerMode() throws IOException, InterruptedException {
|
||||
switch ((String) readParameter("FrameStartTriggerMode")) {
|
||||
case "Freerun":
|
||||
return TriggerMode.Free_Run;
|
||||
case "SyncIn1":
|
||||
return TriggerMode.External;
|
||||
case "Software":
|
||||
return TriggerMode.Software;
|
||||
case "FixedRate":
|
||||
return TriggerMode.Fixed_Rate;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trigger() throws IOException, InterruptedException {
|
||||
Pv.tError ret = Pv.CommandRun(handle, "FrameStartTriggerSoftware");
|
||||
if (ret != Pv.tError.eSuccess) {
|
||||
throw new IOException("Software trigger error: " + ret.toString());
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Sys.addToLibraryPath(new File("home/extensions").getCanonicalPath());
|
||||
//Prosilica prosilica = new Prosilica(null, 25001, "monitor");
|
||||
Prosilica prosilica = new Prosilica(null, 25001, "PacketSize=1504;PixelFormat=Bayer8;AcquisitionMode=Continuous;FrameRate=5.0;AcquisitionFrameCount=1");
|
||||
Prosilica.getCameras();
|
||||
|
||||
JFrame frame = new JFrame("Prosilica");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
Renderer renderer = new Renderer();
|
||||
frame.setSize(640, 480);
|
||||
frame.setContentPane(renderer);
|
||||
frame.setVisible(true);
|
||||
prosilica.startWatchDogTimer(5000);
|
||||
prosilica.initialize();
|
||||
prosilica.addListener(renderer);
|
||||
//renderer.setSource(prosilica);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user