package presentation.controller;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicReference;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import com.github.sarxos.webcam.Webcam;
import javax.imageio.ImageIO;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.stage.WindowEvent;
import presentation.MainApp;
import presentation.utils.FileUtil;
/**
* This is controller for WebCamPreview FXML.
*/
public class WebCamPreviewController extends BaseController implements Initializable {
@FXML
public StackPane stackPaneWebCamPage;
@FXML
public Button btnTakePhoto;
@FXML
public StackPane bpWebCamPaneHolder;
@FXML
public ImageView imgWebCamCapturedImage;
private WebCamInfo webCamInfo;
private class WebCamInfo {
private String webCamName;
private int webCamIndex;
public String getWebCamName() {
return webCamName;
}
public void setWebCamName(String webCamName) {
this.webCamName = webCamName;
}
public int getWebCamIndex() {
return webCamIndex;
}
public void setWebCamIndex(int webCamIndex) {
this.webCamIndex = webCamIndex;
}
@Override
public String toString() {
return webCamName;
}
}
private boolean cameraStop = false;
private BufferedImage grabbedImage;
private Webcam selWebCam = null;
private ObjectProperty<Image> imageProperty = new SimpleObjectProperty<>();
private FileUtil fileUtil;
private final String TMP_IMAGE_NAME = "image%s.png";
public WebCamPreviewController() {
this.fileUtil = new FileUtil();
}
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
setUp();
}
public void setUp() {
btnTakePhoto.setVisible(false);
webCamInfo = new WebCamInfo();
webCamInfo.setWebCamIndex(0);
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
starWebCam(webCamInfo.getWebCamIndex());
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
MainApp.primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
closeCamera();
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
});
}
private void starWebCam(final int webCamIndex) {
initializeWebCam(webCamIndex);
Platform.runLater(new Runnable() {
@Override
public void run() {
setImageViewSize();
}
});
}
private void setImageViewSize() {
double height = bpWebCamPaneHolder.getHeight();
double width = bpWebCamPaneHolder.getWidth();
imgWebCamCapturedImage.setFitHeight(height);
imgWebCamCapturedImage.setFitWidth(width);
imgWebCamCapturedImage.prefHeight(height);
imgWebCamCapturedImage.prefWidth(width);
imgWebCamCapturedImage.setPreserveRatio(true);
}
private void initializeWebCam(final int webCamIndex) {
if (selWebCam != null) {
closeCamera();
}
selWebCam = Webcam.getWebcams().get(webCamIndex);
selWebCam.setViewSize(new Dimension(640,480));
selWebCam.open();
startWebCamStream();
}
private void startWebCamStream() {
cameraStop = false;
btnTakePhoto.setVisible(true);
Task<Void> webCamStreamTask = new Task<Void>() {
@Override
protected Void call() throws Exception {
final AtomicReference<WritableImage> ref = new AtomicReference<>();
while (!cameraStop) {
try {
if ((grabbedImage = selWebCam.getImage()) != null) {
Platform.runLater(new Runnable() {
@Override
public void run() {
final Image mainImage = SwingFXUtils.toFXImage(grabbedImage, null);
imageProperty.set(mainImage);
}
});
grabbedImage.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
};
Thread th = new Thread(webCamStreamTask);
th.setDaemon(true);
th.start();
imgWebCamCapturedImage.imageProperty().bind(imageProperty);
imgWebCamCapturedImage.setVisible(true);
}
private void closeCamera() {
cameraStop = true;
Webcam.getDiscoveryService().stop();
selWebCam.close();
}
public void takePhotoBtn(ActionEvent event) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
takePhoto();
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
private void takePhoto() {
btnTakePhoto.setVisible(false);
fileUtil.makeTmpDir();
try {
ArrayList<String> imageNames = new ArrayList<>();
for (int i = 1; i <= 15; i++) {
BufferedImage image = selWebCam.getImage();
String saveImagePath = buildSavingImagePath(i);
ImageIO.write(image, "PNG", new File(saveImagePath));
imageNames.add(buildSaveImageName(i));
}
fileUtil.createImageZip(imageNames);
} catch(IOException e) {
e.printStackTrace();
}
closeCamera();
}
private String buildSavingImagePath(int index) {
return FileUtil.TMP_DIR_NAME + "/" + buildSaveImageName(index);
}
private String buildSaveImageName(int index) {
return String.format(TMP_IMAGE_NAME, index);
}
}