Skip to content

Commit

Permalink
Add ConfiguredCamera handling (untested)
Browse files Browse the repository at this point in the history
  • Loading branch information
datazuul committed Jun 9, 2022
1 parent 92dd899 commit 2c32e68
Show file tree
Hide file tree
Showing 18 changed files with 394 additions and 18 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ This app makes usage of

* NetBeans Platform: <https://netbeans.apache.org/kb/docs/platform/>
* CHDK-PTP-Java Library: <https://github.com/datazuul/CHDK-PTP-Java>
* usb4java-javax: <https://github.com/usb4java/usb4java-javax>
* usb4java-javax: <https://github.com/usb4java/usb4java-javax>
* USB IDs: <http://www.linux-usb.org/usb.ids>
8 changes: 8 additions & 0 deletions eazy-bookscanner-swing/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Eazy BookScanner

OpenSource Book Scanner application for digitizing books with two cameras.
Usage for two digital cameras like described at <http://diybookscanner.org/>.

![Screenshot GUI Eazy BookScanner](./screenshot-20201221.jpg)

## References

* Swing: https://zetcode.com/javaswing/
* Icons: https://www.javacodegeeks.com/2020/03/javafx-tip-32-need-icons-use-ikonli.html
33 changes: 29 additions & 4 deletions eazy-bookscanner-swing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.datazuul</groupId>
<artifactId>eazy-bookscanner-parent</artifactId>
<version>0.2.1-SNAPSHOT</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
</parent>

<name>Eazy BookScanner (Swing)</name>
<groupId>com.datazuul.eazy.bookscanner</groupId>
<artifactId>eazy-bookscanner-swing</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<exec.mainClass>com.datazuul.eazy.bookscanner.App</exec.mainClass>
</properties>
Expand All @@ -23,6 +28,11 @@
<artifactId>CHDK-PTP-Java</artifactId>
<version>0.7.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId>
Expand All @@ -38,5 +48,20 @@
<artifactId>ikonli-swing</artifactId>
<version>12.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>

<build>
<finalName>eazy-bookscanner-${project.version}</finalName>
<plugins>
<!-- Package as an executable jar -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.datazuul.eazy.bookscanner;

import com.datazuul.eazy.bookscanner.devices.CamerasProperties;
import com.datazuul.eazy.bookscanner.gui.ThumbnailsAndScanPanel;
import java.awt.Color;
import java.awt.EventQueue;
Expand All @@ -11,10 +12,22 @@
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
import org.kordamp.ikonli.material2.Material2AL;
import org.kordamp.ikonli.swing.FontIcon;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;

