|
|
@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.control; |
|
|
|
import com.github.sarxos.webcam.Webcam; |
|
|
|
import com.github.sarxos.webcam.WebcamListener; |
|
|
|
import com.github.sarxos.webcam.WebcamResolution; |
|
|
|
import com.github.sarxos.webcam.WebcamUpdater; |
|
|
|
import com.google.zxing.*; |
|
|
|
import com.google.zxing.client.j2se.BufferedImageLuminanceSource; |
|
|
|
import com.google.zxing.common.HybridBinarizer; |
|
|
@ -10,7 +11,7 @@ import javafx.beans.property.BooleanProperty; |
|
|
|
import javafx.beans.property.ObjectProperty; |
|
|
|
import javafx.beans.property.SimpleBooleanProperty; |
|
|
|
import javafx.beans.property.SimpleObjectProperty; |
|
|
|
import javafx.concurrent.Service; |
|
|
|
import javafx.concurrent.ScheduledService; |
|
|
|
import javafx.concurrent.Task; |
|
|
|
import javafx.embed.swing.SwingFXUtils; |
|
|
|
import javafx.scene.image.Image; |
|
|
@ -19,16 +20,24 @@ import java.awt.image.BufferedImage; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
public class WebcamService extends Service<Image> { |
|
|
|
public class WebcamService extends ScheduledService<Image> { |
|
|
|
private WebcamResolution resolution; |
|
|
|
private final WebcamListener listener; |
|
|
|
private BooleanProperty opening = new SimpleBooleanProperty(false); |
|
|
|
private final WebcamUpdater.DelayCalculator delayCalculator; |
|
|
|
private final BooleanProperty opening = new SimpleBooleanProperty(false); |
|
|
|
|
|
|
|
private final ObjectProperty<Result> resultProperty = new SimpleObjectProperty<>(null); |
|
|
|
|
|
|
|
public WebcamService(WebcamResolution resolution, WebcamListener listener) { |
|
|
|
private static final int QR_SAMPLE_PERIOD_MILLIS = 400; |
|
|
|
|
|
|
|
private Webcam cam; |
|
|
|
private long lastQrSampleTime; |
|
|
|
|
|
|
|
public WebcamService(WebcamResolution resolution, WebcamListener listener, WebcamUpdater.DelayCalculator delayCalculator) { |
|
|
|
this.resolution = resolution; |
|
|
|
this.listener = listener; |
|
|
|
this.delayCalculator = delayCalculator; |
|
|
|
this.lastQrSampleTime = System.currentTimeMillis(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
@ -36,35 +45,52 @@ public class WebcamService extends Service<Image> { |
|
|
|
return new Task<Image>() { |
|
|
|
@Override |
|
|
|
protected Image call() throws Exception { |
|
|
|
Webcam cam = Webcam.getWebcams(1, TimeUnit.MINUTES).get(0); |
|
|
|
try { |
|
|
|
cam.setCustomViewSizes(resolution.getSize()); |
|
|
|
cam.setViewSize(resolution.getSize()); |
|
|
|
if(!Arrays.asList(cam.getWebcamListeners()).contains(listener)) { |
|
|
|
cam.addWebcamListener(listener); |
|
|
|
if(cam == null) { |
|
|
|
cam = Webcam.getWebcams(1, TimeUnit.MINUTES).get(0); |
|
|
|
cam.setCustomViewSizes(resolution.getSize()); |
|
|
|
cam.setViewSize(resolution.getSize()); |
|
|
|
if(!Arrays.asList(cam.getWebcamListeners()).contains(listener)) { |
|
|
|
cam.addWebcamListener(listener); |
|
|
|
} |
|
|
|
|
|
|
|
opening.set(true); |
|
|
|
cam.open(true, delayCalculator); |
|
|
|
opening.set(false); |
|
|
|
} |
|
|
|
|
|
|
|
opening.set(true); |
|
|
|
cam.open(); |
|
|
|
opening.set(false); |
|
|
|
while(!isCancelled()) { |
|
|
|
if(cam.isImageNew()) { |
|
|
|
BufferedImage bimg = cam.getImage(); |
|
|
|
updateValue(SwingFXUtils.toFXImage(bimg, null)); |
|
|
|
readQR(bimg); |
|
|
|
} |
|
|
|
BufferedImage bimg = cam.getImage(); |
|
|
|
Image image = SwingFXUtils.toFXImage(bimg, null); |
|
|
|
updateValue(image); |
|
|
|
|
|
|
|
if(System.currentTimeMillis() > (lastQrSampleTime + QR_SAMPLE_PERIOD_MILLIS)) { |
|
|
|
readQR(bimg); |
|
|
|
lastQrSampleTime = System.currentTimeMillis(); |
|
|
|
} |
|
|
|
return getValue(); |
|
|
|
|
|
|
|
return image; |
|
|
|
} finally { |
|
|
|
opening.set(false); |
|
|
|
if(!cam.close()) { |
|
|
|
cam.close(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void reset() { |
|
|
|
cam = null; |
|
|
|
super.reset(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean cancel() { |
|
|
|
if(cam != null && !cam.close()) { |
|
|
|
cam.close(); |
|
|
|
} |
|
|
|
|
|
|
|
return super.cancel(); |
|
|
|
} |
|
|
|
|
|
|
|
private void readQR(BufferedImage bufferedImage) { |
|
|
|
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage); |
|
|
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); |
|
|
|