/**
* Implementing ApplicationRunner interface tells Spring Boot to automatically
* call the run method AFTER the application context has been loaded.
*/
@SpringBootApplication
@EnableConfigurationProperties(CamerasProperties.class)
public class App extends JFrame {

public static final int ICON_SIZE = 20;

public static ConfigurableApplicationContext CONTEXT;

public App() {
initUI();
Expand Down Expand Up @@ -71,9 +84,17 @@ private void initUI() {
}

public static void main(String[] args) {
CONTEXT = new SpringApplicationBuilder(App.class).headless(false).run(args);
EventQueue.invokeLater(() -> {
App ex = new App();
App ex = CONTEXT.getBean(App.class);
ex.setVisible(true);
});

logConfig();
}

private static void logConfig() {
CamerasProperties props = CONTEXT.getBean(CamerasProperties.class);
System.out.println(props);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
package com.datazuul.eazy.bookscanner.devices;

import chdk.ptp.java.ICamera;
import chdk.ptp.java.SupportedCamera;
import chdk.ptp.java.connection.CameraUsbDevice;
import javax.usb.UsbDevice;
import com.datazuul.eazy.bookscanner.App;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Component;

@Component
public class CameraFactory {

public static ICamera getCamera(CameraUsbDevice cameraUsbDevice) {
SupportedCamera sc = SupportedCamera.getCamera(cameraUsbDevice.getIdVendor(), cameraUsbDevice.getIdProduct());
if (sc != null) {
// known camera - create specified class
try {
UsbDevice usbDevice = cameraUsbDevice.getDevice();
return sc.getClazz().getConstructor(UsbDevice.class).newInstance(usbDevice);
} catch (Exception ex) {
return null;
CamerasProperties props = App.CONTEXT.getBean(CamerasProperties.class);

Short idVendor = cameraUsbDevice.getIdVendor();
Short idProduct = cameraUsbDevice.getIdProduct();

ConfiguredCamera camera = getCamera(props, idVendor, idProduct, cameraUsbDevice);
return camera;

// SupportedCamera sc = SupportedCamera.getCamera(idVendor, idProduct);
// if (sc != null) {
// // known camera - create specified class
// try {
// UsbDevice usbDevice = cameraUsbDevice.getDevice();
// return sc.getClazz().getConstructor(UsbDevice.class).newInstance(usbDevice);
// } catch (Exception ex) {
// return null;
// }
// }
// return null;
}

private static ConfiguredCamera getCamera(CamerasProperties props, Short idVendor, Short idProduct, CameraUsbDevice cameraUsbDevice) {
List<Vendor> vendors = props.getVendors();
if (vendors != null) {
Vendor vendor = vendors.stream().filter(v -> Objects.equals(idVendor, v.getId())).findAny().orElse(null);
if (vendor != null) {
System.out.println("found vendor: " + vendor);
List<Product> products = vendor.getProducts();
if (products != null) {
Product product = products.stream().filter(p -> Objects.equals(idProduct, p.getId())).findAny().orElse(null);
if (product != null) {
System.out.println("found product: " + product);
return new ConfiguredCamera(cameraUsbDevice.getDevice(), product);
}
}
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.datazuul.eazy.bookscanner.devices;

import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@ConfigurationProperties(prefix = "cameras")
@ConfigurationPropertiesScan
public class CamerasProperties {

private List<Vendor> vendors;

public List<Vendor> getVendors() {
return vendors;
}

public void setVendors(List<Vendor> vendors) {
this.vendors = vendors;
}

@Override
public String toString() {
return "CamerasProperties{" + "vendors=" + vendors + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.datazuul.eazy.bookscanner.devices;

import chdk.ptp.java.camera.FailSafeCamera;
import chdk.ptp.java.exception.GenericCameraException;
import chdk.ptp.java.exception.PTPTimeoutException;
import chdk.ptp.java.model.FocusMode;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.usb.UsbDevice;

public class ConfiguredCamera extends FailSafeCamera {

private Logger log = Logger.getLogger(ConfiguredCamera.class.getName());

private final Product product;

public ConfiguredCamera(UsbDevice device, Product product) {
super(device);
this.product = product;
}

@Override
public void setFocusMode(FocusMode mode) throws GenericCameraException, PTPTimeoutException {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.log(Level.SEVERE, e.getLocalizedMessage(), e);
throw new GenericCameraException(e.getLocalizedMessage());
}

// currently only supporting autofocus mode
if (FocusMode.AUTO.equals(mode)) {
List<FocusModeChange> autofocus = product.getAutofocus();
int currentFocusMode = getFocusMode().getValue();
for (FocusModeChange focusModeChange : autofocus) {
if (currentFocusMode == focusModeChange.getCurrentMode()) {
List<String> commands = focusModeChange.getExecute();
if (commands != null) {
for (String command : commands) {
switch (command) {
case "LEFT":
this.executeLuaCommand("click('left');");
break;
case "RIGHT":
this.executeLuaCommand("click('right');");
break;
case "SET":
this.executeLuaCommand("click('set');");
break;
default:
break;
}
if (command.startsWith("sleep")) {
long milliseconds = Long.valueOf(command.substring(5));
try {
Thread.sleep(milliseconds);
} catch (InterruptedException ex) {
log.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
throw new GenericCameraException(ex.getLocalizedMessage());
}
}
}
}
// activate auto focus and focus
try {
this.executeLuaCommand("set_aflock(0);");
this.executeLuaCommand("press('shoot_half');");
Thread.sleep(800);
this.executeLuaCommand("release('shoot_half');");
this.executeLuaCommand("set_aflock(1);");
Thread.sleep(1000);
} catch (InterruptedException ex) {
log.log(Level.SEVERE, ex.getLocalizedMessage(), ex);
throw new GenericCameraException(ex.getLocalizedMessage());
}
}
}
}
}

@Override
public void setZoom(int zoomPosition) throws PTPTimeoutException, GenericCameraException {
Zoom zoom = product.getZoom();
if (zoom != null) {
List<String> preExecute = zoom.getPreExecute();
for (String command : preExecute) {
switch (command) {
case "SET_AUTOFOCUS":
setFocusMode(FocusMode.AUTO);
break;
default:
break;
}
}
}
super.setZoom(zoomPosition);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.datazuul.eazy.bookscanner.devices;

import java.util.List;

public class FocusModeChange {

private int currentMode;
private List<String> execute;

public int getCurrentMode() {
return currentMode;
}

public List<String> getExecute() {
return execute;
}

public void setCurrentMode(int currentMode) {
this.currentMode = currentMode;
}

public void setExecute(List<String> execute) {
this.execute = execute;
}

@Override
public String toString() {
return "FocusModeChange{" + "currentMode=" + currentMode + ", execute=" + execute + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.datazuul.eazy.bookscanner.devices;

import java.util.List;

public class Product {

private List<FocusModeChange> autofocus;
private Short id;
private String name;
private Zoom zoom;

public List<FocusModeChange> getAutofocus() {
return autofocus;
}

public Short getId() {
return id;
}

public String getName() {
return name;
}

public Zoom getZoom() {
return zoom;
}

public void setAutofocus(List<FocusModeChange> autofocus) {
this.autofocus = autofocus;
}

public void setId(Short id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}

public void setZoom(Zoom zoom) {
this.zoom = zoom;
}

@Override
public String toString() {
return "Product{" + "autofocus=" + autofocus + ", id=" + id + ", name=" + name + ", zoom=" + zoom + '}';
}
}
Loading

0 comments on commit 2c32e68

Please sign in to comment.