Compare commits

29 Commits

Author SHA1 Message Date
c4d3153bd1 commit 30/10/2025 2025-10-30 08:57:31 +07:00
0b389afe62 commit 03/10/2025 2025-10-03 11:00:51 +07:00
d5fbd2bc0a commit 03/10/2025 2025-10-03 08:09:04 +07:00
1ef8af4d42 commit 30/09/2025 2025-09-30 09:51:24 +07:00
1fd1b4a5ac commit 30/09/2025 2025-09-30 09:50:48 +07:00
f557828cda commit 27/08/2025 2025-09-30 09:20:43 +07:00
668a477289 commit 27/08/2025 2025-08-27 13:02:06 +07:00
8f85e3fccd commit 22/08/2025 2025-08-22 08:11:36 +07:00
f7c74304f5 commit 18/08/2025 2025-08-18 16:27:27 +07:00
d566e4bc4f commit 25/07/2025 2025-07-25 09:32:00 +07:00
49ac4353b3 commit 22/07/2025 2025-07-22 11:33:13 +07:00
3539fb7d65 commit 10/07/2025 2025-07-10 08:48:12 +07:00
e4d2bfa00e commit 27/2025
Tambah Crop Setting
2025-06-30 16:31:57 +07:00
0728ae3ca2 commit 27/2025
Tambah Crop Setting
2025-05-27 14:47:52 +07:00
957d642f5d commit 27/2025
Tambah Crop Setting
2025-05-27 12:38:38 +07:00
3d02641479 commit 27/2025
Tambah Crop Setting
2025-05-27 11:28:56 +07:00
d0fe8123e9 commit 27/2025
Tambah Crop Setting
2025-05-27 11:26:29 +07:00
9e69714ae1 commit 26/05/2025
Tambah Crop Setting
2025-05-26 15:05:02 +07:00
9effe8a7a9 commit 26/05/2025
Tambah Crop Setting
2025-05-26 14:21:22 +07:00
rdkartono
1fcd905b07 commit 22/05/2025 2025-05-22 11:25:54 +07:00
rdkartono
ee0a82aa32 commit 21/05/2025 2025-05-21 15:42:09 +07:00
rdkartono
d1a6dd9f98 commit 21/05/2025 2025-05-21 15:35:18 +07:00
rdkartono
e47e1252fb Merge branch 'master' of https://gitea.rdkartono.my.id/rdkartono/ErhaCam 2025-05-20 10:32:55 +07:00
rdkartono
ef94f87d8a revisi 09/05/2025
Detectors.java :
* scaleFactor 1.05 become 1.2
* minNeighbors 3 become 5
* haarcascade_frontalface_default.xml become haarcascade_frontalface_alt.xml
CaptureView.java :
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber) become OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(CAP_DSHOW+devicenumber);

MainApplication.java :
stage.setTitle("MultiCam Capture App for ERHA 09052025-001")
2025-05-20 10:32:38 +07:00
5f2093a572 commit 19/05/2025 2025-05-20 09:41:36 +07:00
2dfd149990 commit 19/05/2025 2025-05-19 14:09:39 +07:00
rdkartono
4e3381edc4 Merge branch 'master' of https://gitea.rdkartono.my.id/rdkartono/ErhaCam
# Conflicts:
#	out/artifacts/ErhaCam_jar/ErhaCam.jar
2025-05-13 15:19:48 +07:00
rdkartono
1d617a0559 revisi 09/05/2025
Detectors.java :
* scaleFactor 1.05 become 1.2
* minNeighbors 3 become 5
* haarcascade_frontalface_default.xml become haarcascade_frontalface_alt.xml
CaptureView.java :
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber) become OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(CAP_DSHOW+devicenumber);

MainApplication.java :
stage.setTitle("MultiCam Capture App for ERHA 09052025-001")
2025-05-13 15:19:29 +07:00
bc6821a33e Commit 13052025
Old Photo Deleter .
2025-05-13 14:52:26 +07:00
56 changed files with 68682 additions and 849 deletions

3
.gitignore vendored
View File

@@ -2,6 +2,9 @@ target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
logs/
out/
hs_err*.log
### IntelliJ IDEA ###
.idea/modules.xml

52
.idea/artifacts/Dermies.xml generated Normal file
View File

@@ -0,0 +1,52 @@
<component name="ArtifactManager">
<artifact type="jar" name="Dermies">
<output-path>$PROJECT_DIR$/out/artifacts/Dermies</output-path>
<root id="archive" name="Dermies.jar">
<element id="module-output" name="ErhaCam" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.1/controlsfx-11.2.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect2/0.2.0-1.5.9/libfreenect2-0.2.0-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg/6.1.1-1.5.10/ffmpeg-6.1.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/beust/jcommander/1.82/jcommander-1.82.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.27.0/error_prone_annotations-2.27.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/core/3.5.3/core-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/flycapture/2.13.3.31-1.5.9/flycapture-2.13.3.31-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/leptonica/1.84.1-1.5.10/leptonica-1.84.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas/0.3.26-1.5.10/openblas-0.3.26-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-net/commons-net/3.11.1/commons-net-3.11.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect/0.5.7-1.5.9/libfreenect-0.5.7-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/java/dev/jna/jna/5.15.0/jna-5.15.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-impl/2.7.0/tinylog-impl-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.30/lombok-1.18.30.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/jai-imageio/jai-imageio-core/1.4.0/jai-imageio-core-1.4.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/xerial/sqlite-jdbc/3.46.0.0/sqlite-jdbc-3.46.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas/0.3.26-1.5.10/openblas-0.3.26-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/tesseract/5.3.4-1.5.10/tesseract-5.3.4-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense2/2.53.1-1.5.9/librealsense2-2.53.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/javase/3.5.3/javase-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libdc1394/2.2.6-1.5.9/libdc1394-2.2.6-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-jcl/1.7.36/slf4j-jcl-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/artoolkitplus/2.3.1-1.5.9/artoolkitplus-2.3.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg/6.1.1-1.5.10/ffmpeg-6.1.1-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense/1.12.4-1.5.9/librealsense-1.12.4-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacv/1.5.10/javacv-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-api/2.7.0/tinylog-api-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9-windows-x86_64.jar" path-in-jar="/" />
</root>
</artifact>
</component>

6
.idea/copilot.data.migration.agent.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

6
.idea/copilot.data.migration.ask.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

6
.idea/copilot.data.migration.edit.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@@ -1,9 +1,10 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
<inspection_tool class="AutoCloseableResource" enabled="false" level="WARNING" enabled_by_default="false">
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,java.util.concurrent.Executors,newFixedThreadPool" />
</inspection_tool>
<inspection_tool class="ClassEscapesItsScope" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CommentedOutCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="minLines" value="3" />
</inspection_tool>
@@ -15,5 +16,6 @@
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedReturnValue" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

BIN
IU photoboth-01.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
IU photoboth-02.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

BIN
banners/WelcomeDermies.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

View File

@@ -1,9 +1,29 @@
#Thu Apr 10 16:17:13 ICT 2025
AudioPhase1=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase2.mp3
AudioPhase3=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase3.mp3
AudioPhase4=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase4.mp3
AudioPhase5=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase5.mp3
#Wed Aug 27 11:07:31 WIB 2025
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase2.mp3
AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase3.mp3
AudioPhase4=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase4.mp3
AudioPhase5=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase5.mp3
Cam1BottomCrop=20.0
Cam1LeftCrop=8.0
Cam1RightCrop=8.0
Cam1TopCrop=10.0
Cam2BottomCrop=20.0
Cam2LeftCrop=8.0
Cam2RightCrop=8.0
Cam2TopCrop=10.0
Cam3BottomCrop=20.0
Cam3LeftCrop=8.0
Cam3RightCrop=8.0
Cam3TopCrop=10.0
Cam4BottomCrop=20.0
Cam4LeftCrop=8.0
Cam4RightCrop=8.0
Cam4TopCrop=10.0
Cam5BottomCrop=20.0
Cam5LeftCrop=8.0
Cam5RightCrop=8.0
Cam5TopCrop=10.0
CameraCenter=
CameraConfigCenter={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft45={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
@@ -19,11 +39,12 @@ FTPPass=password
FTPPath=/
FTPPort=21
FTPUser=user
FlipCamera=true
MirrorCamera=true
PhotoDirectory=C\:\\Users\\Erha\\Desktop\\ErhaCapture
SharpnessThreshold=1000.0
cascadeMaxSize=500
FlipCamera=false
MirrorCamera=false
PhotoDirectory=D\:\\Capture
Production=false
SharpnessThreshold=850.0
cascadeMaxSize=360
cascadeMinNeighbors=3
cascadeMinSize=250
cascadeScaleFactor=1.1
cascadeScaleFactor=1.05

Binary file not shown.

12213
haarcascade_eye.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

29690
haarcascade_profileface.xml Normal file

File diff suppressed because it is too large Load Diff

BIN
hubungistafkami.wav Normal file

Binary file not shown.

View File

@@ -47,6 +47,16 @@
2024-10-21 15:28:21 INFO: GetAll success, result count: 36
2024-10-21 15:28:25 INFO: Not loading empty fxml file
2024-10-21 15:28:25 INFO: Application closed
2025-03-24 16:03:28 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam
2025-03-24 16:03:28 INFO: Config.ConfigFile.Load() Load config file at C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\config.properties
2025-03-24 16:03:28 INFO: Config.ConfigFile.Load() Config Loaded
2025-03-24 16:03:29 INFO: Config.SomeCodes.LoadQRReader() QRReader loaded
2025-03-24 16:03:30 INFO: Config.SomeCodes.LoadFaceDetector() FaceDetector loaded
2025-03-24 16:03:30 INFO: id.co.gtc.erhacam.MainApplication.start() Application started
2025-03-24 16:03:31 INFO: Database.Sqlite.CreateDatabase() Database created successfully
2025-03-24 16:03:31 INFO: Database.Sqlite.GetAll() GetAll success, result count: 55
2025-03-24 16:04:08 INFO: id.co.gtc.erhacam.MainView.loadContent() Not loading empty fxml file
2025-03-24 16:04:08 INFO: id.co.gtc.erhacam.MainApplication.lambda$start$0() Application closed
2025-03-21 14:43:56 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\Erha\IdeaProjects\ErhaCam
2025-03-21 14:43:56 INFO: Config.ConfigFile.Load() Load config file at C:\Users\Erha\IdeaProjects\ErhaCam\config.properties
2025-03-21 14:43:56 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() FaceMaxSize created with value : 500
@@ -426,3 +436,59 @@
2025-03-21 16:08:12 ERROR: id.co.gtc.erhacam.CaptureView.call() Record associated with barcode
2025-03-21 16:08:33 INFO: id.co.gtc.erhacam.CaptureView.onPlaybackStarted() Audio Positikan Muka Started
2025-03-21 16:08:40 INFO: id.co.gtc.erhacam.CaptureView.onPlaybackFinished() Audio Positikan Muka Finished
2025-03-24 16:05:16 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam
2025-03-24 16:05:16 INFO: Config.ConfigFile.Load() Load config file at C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\config.properties
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() FaceMaxSize created with value : 500
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() EyeMaxSize created with value : 83
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMinSize() FaceMinSize created with value : 250
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMinSize() EyeMinSize created with value : 41
2025-03-24 16:05:16 INFO: Config.ConfigFile.Load() Config Loaded
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\FullQuality, Msg : C:\Users\Erha
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\FullQualityCrop, Msg : C:\Users\Erha
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\Compressed, Msg : C:\Users\Erha
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\CompressedCrop, Msg : C:\Users\Erha
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\thumbs, Msg : C:\Users\Erha
2025-03-24 16:05:17 INFO: id.co.gtc.erhacam.MainApplication.start() Secure Dongle UserID valid
2025-03-24 16:05:18 INFO: id.co.gtc.erhacam.CaptureView.initialize() Audio Player : Inited
2025-03-24 16:05:19 INFO: Config.SomeCodes.LoadQRReader() QRReader loaded
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadFrontalFaceDetector() Face Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_frontalface_alt.xml
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadFrontalFaceDetector() FaceDetector loaded
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadEyeDetector() Eye Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_eye.xml
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadEyeDetector() EyeDetector loaded
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadProfileFaceDetector() Profile Face Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_profileface.xml
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadProfileFaceDetector() ProfileFaceDetector loaded
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.MainApplication.start() Application started
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.lambda$initialize$13() Left90 Index: 1
2025-03-24 16:05:20 INFO: SecureDongle.SecureDongle.lambda$StartMonitor$0() Start Monitoring UserID=14022025
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : QR Reader loaded
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : Face detector loaded
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.initialize() Found 3 Cameras
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : ACER QHD User Facing to camera list
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : OBSBOT Meet 2 StreamCamera to camera list
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : OBSBOT Virtual Camera to camera list
2025-03-24 16:05:31 INFO: Database.Sqlite.CreateDatabase() Database created successfully
2025-03-24 16:05:31 INFO: Database.Sqlite.GetAll() GetAll success, result count: 90
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.initialize() Audio Player : Inited
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.lambda$initialize$13() Left90 Index: 1
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : QR Reader loaded
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : Face detector loaded
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\IdeaProjects\ErhaCam\thumbs\240980 2025-3-24_12-38-45 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_13-50-34 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-41-17 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-49-11 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-50-41 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-12-36 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-26-18 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-36-34 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-37-53 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
2025-03-24 16:07:13 ERROR: id.co.gtc.erhacam.MainView.loadContent() loadContent Not loading empty fxml file
2025-03-24 16:07:13 INFO: id.co.gtc.erhacam.MainApplication.lambda$start$0() Application closed

Binary file not shown.

View File

@@ -1,6 +1,6 @@
package Config;
import id.co.gtc.erhacam.Detectors;
import id.co.gtc.erhacam.MainApplication;
import lombok.Getter;
import org.tinylog.Logger;
@@ -47,9 +47,35 @@ public class ConfigFile {
private @Getter boolean MirrorCamera = false;
private @Getter boolean FlipCamera = false;
private @Getter boolean isProduction = true;
private @Getter double SharpnessThreshold;
private @Getter final double topcropmax = 30.0;
private @Getter final double bottomcropmax = 30.0;
private @Getter final double leftcropmax = 30.0;
private @Getter final double rightcropmax = 30.0;
private @Getter double Cam1TopCrop = 10.0;
private @Getter double Cam1BottomCrop = 20.0;
private @Getter double Cam1LeftCrop = 8.0;
private @Getter double Cam1RightCrop = 8.0;
private @Getter double Cam2TopCrop = 10.0;
private @Getter double Cam2BottomCrop = 20.0;
private @Getter double Cam2LeftCrop = 8.0;
private @Getter double Cam2RightCrop = 8.0;
private @Getter double Cam3TopCrop = 10.0;
private @Getter double Cam3BottomCrop = 20.0;
private @Getter double Cam3LeftCrop = 8.0;
private @Getter double Cam3RightCrop = 8.0;
private @Getter double Cam4TopCrop = 10.0;
private @Getter double Cam4BottomCrop = 20.0;
private @Getter double Cam4LeftCrop = 8.0;
private @Getter double Cam4RightCrop = 8.0;
private @Getter double Cam5TopCrop = 10.0;
private @Getter double Cam5BottomCrop = 20.0;
private @Getter double Cam5LeftCrop = 10.0;
private @Getter double Cam5RightCrop = 10.0;
private boolean needsave = false;
public ConfigFile(){
@@ -58,6 +84,195 @@ public class ConfigFile {
Load();
}
public void setAPI(boolean isProduction){
if (this.isProduction != isProduction){
this.isProduction = isProduction;
needsave = true;
}
}
public void setCam1TopCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam1TopCrop && v <= topcropmax && v >= 0.0){
Cam1TopCrop = v;
needsave = true;
}
}
}
public void setCam1BottomCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam1BottomCrop && v <= bottomcropmax && v >= 0.0){
Cam1BottomCrop = v;
needsave = true;
}
}
}
public void setCam1LeftCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam1LeftCrop && v <= leftcropmax && v >= 0.0){
Cam1LeftCrop = v;
needsave = true;
}
}
}
public void setCam1RightCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam1RightCrop && v <= rightcropmax && v >= 0.0){
Cam1RightCrop = v;
needsave = true;
}
}
}
public void setCam2TopCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam2TopCrop && v <= topcropmax && v >= 0.0){
Cam2TopCrop = v;
needsave = true;
}
}
}
public void setCam2BottomCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam2BottomCrop && v <= bottomcropmax && v >= 0.0){
Cam2BottomCrop = v;
needsave = true;
}
}
}
public void setCam2LeftCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam2LeftCrop && v <= leftcropmax && v >= 0.0){
Cam2LeftCrop = v;
needsave = true;
}
}
}
public void setCam2RightCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam2RightCrop && v <= rightcropmax && v >= 0.0){
Cam2RightCrop = v;
needsave = true;
}
}
}
public void setCam3TopCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam3TopCrop && v <= topcropmax && v >= 0.0){
Cam3TopCrop = v;
needsave = true;
}
}
}
public void setCam3BottomCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam3BottomCrop && v <= bottomcropmax && v >= 0.0){
Cam3BottomCrop = v;
needsave = true;
}
}
}
public void setCam3LeftCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam3LeftCrop && v <= leftcropmax && v >= 0.0){
Cam3LeftCrop = v;
needsave = true;
}
}
}
public void setCam3RightCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam3RightCrop && v <= rightcropmax && v >= 0.0){
Cam3RightCrop = v;
needsave = true;
}
}
}
public void setCam4TopCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam4TopCrop && v <= topcropmax && v >= 0.0){
Cam4TopCrop = v;
needsave = true;
}
}
}
public void setCam4BottomCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam4BottomCrop && v <= bottomcropmax && v >= 0.0){
Cam4BottomCrop = v;
needsave = true;
}
}
}
public void setCam4LeftCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam4LeftCrop && v <= leftcropmax && v >= 0.0){
Cam4LeftCrop = v;
needsave = true;
}
}
}
public void setCam4RightCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam4RightCrop && v <= rightcropmax && v >= 0.0){
Cam4RightCrop = v;
needsave = true;
}
}
}
public void setCam5TopCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam5TopCrop && v <= topcropmax && v >= 0.0){
Cam5TopCrop = v;
needsave = true;
}
}
}
public void setCam5BottomCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam5BottomCrop && v <= bottomcropmax && v >= 0.0){
Cam5BottomCrop = v;
needsave = true;
}
}
}
public void setCam5LeftCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam5LeftCrop && v <= leftcropmax && v >= 0.0){
Cam5LeftCrop = v;
needsave = true;
}
}
}
public void setCam5RightCrop(String value){
if (ValidDouble(value)){
double v = toDouble(value);
if (v != Cam5RightCrop && v <= rightcropmax && v >= 0.0){
Cam5RightCrop = v;
needsave = true;
}
}
}
public void setMirrorCamera(boolean value){
if (MirrorCamera != value){
MirrorCamera = value;
@@ -583,6 +798,7 @@ public class ConfigFile {
if (prop.getProperty("MirrorCamera") == null) allcorrect = false;
if (prop.getProperty("FlipCamera") == null) allcorrect = false;
if (prop.getProperty("SharpnessThreshold") == null) allcorrect = false;
if (prop.getProperty("Production") == null) allcorrect = false;
if (prop.getProperty(CameraConfigEnum.CameraConfigLeft90.toString()) == null) allcorrect = false;
@@ -596,6 +812,28 @@ public class ConfigFile {
if (prop.getProperty("cascadeMinSize") == null) allcorrect = false;
if (prop.getProperty("cascadeMaxSize") == null) allcorrect = false;
if (prop.getProperty("Cam1TopCrop") == null) allcorrect = false;
if (prop.getProperty("Cam1BottomCrop") == null) allcorrect = false;
if (prop.getProperty("Cam1LeftCrop") == null) allcorrect = false;
if (prop.getProperty("Cam1RightCrop") == null) allcorrect = false;
if (prop.getProperty("Cam2TopCrop") == null) allcorrect = false;
if (prop.getProperty("Cam2BottomCrop") == null) allcorrect = false;
if (prop.getProperty("Cam2LeftCrop") == null) allcorrect = false;
if (prop.getProperty("Cam2RightCrop") == null) allcorrect = false;
if (prop.getProperty("Cam3TopCrop") == null) allcorrect = false;
if (prop.getProperty("Cam3BottomCrop") == null) allcorrect = false;
if (prop.getProperty("Cam3LeftCrop") == null) allcorrect = false;
if (prop.getProperty("Cam3RightCrop") == null) allcorrect = false;
if (prop.getProperty("Cam4TopCrop") == null) allcorrect = false;
if (prop.getProperty("Cam4BottomCrop") == null) allcorrect = false;
if (prop.getProperty("Cam4LeftCrop") == null) allcorrect = false;
if (prop.getProperty("Cam4RightCrop") == null) allcorrect = false;
if (prop.getProperty("Cam5TopCrop") == null) allcorrect = false;
if (prop.getProperty("Cam5BottomCrop") == null) allcorrect = false;
if (prop.getProperty("Cam5LeftCrop") == null) allcorrect = false;
if (prop.getProperty("Cam5RightCrop") == null) allcorrect = false;
if (allcorrect){
AudioPhase1 = prop.getProperty("AudioPhase1");
AudioPhase2 = prop.getProperty("AudioPhase2");
@@ -622,20 +860,55 @@ public class ConfigFile {
ConfigRight45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()), CameraConfig.class);
ConfigRight90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()), CameraConfig.class);
cascadeScaleFactor = toDouble(prop.getProperty("cascadeScaleFactor"));
cascadeScaleFactor = cascadetoDouble(prop.getProperty("cascadeScaleFactor"));
cascadeMinNeighbors = toInt(prop.getProperty("cascadeMinNeighbors"));
cascadeMinSize = toInt(prop.getProperty("cascadeMinSize"));
cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize"));
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
if (MainApplication.detectorsList!=null){
MainApplication.detectorsList.forEach((i, d) -> {
if (d != null) {
System.out.println("Setting face detection parameters for detector: " + i);
d.setFaceMaxSize(cascadeMaxSize);
d.setFaceMinSize(cascadeMinSize);
d.setScaleFactor(cascadeScaleFactor);
}
});
}
// Detectors.setFaceMaxSize(cascadeMaxSize);
// Detectors.setFaceMinSize(cascadeMinSize);
// Detectors.setScaleFactor(cascadeScaleFactor);
MirrorCamera = toBoolean(prop.getProperty("MirrorCamera"));
FlipCamera = toBoolean(prop.getProperty("FlipCamera"));
isProduction = toBoolean(prop.getProperty("Production"));
SharpnessThreshold = toDouble(prop.getProperty("SharpnessThreshold"));
Cam1TopCrop = toDouble(prop.getProperty("Cam1TopCrop"));
Cam1BottomCrop = toDouble(prop.getProperty("Cam1BottomCrop"));
Cam1LeftCrop = toDouble(prop.getProperty("Cam1LeftCrop"));
Cam1RightCrop = toDouble(prop.getProperty("Cam1RightCrop"));
Cam2TopCrop = toDouble(prop.getProperty("Cam2TopCrop"));
Cam2BottomCrop = toDouble(prop.getProperty("Cam2BottomCrop"));
Cam2LeftCrop = toDouble(prop.getProperty("Cam2LeftCrop"));
Cam2RightCrop = toDouble(prop.getProperty("Cam2RightCrop"));
Cam3TopCrop = toDouble(prop.getProperty("Cam3TopCrop"));
Cam3BottomCrop = toDouble(prop.getProperty("Cam3BottomCrop"));
Cam3LeftCrop = toDouble(prop.getProperty("Cam3LeftCrop"));
Cam3RightCrop = toDouble(prop.getProperty("Cam3RightCrop"));
Cam4TopCrop = toDouble(prop.getProperty("Cam4TopCrop"));
Cam4BottomCrop = toDouble(prop.getProperty("Cam4BottomCrop"));
Cam4LeftCrop = toDouble(prop.getProperty("Cam4LeftCrop"));
Cam4RightCrop = toDouble(prop.getProperty("Cam4RightCrop"));
Cam5TopCrop = toDouble(prop.getProperty("Cam5TopCrop"));
Cam5BottomCrop = toDouble(prop.getProperty("Cam5BottomCrop"));
Cam5LeftCrop = toDouble(prop.getProperty("Cam5LeftCrop"));
Cam5RightCrop = toDouble(prop.getProperty("Cam5RightCrop"));
Logger.info("Config Loaded");
MakeDirectories();
return;
@@ -651,7 +924,7 @@ public class ConfigFile {
CreateDefault();
}
private double toDouble(String cascadeScaleFactor) {
private double cascadetoDouble(String cascadeScaleFactor) {
try{
return Double.parseDouble(cascadeScaleFactor);
} catch (Exception e){
@@ -659,6 +932,14 @@ public class ConfigFile {
}
}
private double toDouble(String value) {
try{
return Double.parseDouble(value);
} catch (Exception e){
return 0.0;
}
}
private void CreateDefault(){
AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString();
AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString();
@@ -675,22 +956,56 @@ public class ConfigFile {
FTPUser = "user";
FTPPass = "password";
FTPPath = "/";
PhotoDirectory = currentDirectory;
PhotoDirectory = "D:\\Capture";
SetDefaultCameraConfig(ConfigLeft90);
SetDefaultCameraConfig(ConfigLeft45);
SetDefaultCameraConfig(ConfigCenter);
SetDefaultCameraConfig(ConfigRight45);
SetDefaultCameraConfig(ConfigRight90);
cascadeScaleFactor = 1.1;
cascadeScaleFactor = 1.05;
cascadeMinNeighbors = 3;
cascadeMinSize = 250;
cascadeMaxSize = 500;
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
cascadeMaxSize = 360;
if (MainApplication.detectorsList!= null) MainApplication.detectorsList.forEach((i, d) -> {
if (d != null) {
d.setFaceMaxSize(cascadeMaxSize);
d.setFaceMinSize(cascadeMinSize);
d.setScaleFactor(cascadeScaleFactor);
}
});
// Detectors.setFaceMaxSize(cascadeMaxSize);
// Detectors.setFaceMinSize(cascadeMinSize);
// Detectors.setScaleFactor(cascadeScaleFactor);
MirrorCamera = false;
FlipCamera = false;
SharpnessThreshold = 300.0;
isProduction = true;
SharpnessThreshold = 850.0;
Cam1TopCrop = 10.0;
Cam1BottomCrop = 20.0;
Cam1LeftCrop = 8.0;
Cam1RightCrop = 8.0;
Cam2TopCrop = 10.0;
Cam2BottomCrop = 20.0;
Cam2LeftCrop = 8.0;
Cam2RightCrop = 8.0;
Cam3TopCrop = 10.0;
Cam3BottomCrop = 20.0;
Cam3LeftCrop = 8.0;
Cam3RightCrop = 8.0;
Cam4TopCrop = 10.0;
Cam4BottomCrop = 20.0;
Cam4LeftCrop = 8.0;
Cam4RightCrop = 8.0;
Cam5TopCrop = 10.0;
Cam5BottomCrop = 20.0;
Cam5LeftCrop = 8.0;
Cam5RightCrop = 8.0;
Logger.info("Default Config Created");
needsave = true;
Save();
@@ -749,8 +1064,31 @@ public class ConfigFile {
prop.setProperty("MirrorCamera", String.valueOf(MirrorCamera));
prop.setProperty("FlipCamera", String.valueOf(FlipCamera));
prop.setProperty("Production", String.valueOf(isProduction));
prop.setProperty("SharpnessThreshold", String.valueOf(SharpnessThreshold));
prop.setProperty("Cam1TopCrop", String.valueOf(Cam1TopCrop));
prop.setProperty("Cam1BottomCrop", String.valueOf(Cam1BottomCrop));
prop.setProperty("Cam1LeftCrop", String.valueOf(Cam1LeftCrop));
prop.setProperty("Cam1RightCrop", String.valueOf(Cam1RightCrop));
prop.setProperty("Cam2TopCrop", String.valueOf(Cam2TopCrop));
prop.setProperty("Cam2BottomCrop", String.valueOf(Cam2BottomCrop));
prop.setProperty("Cam2LeftCrop", String.valueOf(Cam2LeftCrop));
prop.setProperty("Cam2RightCrop", String.valueOf(Cam2RightCrop));
prop.setProperty("Cam3TopCrop", String.valueOf(Cam3TopCrop));
prop.setProperty("Cam3BottomCrop", String.valueOf(Cam3BottomCrop));
prop.setProperty("Cam3LeftCrop", String.valueOf(Cam3LeftCrop));
prop.setProperty("Cam3RightCrop", String.valueOf(Cam3RightCrop));
prop.setProperty("Cam4TopCrop", String.valueOf(Cam4TopCrop));
prop.setProperty("Cam4BottomCrop", String.valueOf(Cam4BottomCrop));
prop.setProperty("Cam4LeftCrop", String.valueOf(Cam4LeftCrop));
prop.setProperty("Cam4RightCrop", String.valueOf(Cam4RightCrop));
prop.setProperty("Cam5TopCrop", String.valueOf(Cam5TopCrop));
prop.setProperty("Cam5BottomCrop", String.valueOf(Cam5BottomCrop));
prop.setProperty("Cam5LeftCrop", String.valueOf(Cam5LeftCrop));
prop.setProperty("Cam5RightCrop", String.valueOf(Cam5RightCrop));
try{
prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null);
Logger.info("Config Saved");

View File

@@ -12,6 +12,8 @@ import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import lombok.NonNull;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
@@ -34,15 +36,22 @@ import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import static org.bytedeco.opencv.global.opencv_core.CV_64F;
@SuppressWarnings("unused")
public class SomeCodes {
// dermiesMode = true means for Dermies Clinic, false means for Erha Clinic
public static boolean DermiesMode = false;
public final static String currentDirectory = System.getProperty("user.dir");
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final Java2DFrameConverter converter = new Java2DFrameConverter();
@@ -143,6 +152,19 @@ public class SomeCodes {
}
}
public static void WaitAsync(long millis, String threadname, Consumer<Void> success){
Thread thread = new Thread(()->{
try {
Thread.sleep(millis);
} catch (Exception ignored){ }
if (success != null) success.accept(null);
});
thread.setName(threadname);
thread.setDaemon(true);
thread.start();
}
/**
* Make thumbfile from source jpg file
* @param sourcejpg source jpg file
@@ -182,6 +204,74 @@ public class SomeCodes {
return x.format(dtf);
}
public static LocalDateTime StringToLocalDateTime(String x){
if (ValidString(x)){
try{
return LocalDateTime.parse(x, dtf);
} catch (Exception e){
Logger.error("Error parsing date: "+x+", Msg : "+e.getMessage());
}
}
return null;
}
public static LocalDateTime GetCreationTime(Path p){
try{
BasicFileAttributes attr = Files.readAttributes(p, BasicFileAttributes.class);
FileTime ft = attr.creationTime();
return LocalDateTime.ofInstant(ft.toInstant(), java.time.ZoneId.systemDefault());
} catch (Exception e){
Logger.error("Error getting creation time: "+p+", Msg : "+e.getMessage());
}
return null;
}
public static @NonNull Path[] GetFilesInDirectory(String path) {
if (ValidDirectory(path)) {
try{
return Files.list(Path.of(path))
.filter(Files::isRegularFile)
.toArray(Path[]::new);
} catch (Exception ignored){}
}
return new Path[0];
}
public static boolean Delete(String... path){
if (path!=null && path.length>0){
Boolean[] result = new Boolean[path.length];
for(int i=0; i<path.length; i++){
try{
result[i] = Files.deleteIfExists(Path.of(path[i]));
if (result[i]) Logger.info("Delete: "+path[i]);
} catch (Exception e){
result[i] = false;
Logger.error("Error deleting file: "+path[i]+", Msg : "+e.getMessage());
}
}
return Arrays.stream(result).allMatch(x->x);
}
return false;
}
public static boolean Delete(Path... path){
if (path!=null && path.length>0){
Boolean[] result = new Boolean[path.length];
for(int i=0; i<path.length; i++){
try{
result[i] = Files.deleteIfExists(path[i]);
if (result[i]) Logger.info("Delete: "+path[i]);
} catch (Exception e){
result[i] = false;
Logger.error("Error deleting file: "+path[i]+", Msg : "+e.getMessage());
}
}
return Arrays.stream(result).allMatch(x->x);
}
return false;
}
/**
* Extract resource file to current directory
* @param filename resource file name
@@ -557,7 +647,7 @@ public class SomeCodes {
* Check if Region of Interest 1 is same with Region of Interest 2
* @param ROI1 Region of Interest 1
* @param ROI2 Region of Interest 2
* @return true if same, false if not same
* @return true if same, false if different
*/
public static boolean IsSameROI(Rect ROI1, Rect ROI2){
if (ValidROI(ROI1) && ValidROI(ROI2)){
@@ -692,7 +782,7 @@ public class SomeCodes {
public static double CalculateSharpness(String filename){
if (ValidFile(filename)){
try(Mat mat = opencv_imgcodecs.imread(filename)){
return CalculateSharpness(new UMat(mat));
return CalculateSharpness(mat);
} catch (Exception e){
Logger.error("Error calculating sharpness: "+filename+", Msg : "+e.getMessage());
}
@@ -730,23 +820,23 @@ public class SomeCodes {
* @param mat image in UMat format, expected in gray scale
* @return sharpness value
*/
public static double CalculateSharpness(UMat mat){
public static double CalculateSharpness(Mat mat){
if (mat!=null && !mat.empty()){
if (mat.channels()!=1){
UMat grey = new UMat();
Mat grey = new Mat();
opencv_imgproc.cvtColor(mat, grey, opencv_imgproc.COLOR_BGR2GRAY);
mat = grey;
}
opencv_imgproc.equalizeHist(mat, mat);
UMat laplacian = new UMat();
Mat laplacian = new Mat();
opencv_imgproc.Laplacian(mat, laplacian, CV_64F);
UMat mean = new UMat(1,1, CV_64F);
UMat stddev = new UMat(1,1, CV_64F);
Mat mean = new Mat(1,1, CV_64F);
Mat stddev = new Mat(1,1, CV_64F);
opencv_core.meanStdDev(laplacian, mean, stddev);
@@ -761,7 +851,7 @@ public class SomeCodes {
return 0;
}
public static boolean IsBlurred(UMat mat, double threshold){
public static boolean IsBlurred(Mat mat, double threshold){
return CalculateSharpness(mat)<threshold;
}
@@ -793,4 +883,30 @@ public class SomeCodes {
mat.data().get(data);
return image;
}
/**
* Close Stage if not null
* and wait until closed
* @param obj Stage object to close
*/
public static void closeStage(Stage obj) throws InterruptedException {
if (obj != null) {
if (Platform.isFxApplicationThread()) {
// Already on FX thread, just close directly
obj.close();
} else {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
try {
obj.close();
} finally {
latch.countDown();
}
});
// Wait for runLater task to finish
latch.await();
}
}
}
}

View File

@@ -0,0 +1,125 @@
package Database;
import Config.SomeCodes;
import org.tinylog.Logger;
import java.nio.file.Path;
import java.time.LocalDateTime;
/**
* PhotoCleaner class
* Responsible for deleting photos older than a certain number of days
*/
public class PhotoCleaner {
private final int days;
private final boolean[] started;
/**
* PhotoCleaner constructor
* @param days how many days old photos to delete
*/
public PhotoCleaner(int days){
this.days = days;
this.started = new boolean[]{false};
}
/**
* Start PhotoCleaner Thread
*/
@SuppressWarnings("BusyWait")
public void Start(){
Thread thread = new Thread(() -> {
started[0] = true;
while (started[0]) {
try {
System.out.println("Rechecking Database for older photos...");
// Delete photos older than the specified number of days
LocalDateTime now = LocalDateTime.now();
// delete from database
Thread sqldelete = new Thread(()->{
Sqlite sql = new Sqlite();
PhotoReviewClass[] prcs = sql.GetAll();
for (PhotoReviewClass prc : prcs) {
if (!started[0]) break;
if (prc != null && prc.getDateTime() != null) {
LocalDateTime ldt = SomeCodes.StringToLocalDateTime(prc.getDateTime());
if (ldt!=null){
if (ldt.isBefore(now.minusDays(days))) {
SomeCodes.Delete(prc.fullres());
SomeCodes.Delete(prc.cropped());
SomeCodes.Delete(prc.compressed());
SomeCodes.Delete(prc.compressedcrop());
SomeCodes.Delete(prc.thumbnails());
sql.Delete(prc);
Logger.info("Deleted PhotoReviewClass: " + prc.getDateTime() + " " + prc.getPrefix());
}
}
}
}
});
RunThread(sqldelete, "DeleteFromDatabase");
// delete from disk
Thread deletefullres = new Thread(new DiskDeleter(SomeCodes.config.getFullQualityDirectory()));
RunThread(deletefullres, "DeleteFullRes");
Thread deletefullrescrop = new Thread(new DiskDeleter(SomeCodes.config.getFullQualityCropDirectory()));
RunThread(deletefullrescrop, "DeleteFullResCrop");
Thread deletecompressed = new Thread(new DiskDeleter(SomeCodes.config.getCompressedDirectory()));
RunThread(deletecompressed, "DeleteCompressed");
Thread deletecompressedcrop = new Thread(new DiskDeleter(SomeCodes.config.getCompressedCropDirectory()));
RunThread(deletecompressedcrop, "DeleteCompressedCrop");
Thread deletethumbnails = new Thread(new DiskDeleter(SomeCodes.config.getThumbsDirectory()));
RunThread(deletethumbnails, "DeleteThumbnails");
// Sleep for 1 hour
Thread.sleep(60 * 60 * 1000);
} catch (Exception e) {
Logger.error("Error in PhotoCleaner Thread: " + e.getMessage());
}
}
System.out.println("PhotoCleaner stopped");
});
thread.setName("PhotoCleaner Thread");
thread.setDaemon(true);
thread.start();
}
private void RunThread(Thread thread, String name){
thread.setName(name);
thread.setDaemon(true);
thread.start();
}
class DiskDeleter implements Runnable{
private final String path;
private final LocalDateTime now ;
public DiskDeleter(String path){
this.path = path;
this.now = LocalDateTime.now();
}
public void run(){
Path[] ppp = SomeCodes.GetFilesInDirectory(path);
if (ppp != null){
for(Path p : ppp){
if (!started[0]) break;
LocalDateTime ldt = SomeCodes.GetCreationTime(p);
if (ldt != null) {
if (ldt.isBefore(now.minusDays(days))) {
SomeCodes.Delete(p);
}
}
}
}
}
}
/**
* Stop PhotoCleaner Thread
*/
public void Stop(){
started[0] = false;
}
}

View File

@@ -2,6 +2,8 @@ package Database;
import lombok.Data;
import java.time.LocalDateTime;
import static Config.SomeCodes.MakeArray;
@Data

View File

@@ -40,13 +40,32 @@ public class Sqlite {
*/
public void Insert(PhotoReviewClass pr){
if (pr!=null){
// System.out.println("Inserting PhotoReviewClass");
// System.out.println(pr);
Insert(pr.getPrefix(), pr.getFileLeft90(), pr.getFileLeft45(), pr.getFileCenter(), pr.getFileRight45(), pr.getFileRight90(), pr.getThumbLeft90(), pr.getThumbLeft45(), pr.getThumbCenter(), pr.getThumbRight45(), pr.getThumbRight90());
}
}
/**
* Delete PhotoReviewClass object from database
* @param pr PhotoReviewClass objects
*/
public void Delete(PhotoReviewClass... pr){
if (pr!=null && pr.length>0){
try{
Connection conn = GetConnection();
if (conn != null){
for (PhotoReviewClass photo : pr) {
PreparedStatement stmt = conn.prepareStatement("DELETE FROM photos WHERE id = ?");
stmt.setInt(1, photo.getId());
stmt.execute();
}
conn.close();
Logger.info("Data deleted successfully");
} else Logger.info("Delete failed, connection is null");
} catch (Exception e){
Logger.error("Error deleting data: "+e.getMessage());
}
}
}
/**
* Get all PhotoReviewClass object from database
@@ -108,14 +127,6 @@ public class Sqlite {
try{
Connection conn = GetConnection();
if (conn != null){
// System.out.println("Inserting data");
// System.out.println("prefix: "+prefix);
// System.out.println("fileLeft90: "+fileLeft90);
// System.out.println("fileLeft45: "+fileLeft45);
// System.out.println("fileCenter: "+fileCenter);
// System.out.println("fileRight45: "+fileRight45);
// System.out.println("fileRight90: "+fileRight90);
PreparedStatement stmt = conn.prepareStatement("INSERT INTO photos (DateTime, Prefix, FileLeft90, FileLeft45, FileCenter, FileRight45, FileRight90, ThumbLeft90, ThumbLeft45, ThumbCenter, ThumbRight45, ThumbRight90 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setString(1, LocalDateTimeToString(LocalDateTime.now()));
stmt.setString(2, ValidString(prefix)?prefix:"");

View File

@@ -0,0 +1,10 @@
package ErhaAPI;
import lombok.Data;
@Data
public class BarcodeHttpResult {
private int statusCode;
private String body;
private BarcodeResult result;
}

View File

@@ -1,7 +1,7 @@
package ErhaAPI;
public class BarcodeResullt {
public class BarcodeResult {
public int currentPage;
public int limit;
public int totalPages;

View File

@@ -3,15 +3,19 @@ package ErhaAPI;
import Config.SomeCodes;
import com.google.gson.Gson;
import lombok.Getter;
import lombok.NonNull;
import org.tinylog.Logger;
import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.net.URI;
import java.net.UnknownHostException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpTimeoutException;
import java.nio.file.Files;
import java.util.Base64;
import java.util.UUID;
@@ -23,10 +27,8 @@ public class ErhaAPI {
private @Getter String API_USERNAME = "erha-pb-001";
private @Getter String API_PASSWORD = "bM0tH!s";
private String auth;
private final String API_URL;
private String API_URL="";
private final Gson gson = new Gson();
@@ -35,11 +37,27 @@ public class ErhaAPI {
* @param isProduction if true will use Production URL, if false will use Staging URL
*/
public ErhaAPI(boolean isProduction){
setProduction(isProduction);
}
public void setProduction(boolean isProduction){
final String API_URL_PROD = "https://connect-api.aryanoble.co.id/api";
final String API_URL_STAGING = "https://connect-api-staging.aryanoble.web.id/api";
API_URL = isProduction ? API_URL_PROD : API_URL_STAGING;
if (isProduction){
if (!API_URL.equals(API_URL_PROD)){
API_URL = API_URL_PROD;
update_auth();
}
} else {
if (!API_URL.equals(API_URL_STAGING)){
API_URL = API_URL_STAGING;
update_auth();
}
}
}
/**
* Set API Username
* @param API_USERNAME API Username
@@ -68,22 +86,29 @@ public class ErhaAPI {
}
}
/**
* Validate Barcode data
* @param Barcode Barcode to verify
* @return BarcodeResullt object if success, or null if failed
* @return BarcodeHttpResult object
*/
public BarcodeResullt Validate_Barcode(String Barcode, boolean printdebug){
public @NonNull BarcodeHttpResult Validate_Barcode(String Barcode, boolean printdebug){
BarcodeHttpResult bhr = new BarcodeHttpResult();
if (ValidBarCode(Barcode)){
System.out.println("Checking Barcode : " + Barcode +" on "+(config.isProduction()?"Production":"Staging")+" API " );
try (HttpClient client = HttpClient.newHttpClient()) {
int medical_record_detail_id = toInt(Barcode);
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(API_URL+"/photobooth/photobooth/" + medical_record_detail_id))
.uri(java.net.URI.create(API_URL+ (DermiesMode ? "/photobooth/dermies/":"/photobooth/photobooth/") + medical_record_detail_id))
.header("Authorization", "Basic " + auth)
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
bhr.setStatusCode(response.statusCode());
bhr.setBody(response.body());
if (response.statusCode()==200){
String body = response.body();
if (printdebug){
@@ -91,22 +116,36 @@ public class ErhaAPI {
System.out.println("Validate_Barcode HTTP body : ");
System.out.println(body);
}
return gson.fromJson(body, BarcodeResullt.class);
BarcodeResult brr = gson.fromJson(body, BarcodeResult.class);
bhr.setResult(brr);
} else {
Logger.error("Validate_Barcode failed, status code : " , response.statusCode());
System.out.println("Validate Barcode status code : " + response.statusCode());
}
} catch (IOException e) {
System.out.println("Validate_Barcode IO Exception, Msg : " + e.getMessage());
Logger.error("Validate_Barcode IO Exception, Msg : " , e.getMessage());
} catch (InterruptedException e) {
System.out.println("Validate_Barcode Interrupted Exception, Msg : " + e.getMessage());
Logger.error("Validate_Barcode Interrupted Exception, Msg : " , e.getMessage());
} catch (UnknownHostException e) {
// no internet or no DNS
Logger.error("Validate_Barcode UnknownHostException, Msg : " , e.getMessage());
bhr.setStatusCode(0);
bhr.setBody("No internet connection or DNS error");
} catch (ConnectException e) {
// connection refused
Logger.error("Validate_Barcode ConnectException , Msg : " , e.getMessage());
bhr.setStatusCode(-1);
bhr.setBody("Connection refused");
} catch( HttpTimeoutException e){
// timeout
Logger.error("Validate_Barcode HttpTimeoutException, Msg : " , e.getMessage());
bhr.setStatusCode(408);
bhr.setBody("Http Request timeout");
} catch (IOException | InterruptedException e) {
// generic network error
Logger.error("Validate_Barcode IOException/InterruptedException, Msg : " , e.getMessage());
bhr.setStatusCode(-2);
bhr.setBody("Network error: " + e.getMessage());
}
}
return null;
return bhr;
}
@@ -116,9 +155,10 @@ public class ErhaAPI {
* Upload File
* @param patientID Patient ID
* @param filename File to upload
* @return null if failed, or response body if success
* @return UploadHttpResult object
*/
public UploadResult Upload_File(String patientID, String filename, boolean printdebug) {
public @NonNull UploadHttpResult Upload_File(String patientID, String filename, boolean printdebug) {
UploadHttpResult uhr = new UploadHttpResult();
if (ValidMedicalRecordId(patientID)){
int medical_record_detail_id = toInt(patientID);
if (ValidFile(filename)){
@@ -151,9 +191,9 @@ public class ErhaAPI {
endBoundary.getBytes()
);
System.out.println("Uploading file : " + filename + " to " + (config.isProduction()?"Production":"Staging")+" API ");
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(API_URL + "/photobooth/photobooth"))
.uri(new URI(API_URL + (DermiesMode ?"/photobooth/dermies":"/photobooth/photobooth")))
.header("Authorization", "Basic " + auth)
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(multipartData))
@@ -162,6 +202,8 @@ public class ErhaAPI {
// Send request
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
uhr.setStatusCode(response.statusCode());
uhr.setBody(response.body());
if (printdebug){
System.out.println("Upload_File status code : " + response.statusCode());
System.out.println("Upload_File HTTP body : ");
@@ -170,21 +212,20 @@ public class ErhaAPI {
if (response.statusCode()==200){
return gson.fromJson(response.body(), UploadResult.class);
UploadResult ur = gson.fromJson(response.body(), UploadResult.class);
uhr.setResult(ur);
} else {
System.out.println("Upload_File status code : " + response.statusCode());
Logger.error("Upload_File file ",filename," failed, status code : " , response.statusCode());
}
} catch (Exception e){
System.out.println("Upload_File Exception, Msg : " + e.getMessage());
Logger.error("Upload_File file ",filename," failed, Exception, Msg : " , e.getMessage());
}
}
}
return null;
return uhr;
}

View File

@@ -0,0 +1,10 @@
package ErhaAPI;
import lombok.Data;
@Data
public class UploadHttpResult {
int statusCode;
String body;
UploadResult result;
}

View File

@@ -76,7 +76,6 @@ public class SecureDongle {
if (result== LibSecureDongle.ERR_SUCCESS){
HardwareID = lp1[0];
//System.out.println("SecureDongle found with HardwareID="+HardwareID);
return true;
} else {
if (event!=null) event.onDongleError("Find", result);
@@ -135,10 +134,9 @@ public class SecureDongle {
System.arraycopy(data, 0, buffer, 0, length);
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" write success ");
return true;
} else if (event!=null) event.onDongleError("Write", result);
} //else System.out.println("SecureDongle not opened");
}
return false;
}
@@ -160,12 +158,11 @@ public class SecureDongle {
p2[0] = Length;
short result = SD.SecureDongle(LibSecureDongle.SD_READ, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" read success ");
byte[] data = new byte[Length];
System.arraycopy(buffer, 0, data, 0, Length);
return data;
} else if (event!=null) event.onDongleError("Read", result);
} //else System.out.println("SecureDongle not opened");
}
return new byte[0];
}
@@ -181,14 +178,13 @@ public class SecureDongle {
handle[0] = Handle;
short result = SD.SecureDongle(LibSecureDongle.SD_RANDOM, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" generate random success ");
random[0] = p1[0];
random[1] = p2[0];
random[2] = p3[0];
random[3] = p4[0];
return random;
} else if (event!=null) event.onDongleError("GenerateRandomNumber", result);
} //else System.out.println("SecureDongle not opened");
}
return random;
}
@@ -205,11 +201,10 @@ public class SecureDongle {
lp1[0] = UserID;
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE_USERID, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" set UserID success ");
this.UserID = UserID;
return true;
} else if (event!=null) event.onDongleError("WriteUserID", result);
} //else System.out.println("SecureDongle not opened");
}
return false;
}
@@ -224,10 +219,9 @@ public class SecureDongle {
short result = SD.SecureDongle(LibSecureDongle.SD_READ_USERID, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
this.UserID = lp1[0];
//System.out.println("SecureDongle HardwareID="+HardwareID+" read UserID success, value = "+UserID);
return UserID;
} else if (event!=null) event.onDongleError("ReadUserID", result);
} //else System.out.println("SecureDongle not opened");
}
return 0;
}

View File

@@ -5,24 +5,22 @@ import javafx.animation.PauseTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.*;
import javafx.util.Duration;
import org.tinylog.Logger;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import static Config.SomeCodes.*;
@@ -43,10 +41,16 @@ public class AutoCloseAlert {
private static Circle Cam5;
public static void init(){
String f_01 = ExtractResource("/IU photoboth-01.jpg");
System.out.println("Banner 01 extracted as file: "+f_01);
String f_01;
if (DermiesMode){
f_01 = ExtractResource("/WelcomeDermies.jpg");
} else {
f_01 = ExtractResource("/IU photoboth-01.jpg");
}
//System.out.println("Banner 01 extracted as file: "+f_01);
String f_02 = ExtractResource("/IU photoboth-02.jpg");
System.out.println("Banner 02 extracted as file: "+f_02);
//System.out.println("Banner 02 extracted as file: "+f_02);
banner_01 = LoadImage(f_01);
if (banner_01!=null) System.out.println("Banner 01 loaded"); else System.out.println("Banner 01 not loaded");
banner_02 = LoadImage(f_02);
@@ -54,17 +58,20 @@ public class AutoCloseAlert {
Cam1 = new Circle(10, Color.RED);
Cam2 = new Circle(10, Color.RED);
Cam3 = new Circle(10, Color.RED);
if (!DermiesMode){
Cam4 = new Circle(10, Color.RED);
Cam5 = new Circle(10, Color.RED);
}
}
public static void ChangeCamStatus(int id, boolean active){
Circle x = switch (id){
case 1 -> Cam1;
case 2 -> Cam2;
case 3 -> Cam3;
case 4 -> Cam4;
case 5 -> Cam5;
case 4 -> DermiesMode? null: Cam4;
case 5 -> DermiesMode ? null : Cam5;
default -> null;
};
if (x!=null){
@@ -82,8 +89,16 @@ public class AutoCloseAlert {
* Close the current alert if it is shown
*/
public static void close(){
Optional.ofNullable(currentAlertStage).ifPresent(Stage::close);
if (currentAlertStage!=null){
try {
closeStage(currentAlertStage);
} catch (InterruptedException e) {
Logger.error("Error closing alert stage: " + e.getMessage());
}
currentAlertStage = null;
}
clear();
}
@@ -186,7 +201,12 @@ public class AutoCloseAlert {
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), event -> alertStage.show()));
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(seconds* (pictures.length)), event -> {
alertStage.close();
try {
closeStage(alertStage);
} catch (InterruptedException e) {
Logger.error("Error closing alert stage: " + e.getMessage());
}
//alertStage.close();
if (currentAlertStage == alertStage) {
currentAlertStage = null;
}
@@ -225,7 +245,8 @@ public class AutoCloseAlert {
imageView.setSmooth(true);
stackPane.getChildren().add(imageView);
}
HBox CamStatus = new HBox(30, Cam1, Cam2, Cam3, Cam4, Cam5);
HBox CamStatus = DermiesMode ? new HBox(30, Cam1, Cam2, Cam3) : new HBox(30, Cam1, Cam2, Cam3, Cam4, Cam5);
CamStatus.setMinHeight(60);
CamStatus.setAlignment(Pos.CENTER);
@@ -275,26 +296,37 @@ public class AutoCloseAlert {
double screenwidth = Screen.getPrimary().getBounds().getWidth();
double screenheight = Screen.getPrimary().getBounds().getHeight();
double height = screenheight/4;
double width = height * 21/9;
double height = screenheight/4.0;
double width = height * 21.0/9.0;
VBox root = new VBox(10);
root.setPadding(new Insets(12));
root.setPrefSize(width, height);
root.setAlignment(Pos.CENTER);
List<Node> children = new ArrayList<>();
if (ValidString(header)){
Label headerLabel = new Label(header);
headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 28px;");
headerLabel.setWrapText(true);
headerLabel.setMinHeight(height*0.25);
children.add(headerLabel);
headerLabel.setMaxWidth(Double.MAX_VALUE);
headerLabel.prefWidthProperty().bind(root.widthProperty());
root.getChildren().add(headerLabel);
}
if (ValidString(content)){
Label contentLabel = new Label(content);
contentLabel.setWrapText(true);
contentLabel.setStyle("-fx-font-size: 24px;");
contentLabel.setMinHeight(height*0.75);
children.add(contentLabel);
contentLabel.setMaxWidth(Double.MAX_VALUE);
contentLabel.prefWidthProperty().bind(root.widthProperty());
VBox.setVgrow(contentLabel, Priority.ALWAYS);
contentLabel.setAlignment(Pos.TOP_CENTER);
root.getChildren().add(contentLabel);
}
VBox root = new VBox(10, children.toArray(new Node[0]));
root.setPrefSize(width, height);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root);
alertStage.setScene(scene);
@@ -323,10 +355,16 @@ public class AutoCloseAlert {
* @param alertStage the alert stage to be closed
*/
private static void closeAlertStage(int seconds, Consumer<String> onClose, Stage alertStage) {
if (seconds>0){
PauseTransition delay = new PauseTransition(Duration.seconds(seconds));
delay.setOnFinished(e -> {
alertStage.close();
try {
closeStage(alertStage);
} catch (InterruptedException err) {
Logger.error("Error closing alert stage: " + err.getMessage());
}
//alertStage.close();
if (currentAlertStage == alertStage) {
currentAlertStage = null;
}
@@ -340,13 +378,11 @@ public class AutoCloseAlert {
private static Image LoadImage(String filename){
if (ValidFile(filename)){
try{
Image mm = new Image(Paths.get(filename).toUri().toString());
System.out.println("Load image from "+filename);
return mm;
return new Image(Paths.get(filename).toUri().toString());
} catch (Exception e){
System.out.println("Error loading image: " + filename+", Message: "+e.getMessage());
Logger.error("Error loading image: " + filename+", Message: "+e.getMessage());
}
} else System.out.println("LoadImage: Invalid file: "+filename);
} else Logger.error("LoadImage: Invalid file: " + filename);
return null;
}

View File

@@ -44,7 +44,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"})
@@ -67,6 +66,11 @@ public class Cameradetail {
private LiveCamEvent event = null;
private @Getter @Setter CameraConfigEnum cameraConfigEnum = CameraConfigEnum.CameraConfigCenter;
private @Getter int LiveFPS = 0;
private double topcrop = 0.0;
private double bottomcrop = 0.0;
private double leftcrop = 0.0;
private double rightcrop = 0.0;
private String title = "";
@@ -111,11 +115,11 @@ public class Cameradetail {
private @Getter final UMat BestMat = new UMat();
private @Getter final UMat LiveMat = new UMat();
private @Getter final UMat ReducedMat = new UMat();
private @Getter final UMat GrayMat = new UMat();
private @Getter final Mat GrayMat = new Mat();
private @Getter Rect BestMatROI;
private @Getter Rect ReducedMatROI;
private @Getter Rect LiveMatROI;
// private @Getter Rect BestMatROI;
// private @Getter Rect ReducedMatROI;
// private @Getter Rect LiveMatROI;
private boolean IsPortrait = false;
@@ -151,7 +155,8 @@ public class Cameradetail {
private boolean use_qr = false;
private boolean use_face = false;
private int _hardwareID = -1;
private @Getter Detectors detector;
private void setSliderValue(Slider sld, CameraProperty prop, double value){
@@ -235,6 +240,8 @@ public class Cameradetail {
raise_log("Exposure for "+getCameraTitle()+" changed to "+newVal);
});
detector = new Detectors();
}
@FXML
@@ -261,14 +268,20 @@ public class Cameradetail {
public void setCameraTitle(String title){
if (ValidString(title)){
this.title = title;
LabelSetText(cameratitle, title,null);
}
}
public void setSharpness_indicator(double value){
if (value >= config.getSharpnessThreshold()){
if (value < 0){
// not defined
LabelSetText(sharpness_indicator, "","");
} else if (value >= config.getSharpnessThreshold()){
// sharpness is good
LabelSetText(sharpness_indicator, "OK","-fx-text-fill: green; -fx-border-color: black");
} else {
// sharpness is bad
LabelSetText(sharpness_indicator,"BAD","-fx-text-fill: red; -fx-border-color: black");
}
}
@@ -413,7 +426,6 @@ public class Cameradetail {
}
mGrabber = grabber;
_hardwareID = hardwareID;
}
//Exposure and Focus Tricks :
@@ -678,7 +690,7 @@ public class Cameradetail {
* @return filename path of the saved photo, or null if failed
*/
public PhotoResult TakePhoto(String directory, String prefix) {
PhotoResult result = new PhotoResult(cameratitle.getText());
PhotoResult result = new PhotoResult(title);
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
@@ -690,37 +702,48 @@ public class Cameradetail {
if (!BestMat.empty()){
UMat cloned;
UMat cloned = new UMat();
synchronized (BestMat){
cloned = BestMat.clone();
BestMat.copyTo(cloned);
}
// save BestMat at quality 9 PNG
String filename = GetFullQualityPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cloned, parampng)){
result.setFullres(filename);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
String xx = CropBestMat(directory, prefix, BestMatROI);
if (ValidFile(xx)) {
result.setFullcrop(xx);
result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
}
String fullresfile = GetFullQualityPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(fullresfile, cloned, parampng)){
result.setFullres(fullresfile);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+title);
// save ReducedMat at 100% JPEG
String reducedfilename = GetReducedPhotoPath(directory, prefix);
String reducedfile = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(cloned, ReducedMat, ReducedSize);
if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText());
} else result.setCompressedfile(reducedfilename);
String xy = CropReducedMat(directory, prefix, ReducedMatROI);
if (ValidFile(xy)){
result.setCompressedcrop(xy);
result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
if (opencv_imgcodecs.imwrite(reducedfile, ReducedMat, paramjpeg)){
result.setCompressedfile(reducedfile);
} else {
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+title);
}
String fullcropfile = GetFullQualityCropPhotoPath(directory, prefix);
UMat croppedfull = CropMat(cloned);
if (croppedfull!=null && !croppedfull.empty()){
if (opencv_imgcodecs.imwrite(fullcropfile, croppedfull, parampng)){
result.setFullcrop(fullcropfile);
} else {
System.out.println("TakePhoto failed, Unable to Save FullCrop Photo for camera "+title);
}
} else System.out.println("TakePhoto failed, Unable to Save FullCrop Photo for camera "+title);
String reducedcropfile = GetReducedCropPhotoPath(directory, prefix);
UMat reducedcrop = CropMat(ReducedMat);
if (reducedcrop!=null && !reducedcrop.empty()){
if (opencv_imgcodecs.imwrite(reducedcropfile, reducedcrop, paramjpeg)){
result.setCompressedcrop(reducedcropfile);
} else {
System.out.println("TakePhoto failed, Unable to Save ReducedCrop Photo for camera "+title);
}
} else System.out.println("TakePhoto failed, Unable to Save ReducedCrop Photo for camera "+title);
cloned.release();
} else raise_log("TakePhoto failed, Live View is Empty");
@@ -740,9 +763,9 @@ public class Cameradetail {
public String CropBestMat(String directory, String prefix, Rect ROI){
UMat cloned;
UMat cloned = new UMat();
synchronized (BestMat){
cloned = BestMat.clone();
BestMat.copyTo(cloned);
}
if (!cloned.empty()) {
if (ValidROI(ROI)){
@@ -787,22 +810,34 @@ public class Cameradetail {
private String makeFileName(String prefix, String extension){
LocalDateTime ldt = LocalDateTime.now();
String timetag = ldt.getYear() + "-" + ldt.getMonthValue() + "-" + ldt.getDayOfMonth() + "_" + ldt.getHour() + "-" + ldt.getMinute() + "-" + ldt.getSecond();
return prefix+" "+timetag+" "+cameratitle.getText() + extension;
return prefix+" "+timetag+" "+title + extension;
}
@SuppressWarnings("SameParameterValue")
private String makeReducedFileName(String prefix, String extension){
LocalDateTime ldt = LocalDateTime.now();
String timetag = ldt.getYear() + "-" + ldt.getMonthValue() + "-" + ldt.getDayOfMonth() + "_" + ldt.getHour() + "-" + ldt.getMinute() + "-" + ldt.getSecond();
return prefix+" "+timetag+" "+cameratitle.getText() + "_reduced" + extension;
return prefix+" "+timetag+" "+title + "_reduced" + extension;
}
// public void Release(){
// if (mGrabber!=null){
// try{
// StopLiveView();
// mGrabber.release();
// mGrabber = null;
// } catch (Exception e){
// System.out.println("Release failed, Unable to Release Camera, Error: " + e.getMessage());
// }
// }
// }
public void StopLiveView(){
Capturing.set(false);
if (mGrabber!=null){
try{
mGrabber.close();
System.out.println("Camera "+cameratitle.getText()+" stopped");
System.out.println("Camera "+title+" stopped");
setCameraStatus("Camera Stopped");
} catch (Exception e){
raise_log("StopLiveView failed, Unable to Stop Camera, Error: " + e.getMessage());
@@ -837,11 +872,8 @@ public class Cameradetail {
while(Capturing.get()){
try {
qr_semaphore.acquire();
UMat gray;
synchronized (lockObject){
gray = GrayMat;
}
String qr = DetectQRFromMat(gray);
String qr = DetectQRFromMat(GrayMat.clone());
if (ValidBarCode(qr)){
if (event!=null) event.onDetectedQRCode(qr);
}
@@ -866,18 +898,15 @@ public class Cameradetail {
while(Capturing.get()){
try {
face_semaphore.acquire();
UMat gray;
synchronized (lockObject){
gray = GrayMat;
}
DetectorResult theface = null;
boolean have_frontal_face = false;
boolean have_left_45_face = false;
int _face_width = 0;
int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(gray);
List<DetectorResult> frontalfaces = detector.HaveFrontalFace(GrayMat.clone());
//System.out.println("camera "+title+ (frontalfaces.isEmpty() ? " no frontal face detected" : " found "+frontalfaces.size()+" frontal faces"));
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
@@ -895,7 +924,8 @@ public class Cameradetail {
} else {
// gak punya frontal face
// coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(gray);
List<DetectorResult> Left45Faces = detector.HaveLeft45Face(GrayMat.clone());
//System.out.println("camera "+title+ (Left45Faces.isEmpty() ? " no left 45 face detected" : " found "+Left45Faces.size()+" left 45 faces"));
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){
@@ -917,10 +947,10 @@ public class Cameradetail {
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
LabelVisible(face_indicator,true);
if (theface.getFace()!=null){
LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
//System.out.println("Frontal Face Detected from camera "+cameratitle+" "+RectToString(LiveMatROI));
}
// Revisi 26/05/2025, LiveMatROI dihitung dari topcrop, bottomcrop, leftcrop dan rightcrop
// if (theface.getFace()!=null){
// LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
// }
if (theface.getEyesCount()>=2){
// ada mata (buka mata)
@@ -930,16 +960,14 @@ public class Cameradetail {
if (event!=null) event.onEyeDetector(true);
LabelVisible(eye_indicator,true);
//System.out.println("Valid Eye Detected from camera "+cameratitle);
// Valid eye condition
if (eye_state.get()!=1){
// transisi dari tutup mata ke buka mata
if (eye_state.get()==-1) {
System.out.println("First Eye Detected from camera "+cameratitle.getText());
//System.out.println("First Eye Detected from camera "+title);
eye_state.set(1);
} else {
//System.out.println("Transition from close to open eyes");
eye_state.set(1);
blink_counter.incrementAndGet();
@@ -951,13 +979,13 @@ public class Cameradetail {
long diff = now - last_blink.get();
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 3 detik
if (diff<=3000){
System.out.println("Double Blink Detected from camera "+cameratitle.getText());
//System.out.println("Double Blink Detected from camera "+title);
if (event!=null) event.onDoubleBlink((int)diff);
}
waiting_for_second_blink.set(false);
} else {
waiting_for_second_blink.set(true);
System.out.println("First Blink Detected from camera "+cameratitle.getText());
//System.out.println("First Blink Detected from camera "+title);
}
last_blink.set(now);
}
@@ -975,7 +1003,6 @@ public class Cameradetail {
if (eye_state.get()!=0){
//System.out.println("Transition from open to close eyes");
eye_state.set(0);
}
@@ -1012,13 +1039,19 @@ public class Cameradetail {
}
if (LiveMat != null && !LiveMat.empty()){
Mat imgmat = new Mat();
LiveMat.copyTo(imgmat);
// copy back to CPU
LiveMat.copyTo(imgmat);
setCameraStream(MatToImage(imgmat));
imgmat.release();
}
} catch (Exception e) {
//System.out.println(Thread.currentThread().getName()+" interrupted");
}
@@ -1034,11 +1067,11 @@ public class Cameradetail {
// 30 fps means 33 ms per frame
// so if grab is quicker than 30 ms , its stale frame
try{
if (mGrabber==null) throw new FrameGrabber.Exception("Grabber is null");
if (mGrabber==null) throw new Exception("Grabber is null");
Frame frame = mGrabber.grab(); // grab frame
delta = System.currentTimeMillis() - now;
now = System.currentTimeMillis();
} catch (FrameGrabber.Exception ignored) {
} catch (Exception ignored) {
}
@@ -1064,11 +1097,10 @@ public class Cameradetail {
if (Capturing.get()) {
try{
if (mGrabber!=null)
frame = mGrabber.grab();
else throw new FrameGrabber.Exception("Grabber is null");
if (mGrabber==null) throw new Exception("Grabber is null");
} catch (FrameGrabber.Exception e){
frame = mGrabber.grab();
} catch (Exception e){
if (Capturing.get()){
// kalau ada exception padahal masih capturing. Kalau sudah tidak capturing, tidak peduli
if (ValidString(e.getMessage())){
@@ -1122,15 +1154,29 @@ public class Cameradetail {
// rotate 90 degree counter clockwise karena kamera potrait
opencv_core.rotate(originalmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE);
originalmat.release();
if (!BestMat.empty()) {
// LiveMat and GrayMat are synchronized
synchronized (lockObject){
opencv_imgproc.resize(BestMat, LiveMat, LiveSize); // resize to LiveSize
opencv_imgproc.cvtColor(LiveMat,GrayMat, COLOR_BGR2GRAY); // convert to grayscale
// resize BestMat to LiveSize
UMat _liveMat = new UMat();
opencv_imgproc.resize(BestMat, _liveMat, LiveSize);
// crop LiveMat
UMat croppedLiveMat = CropMat(_liveMat);
if (croppedLiveMat!=null && !croppedLiveMat.empty()){
croppedLiveMat.copyTo(LiveMat);
croppedLiveMat.release();
} else {
_liveMat.copyTo(LiveMat);
_liveMat.release();
}
// convert to grayscale
Mat xx = new Mat();
LiveMat.copyTo(xx);
opencv_imgproc.cvtColor(xx,GrayMat, COLOR_BGR2GRAY);
}
if (use_qr){
@@ -1144,19 +1190,73 @@ public class Cameradetail {
}
} catch ( FrameGrabber.Exception fe){
System.out.println("FrameGrabber Exception in" + Thread.currentThread().getName() + " : " + fe.getMessage());
fe.printStackTrace();
//fe.printStackTrace();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+" interrupted");
} catch (Exception e){
System.out.println(Thread.currentThread().getName()+" exception : "+e.getMessage());
e.printStackTrace();
//e.printStackTrace();
}
}
});
private UMat CropMat(UMat mat){
if (mat != null && !mat.empty()){
int width = mat.cols();
int height = mat.rows();
int x = (int) (width * leftcrop / 100);
int y = (int) (height * topcrop / 100);
int w = (int) (width * (100 - leftcrop - rightcrop) / 100);
int h = (int) (height * (100 - topcrop - bottomcrop) / 100);
// Ensure the crop dimensions are valid
if (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= width && y + h <= height) {
Rect roi = new Rect(x, y, w, h);
UMat crop = new UMat();
mat.apply(roi).copyTo(crop);
return crop;
}
}
return null;
}
public void ChangeCropValue(){
if ("01".equals(title)){
topcrop = config.getCam1TopCrop();
leftcrop = config.getCam1LeftCrop();
rightcrop = config.getCam1RightCrop();
bottomcrop = config.getCam1BottomCrop();
} else if ("02".equals(title)){
topcrop = config.getCam2TopCrop();
leftcrop = config.getCam2LeftCrop();
rightcrop = config.getCam2RightCrop();
bottomcrop = config.getCam2BottomCrop();
} else if ("03".equals(title)){
topcrop = config.getCam3TopCrop();
leftcrop = config.getCam3LeftCrop();
rightcrop = config.getCam3RightCrop();
bottomcrop = config.getCam3BottomCrop();
} else if ("04".equals(title)){
topcrop = config.getCam4TopCrop();
leftcrop = config.getCam4LeftCrop();
rightcrop = config.getCam4RightCrop();
bottomcrop = config.getCam4BottomCrop();
} else if ("05".equals(title)){
topcrop = config.getCam5TopCrop();
leftcrop = config.getCam5LeftCrop();
rightcrop = config.getCam5RightCrop();
bottomcrop = config.getCam5BottomCrop();
}
}
public boolean StartLiveView(LiveCamEvent event, String cameratitle, boolean use_qr , boolean use_face) {
this.event = event;
this.title = cameratitle;
ChangeCropValue();
if (mGrabber != null) {
try {
@@ -1184,6 +1284,7 @@ public class Cameradetail {
@Override
public void run() {
if (Capturing.get()){
int fpsval = fps.getAndSet(0);
if (fpsval!=LiveFPS){
LiveFPS = fpsval;
@@ -1233,83 +1334,78 @@ public class Cameradetail {
}
/**
* Remap LiveMatROI to BestMatROI and ReducedMatROI Resolution
* @param scaleX scale factor for width
* @param scaleY scale factor for height
*/
public void RemapROI(double scaleX, double scaleY, boolean printdebug){
BestMatROI = null;
ReducedMatROI = null;
if (ValidROI(LiveMatROI)){
if (ROIInsideUMat(LiveMatROI, LiveMat)){
if (printdebug) System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
double scaleXBest = 1.0*BestSize.width()/LiveSize.width();
double scaleYBest = 1.0*BestSize.height()/LiveSize.height();
int XBest = (int) (LiveMatROI.x()*scaleXBest);
int YBest = (int) (LiveMatROI.y()*scaleYBest);
int WBest = (int) (LiveMatROI.width()*scaleXBest);
int HBest = (int) (LiveMatROI.height()*scaleYBest);
int deltaWBest = (int) (BestSize.width() * scaleX);
int deltaHBest = (int) (BestSize.height() * scaleY);
XBest = XBest - deltaWBest/2;
if (XBest<0) XBest = 0;
YBest = YBest - deltaHBest/2;
if (YBest<0) YBest = 0;
WBest = WBest + deltaWBest;
if (WBest>BestSize.width()) WBest = BestSize.width();
HBest = HBest + deltaHBest;
if (HBest>BestSize.height()) HBest = BestSize.height();
BestMatROI = new Rect(XBest, YBest, WBest, HBest);
if (printdebug){
System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest);
System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI));
}
double scaleXReduced = 1.0*ReducedSize.width()/LiveSize.width();
double scaleYReduced = 1.0*ReducedSize.height()/LiveSize.height();
int XReduced = (int) (LiveMatROI.x()*scaleXReduced);
int YReduced = (int) (LiveMatROI.y()*scaleYReduced);
int WReduced = (int) (LiveMatROI.width()*scaleXReduced);
int HReduced = (int) (LiveMatROI.height()*scaleYReduced);
int deltaWReduced = (int) (ReducedSize.width() * scaleX);
int deltaHReduced = (int) (ReducedSize.height() * scaleY);
XReduced = XReduced - deltaWReduced/2;
if (XReduced<0) XReduced = 0;
YReduced = YReduced - deltaHReduced/2;
if (YReduced<0) YReduced = 0;
WReduced = WReduced + deltaWReduced;
if (WReduced>ReducedSize.width()) WReduced = ReducedSize.width();
HReduced = HReduced + deltaHReduced;
if (HReduced>ReducedSize.height()) HReduced = ReducedSize.height();
ReducedMatROI = new Rect(XReduced, YReduced, WReduced, HReduced);
if (printdebug){
System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI));
}
} //else System.out.println("LiveMatROI is Outside LiveMat for camera "+cameratitle.getText());
} //else System.out.println("LiveMatROI is invalid for camera "+cameratitle.getText());
}
// /**
// * Remap LiveMatROI to BestMatROI and ReducedMatROI Resolution
// * @param scaleX scale factor for width
// * @param scaleY scale factor for height
// */
// public void RemapROI(double scaleX, double scaleY, boolean printdebug){
// BestMatROI = null;
// ReducedMatROI = null;
// if (ValidROI(LiveMatROI)){
// if (ROIInsideUMat(LiveMatROI, LiveMat)){
// if (printdebug) System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
//
// double scaleXBest = 1.0*BestSize.width()/LiveSize.width();
// double scaleYBest = 1.0*BestSize.height()/LiveSize.height();
// int XBest = (int) (LiveMatROI.x()*scaleXBest);
// int YBest = (int) (LiveMatROI.y()*scaleYBest);
// int WBest = (int) (LiveMatROI.width()*scaleXBest);
// int HBest = (int) (LiveMatROI.height()*scaleYBest);
// int deltaWBest = (int) (BestSize.width() * scaleX);
// int deltaHBest = (int) (BestSize.height() * scaleY);
// XBest = XBest - deltaWBest/2;
// if (XBest<0) XBest = 0;
// YBest = YBest - deltaHBest/2;
// if (YBest<0) YBest = 0;
// WBest = WBest + deltaWBest;
// if (WBest>BestSize.width()) WBest = BestSize.width();
// HBest = HBest + deltaHBest;
// if (HBest>BestSize.height()) HBest = BestSize.height();
// BestMatROI = new Rect(XBest, YBest, WBest, HBest);
//
// if (printdebug){
// System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest);
// System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI));
// }
//
// double scaleXReduced = 1.0*ReducedSize.width()/LiveSize.width();
// double scaleYReduced = 1.0*ReducedSize.height()/LiveSize.height();
// int XReduced = (int) (LiveMatROI.x()*scaleXReduced);
// int YReduced = (int) (LiveMatROI.y()*scaleYReduced);
// int WReduced = (int) (LiveMatROI.width()*scaleXReduced);
// int HReduced = (int) (LiveMatROI.height()*scaleYReduced);
// int deltaWReduced = (int) (ReducedSize.width() * scaleX);
// int deltaHReduced = (int) (ReducedSize.height() * scaleY);
// XReduced = XReduced - deltaWReduced/2;
// if (XReduced<0) XReduced = 0;
// YReduced = YReduced - deltaHReduced/2;
// if (YReduced<0) YReduced = 0;
// WReduced = WReduced + deltaWReduced;
// if (WReduced>ReducedSize.width()) WReduced = ReducedSize.width();
// HReduced = HReduced + deltaHReduced;
// if (HReduced>ReducedSize.height()) HReduced = ReducedSize.height();
// ReducedMatROI = new Rect(XReduced, YReduced, WReduced, HReduced);
// if (printdebug){
// System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
// System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI));
// }
// }
// }
//
// }
/**
* Detect QR Code from Mat
* @param graymat Mat in Gray Scale
* @param mat Mat in Gray Scale
* @return QR Code Text, or null if not detected
*/
private String DetectQRFromMat(UMat graymat){
private String DetectQRFromMat(Mat mat){
if (qrreader!=null){
Mat mat = new Mat();
graymat.copyTo(mat); // back to CPU, because zxing only accept BufferedImage
if (mat!=null && !mat.empty()){
BufferedImage bufferedImage = matToBufferedImage(mat);
String title = cameratitle.getText();
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage)));
try{
Result result = qrreader.decode(binaryBitmap);
@@ -1320,6 +1416,8 @@ public class Cameradetail {
}
mat.release();
}
}
return null;
}

View File

@@ -4,15 +4,16 @@ import BASS.AudioPlayer;
import BASS.PlaybackStatus;
import Camera.*;
import Config.CameraConfigEnum;
import Config.SomeCodes;
import Database.PhotoReviewClass;
import Database.Sqlite;
import ErhaAPI.ErhaAPI;
import ErhaAPI.BarcodeResullt;
import ErhaAPI.BarcodeHttpResult;
import ErhaAPI.UploadHttpResult;
import ErhaAPI.PhotoResult;
import ErhaAPI.PatientRecord;
import ErhaAPI.UploadResult;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.concurrent.Task;
@@ -30,6 +31,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.scene.control.Alert.AlertType;
import javafx.util.Duration;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.javacv.VideoInputFrameGrabber;
import org.bytedeco.opencv.opencv_core.Rect;
@@ -73,7 +75,7 @@ public class CaptureView {
private String audio_posisikan_muka = "posisikan_wajah.wav";
private String audio_scan_barcode = "scan_barcode.wav";
private String audio_pengambilan_gagal = "pengambilan_gagal.wav";
private String audio_pengambilan_berhasil = "pengambilan_berhasil.wav";
private String audio_pengambilan_berhasil = "pengambilan_berhasil_tunggu_lobby.wav";
private String audio_upload_gagal = "upload_gagal.wav";
private String audio_countdown = "countdown321.wav";
private String audio_camera_shutter = "camera-shutter-click-01.wav";
@@ -88,7 +90,8 @@ public class CaptureView {
private final AtomicBoolean isTakingPhoto = new AtomicBoolean(false);
private final ErhaAPI erhaAPI = new ErhaAPI(false);
private final ErhaAPI erhaAPI = new ErhaAPI(config.isProduction());
// for timeout 180 detik
private final int timeout = 180;
@@ -142,6 +145,7 @@ public class CaptureView {
@FXML
private void TakePhotos(){
if (audioTimeline!=null) audioTimeline.stop();
String directory = config.getPhotoDirectory();
String prefix = RemoveSpaces(medicalRecordID.getText()) ;
boolean has_face = Arrays.stream(have_face).anyMatch(AtomicBoolean::get);
@@ -150,11 +154,7 @@ public class CaptureView {
isTakingPhoto.set(true);
if (has_face){
AutoCloseAlert.show("Pengambilan Foto", "Tahan Posisi Anda", "Proses ini kurang lebih 3 detik", 5, null);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_tahan_posisi)){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_tahan_posisi, new PlaybackStatus() {
PlayFileWithEvent(audio_tahan_posisi, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
@@ -162,9 +162,8 @@ public class CaptureView {
@Override
public void onPlaybackFinished(String filename) {
Wait(500);
audioPlayer.PlayFile(audio_countdown, new PlaybackStatus() {
PlayFileWithEvent(audio_countdown, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
@@ -180,8 +179,6 @@ public class CaptureView {
}
});
}
@Override
@@ -190,44 +187,21 @@ public class CaptureView {
}
});
}
}
} else {
AutoCloseAlert.show("Error", "No Face Detected", "No Face Detected", 5, null);
isTakingPhoto.set(false);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) {
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_posisikan_muka, null);
}
}
PlayFileWithoutEvent(audio_posisikan_muka);
}
} else {
System.out.println("Prefix invalid, not taking photo");
isTakingPhoto.set(false);
//AutoCloseAlert.show("QR Code Not Available", "", "Please scan QR before continue", 5, s -> AutoCloseAlert.show("Scan Barcode", "Silahkan Scan Barcode Anda", "Arahkan kertas barcode ke kamera", 0, null));
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
if (AutoCloseAlert.banner_01!=null){
System.out.println("Showing banner 01 because prefix invalid");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
}
}
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) {
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_scan_barcode, null);
}
}
clear();
PlayFileWithoutEvent(audio_scan_barcode);
}
} else {
System.out.println("Photo Directory invalid, not taking photo");
isTakingPhoto.set(false);
AutoCloseAlert.show("Invalid Photo Directory","Photo Directory not set", "Please set photo directory at Setting", 5, s -> AutoCloseAlert.show("Setting", "Setting", "Please set photo directory", 0, null));
AutoCloseAlert.show("Invalid Photo Directory","Photo Directory not set", "Please set photo directory at Setting", 5, s -> AutoCloseAlert.show("Setting", "Setting", "Please set photo directory", 0, sx-> clear()));
}
@@ -247,7 +221,7 @@ public class CaptureView {
@Override
public PhotoResult call() {
if (image!=null){
image.RemapROI(0.1, 0.3, false);
//image.RemapROI(0.1, 0.3, false);
double sharpness = CalculateSharpness(image.getGrayMat());
image.setSharpness_indicator(sharpness);
PhotoResult p = image.TakePhoto(directory, prefix);
@@ -265,7 +239,7 @@ public class CaptureView {
AtomicInteger takephoto_failure_counter = new AtomicInteger(0);
private void take_photo_lanjutan(String directory, String prefix){
audioPlayer.PlayFile(audio_camera_shutter, null);
PlayFileWithoutEvent(audio_camera_shutter);
Size thumbsize = new Size(160,120);
PhotoReviewClass prc = new PhotoReviewClass();
@@ -307,8 +281,6 @@ public class CaptureView {
String timestamp = SomeCodes.GetDateTimeString();
System.out.println("Creating timestamp: "+timestamp);
// check for blurred image
double score1=-1, score2=-1, score3=-1, score4=-1, score5=-1;
@@ -340,21 +312,11 @@ public class CaptureView {
String lowest_string = String.format("%.2f", lowest);
AutoCloseAlert.show("Take Photos Failed", "Blurred Image Detected", "Blurred Image Detected at "+culprit+" with sharpness score "+lowest_string, 5, s -> isTakingPhoto.set(false));
takephoto_failure_counter.incrementAndGet();
if (audioPlayer!=null && audioPlayer.isInited()){
if (takephoto_failure_counter.get() < 2){
if (!Objects.equals(audio_pengambilan_gagal, audioPlayer.getCurrentFile())){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_pengambilan_gagal, null);
}
PlayFileWithoutEvent(audio_pengambilan_gagal);
} else {
if (!Objects.equals(audio_hubungi_staf_kami, audioPlayer.getCurrentFile())){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_hubungi_staf_kami, null);
}
}
PlayFileWithoutEvent(audio_hubungi_staf_kami);
clear();
}
return;
@@ -516,11 +478,15 @@ public class CaptureView {
String[] files = prc.compressed();
if (files.length>0){
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_berhasil)){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_pengambilan_berhasil, new PlaybackStatus() {
AutoCloseAlert.showpictures(prc.compressedcrop(),3, (s)->{
if (AutoCloseAlert.banner_02!=null) {
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
UploadFiles(prc, prefix);
if (runningTask!=null) runningTask.cancel(false);
}
});
PlayFileWithEvent(audio_pengambilan_berhasil, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
@@ -528,16 +494,6 @@ public class CaptureView {
@Override
public void onPlaybackFinished(String filename) {
AutoCloseAlert.showpictures(prc.compressed(),3, (s)->{
if (AutoCloseAlert.banner_02!=null) {
System.out.println("Showing banner 02 after photo taken");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
UploadFiles(prc, prefix);
if (runningTask!=null) runningTask.cancel(false);
}
});
}
@@ -545,42 +501,32 @@ public class CaptureView {
public void onPlaybackFailure(String filename) {
}
});
}
}
} else {
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_gagal)){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_pengambilan_gagal, null);
}
}
PlayFileWithoutEvent(audio_pengambilan_gagal);
clear();
if (runningTask!=null) runningTask.cancel(false);
}
}
private void UploadFiles(PhotoReviewClass prc, String prefix){
String[] files = prc.compressed();
String[] files = prc.compressedcrop();
if (files.length>0){
InsertSQL(prc);
erhaAPI.setProduction(config.isProduction());
Task<Void> uploadtask = new Task<>() {
@Override
protected Void call() {
int totalfiles = files.length;
int counter = 0;
for (String ff : files) {
UploadResult ur = erhaAPI.Upload_File(prefix, ff,true);
if (ur != null) {
if (ur.message.startsWith("Record has been created")) {
UploadHttpResult ur = erhaAPI.Upload_File(prefix, ff,true);
if (ur.getResult().message.startsWith("Record has been created")) {
counter++;
updateMessage("Upload success for " + ff);
} else updateMessage("Upload failed for " + ff+", Message : "+ur.message);
} else updateMessage("Upload failed for " + ff+" because UploadResult is null");
} else updateMessage("Upload failed for " + ff+", Message : "+ur.getResult().message);
}
if (counter == totalfiles) {
super.succeeded();
@@ -591,26 +537,13 @@ public class CaptureView {
uploadtask.messageProperty().addListener((obs, oldval, newval)-> {
System.out.println("UploadTask message: "+newval);
Logger.info(newval);
});
uploadtask.messageProperty().addListener((obs, oldval, newval)-> Logger.info(newval));
uploadtask.setOnSucceeded(e-> {
System.out.println("UploadTask succeeded");
clear();
});
uploadtask.setOnSucceeded(e-> clear());
uploadtask.setOnFailed(e-> {
System.out.println("UploadTask failed");
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_upload_gagal)){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_upload_gagal, null);
}
}
PlayFileWithoutEvent(audio_upload_gagal);
AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> clear());
});
@@ -625,7 +558,7 @@ public class CaptureView {
@FXML
public void initialize(){
audio_posisikan_muka = ExtractResource("/posisikan_wajah.wav");
audio_pengambilan_berhasil = ExtractResource("/pengambilan_berhasil.wav");
audio_pengambilan_berhasil = ExtractResource("/pengambilan_berhasil_tunggu_lobby.wav");
audio_pengambilan_gagal = ExtractResource("/pengambilan_gagal.wav");
audio_scan_barcode = ExtractResource("/scan_barcode.wav");
audio_upload_gagal = ExtractResource("/upload_gagal.wav");
@@ -637,16 +570,13 @@ public class CaptureView {
//tambahan 19/03/2025
barcodeData.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("barcodeData changed from ["+oldValue+"] to ["+newValue+"]");
if (ValidBarCode(newValue)){
if (Objects.equals(AutoCloseAlert.banner_01, AutoCloseAlert.shownBanner)){
System.out.println("Close banner 01");
AutoCloseAlert.close();
}
} else {
if (AutoCloseAlert.banner_01!=null){
System.out.println("Show banner 01");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0, null);
//AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0, null);
}
}
TakePhotoButtonChange();
@@ -674,16 +604,13 @@ public class CaptureView {
LoadCameraDetail(cam1, 1, CameraConfigEnum.CameraConfigLeft90);
LoadCameraDetail(cam2, 2, CameraConfigEnum.CameraConfigLeft45);
LoadCameraDetail(cam3, 3, CameraConfigEnum.CameraConfigCenter);
if (!DermiesMode){
LoadCameraDetail(cam4, 4, CameraConfigEnum.CameraConfigRight45);
LoadCameraDetail(cam5, 5, CameraConfigEnum.CameraConfigRight90);
}
Platform.runLater(()->{
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
if (AutoCloseAlert.banner_01!=null){
System.out.println("Showing banner 01 for first time");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
}
}
clear();
int indexleft90=-1;
int indexleft45=-1;
@@ -775,11 +702,23 @@ public class CaptureView {
}
Timeline audioTimeline;
private void clear(){
isTakingPhoto.set(false);
TextAreaSetText(medicalRecordID,"");
TextAreaSetText(PatientName,"");
if (image1!=null) image1.setSharpness_indicator(-1);
if (image2!=null) image2.setSharpness_indicator(-1);
if (image3!=null) image3.setSharpness_indicator(-1);
if (image4!=null) image4.setSharpness_indicator(-1);
if (image5!=null) image5.setSharpness_indicator(-1);
if (barcodeData.getText().isBlank()){
// pancing supaya addlistener barcodeData trigger
TextAreaSetText(barcodeData,"x");
Wait(10);
TextAreaSetText(barcodeData,"");
} else TextAreaSetText(barcodeData,"");
}
public void Unload(){
@@ -877,8 +816,8 @@ public class CaptureView {
photoheight = ObsbotMeet2.ModeBest.getHeight();
livewidth = ObsbotMeet2.ModeLive.getWidth();
liveheight = ObsbotMeet2.ModeLive.getHeight();
reducewidth = ObsbotMeet2.Mode3.getWidth();
reduceheight = ObsbotMeet2.Mode3.getHeight();
reducewidth = ObsbotMeet2.Mode2.getWidth();
reduceheight = ObsbotMeet2.Mode2.getHeight();
}
image.SetGrabber(devicenumber,grabber, livewidth,liveheight,photowidth,photoheight,reducewidth,reduceheight, true);
@@ -886,6 +825,9 @@ public class CaptureView {
boolean use_qr_detector = true;
LiveCamEvent lce = new LiveCamEvent() {
@Override
public void onDetectedQRCode(String barCode) {
barCode = RemoveSpaces(barCode);
@@ -894,39 +836,135 @@ public class CaptureView {
if (!barCode.equals(prefix)){
final String finalbarCode = barCode;
TextAreaSetText(barcodeData, finalbarCode);
// revisi 19/05/2025
if (runningTask!=null) runningTask.cancel(false);
runningTask = timeoutExecutor.schedule(()->{
// timeout
clear();
System.out.println("180 seconds timeout");
}, timeout, TimeUnit.SECONDS);
// Revisi 19/05/2025
// pakai Timeline untuk pengulangan PlayFile audio_posisikan_muka dengan interval 5 detik
// diulang 3x
// terakhir, PlayFile audio_hubungi_staf_kami
audioTimeline = new Timeline();
final int file_duration = 8; // audio_posisikan_muka durasi 7 detik
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), k1 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
System.out.println("Peringatan pertama audio_posisikan_muka");
}
@Override
public void onPlaybackFinished(String filename) {
anti_bawel.set(false);
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
})));
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(file_duration+5), k2 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
System.out.println("Peringatan kedua audio_posisikan_muka");
}
@Override
public void onPlaybackFinished(String filename) {
anti_bawel.set(false);
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
})));
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(3*file_duration+5), k3 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
System.out.println("Peringatan ketiga audio_posisikan_muka");
}
@Override
public void onPlaybackFinished(String filename) {
anti_bawel.set(false);
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
})));
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5*file_duration+5), k4 ->{
PlayFileWithEvent(audio_hubungi_staf_kami, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
System.out.println("Peringatan keempat audio_hubungi_staf_kami");
}
@Override
public void onPlaybackFinished(String filename) {
anti_bawel.set(false);
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
});
clear();
}));
Task<PatientRecord> checkpatientID = new Task<>() {
@Override
protected PatientRecord call() throws Exception {
BarcodeResullt br = erhaAPI.Validate_Barcode(finalbarCode,true);
if (br!=null){
if (br.message.startsWith("Records found")){
if (br.data!=null && br.data.length>0){
PatientRecord pr = br.data[0];
erhaAPI.setProduction(config.isProduction());
BarcodeHttpResult br = erhaAPI.Validate_Barcode(finalbarCode,true);
if (br.getStatusCode()==200){
if (br.getResult().message.startsWith("Records found")){
if (br.getResult().data!=null && br.getResult().data.length>0){
PatientRecord pr = br.getResult().data[0];
if (!pr.medical_record_detail_id.isBlank()){
if (!pr.name.isBlank()){
super.succeeded();
return pr;
} else {
Logger.error("Barcode ",finalbarCode," PatientRecord name is empty");
throw new Exception("Barcode "+finalbarCode+" PatientRecord name kosong");
throw new Exception("Barcode "+finalbarCode+" PatientRecord name kosong, code= "+br.getStatusCode());
}
} else {
Logger.error("Barcode ",finalbarCode," PatientRecord medical_record_detail_id is empty");
throw new Exception("Data dengan barcode "+finalbarCode+", PatientRecord medical_record_detail_id kosong");
throw new Exception("Data dengan barcode "+finalbarCode+", PatientRecord medical_record_detail_id kosong, code= "+br.getStatusCode());
}
} else {
Logger.error("Record associated with barcode ",finalbarCode," is empty");
throw new Exception("Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong");
throw new Exception("Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong, code= "+br.getStatusCode());
}
} else {
Logger.error("Record associated with barcode ",finalbarCode," is not found");
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server");
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server, code= "+br.getStatusCode());
}
} else {
Logger.error("BarcodeResullt with barcode ",finalbarCode," is null");
throw new Exception("BarcodeResult dengan barcode "+finalbarCode+" menghasilkan null");
Logger.error("HTTP code ", br.getStatusCode(), " for barcode ", finalbarCode);
throw new Exception("Barcode "+finalbarCode+" failed, code= "+br.getStatusCode()+", message: "+br.getBody());
}
}
};
checkpatientID.setOnSucceeded(event -> {
@@ -936,63 +974,19 @@ public class CaptureView {
TextAreaSetText(medicalRecordID,""+medrecid);
TextAreaSetText(PatientName, pr.name);
if (anti_bawel.get()) return; // sudah ada LiveCamEvent lain yang bunyiin, jadi tidak usah bunyiin lagi
if (audioTimeline!=null) audioTimeline.playFromStart();
runningTask = timeoutExecutor.schedule(()->{
// timeout
System.out.println("runningTask timeout after "+timeout+" seconds");
clear();
}, timeout, TimeUnit.SECONDS);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) {
if (!anti_bawel.get()){
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(audio_posisikan_muka, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
}
@Override
public void onPlaybackFinished(String filename) {
anti_bawel.set(false);
Thread antibawel = new Thread(()->{
try {
Thread.sleep(15*1000);
} catch (InterruptedException ignored) {
}
anti_bawel.set(false);
});
antibawel.setName("anti bawel");
antibawel.setDaemon(true);
antibawel.start();
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
});
}
}
}
}
});
checkpatientID.setOnFailed(event -> {
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_data_barcode_tidak_ditemukan)) {
audioPlayer.StopCurrentPlayback();
audioPlayer.PlayFile(audio_data_barcode_tidak_ditemukan,null);
}
}
PlayFileWithoutEvent(audio_data_barcode_tidak_ditemukan);
clear();
Task<?> failed = (Task<?>) event.getSource();
Throwable t = failed.getException();
final String message = t.getMessage();
System.out.println("checkpatientID.setOnFailed message : "+message);
AutoCloseAlert.show("Data Tidak Ditemukan", "Pastikan data barcode anda benar", message , 5, s -> clear());
@@ -1019,42 +1013,33 @@ public class CaptureView {
}
//update_status(image);
// instruksi scan barcode ketika welcomeUI masih muncul dan ada muka terdeteksi
if (hasface && Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) {
audioPlayer.StopCurrentPlayback();
if (anti_bawel.get()) return;
audioPlayer.PlayFile(audio_scan_barcode, new PlaybackStatus() {
if (hasface){
// ada face terdeteksi
if (Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
// WelcomeUI masih muncul
if (anti_bawel.get()) return; // sudah ada LiveCamEvent lain yang bunyiin, jadi tidak usah bunyiin lagi
PlayFileWithEvent(audio_scan_barcode, new PlaybackStatus() {
@Override
public void onPlaybackStarted(String filename) {
anti_bawel.set(true);
}
@Override
public void onPlaybackFinished(String filename) {
Thread antibawel = new Thread(()->{
try {
Thread.sleep(15*1000);
} catch (InterruptedException ignored) {
}
anti_bawel.set(false);
});
antibawel.setName("anti bawel");
antibawel.setDaemon(true);
antibawel.start();
WaitAsync(15*1000, "anti bawel", x-> anti_bawel.set(false));
}
@Override
public void onPlaybackFailure(String filename) {
anti_bawel.set(false);
}
});
}
});
} else if (audioTimeline!=null){
// WelcomeUI sudah tidak muncul, tapi audioTimeLine masih ada
audioTimeline.stop();
}
}
}
@@ -1092,9 +1077,8 @@ public class CaptureView {
@Override
public void onDoubleBlink(int counter) {
System.out.println("Double Blink detected at camera "+title+" delay= "+counter);
if (audioPlayer!=null && audioPlayer.isPlaying()) return; // let audio finish playback
if (isTakingPhoto.get()) return; // other camera is taking picture
if (isTakingPhoto.get()) return; // another camera is taking picture
// revisi 08/04/2025
TakePhotos();
}
@@ -1122,8 +1106,11 @@ public class CaptureView {
};
image.setCameraStatus("Camera Starting");
if (image.StartLiveView(lce, title, use_qr_detector, use_face_detector)){
//TODO Start Live View berhasil, apa lagi yang mau dikerjakan ?
image.getDetector().setFaceMaxSize(config.getCascadeMaxSize());
image.getDetector().setFaceMinSize(config.getCascadeMinSize());
image.getDetector().setScaleFactor(config.getCascadeScaleFactor());
MainApplication.detectorsList.put(devicenumber, image.getDetector());
Logger.info("Camera "+cameraname+" started with device number "+devicenumber);
} else image.setCameraStatus("Unable to Set Grabber");
} else image.setCameraStatus("Camera not found, please check setting");
}
@@ -1145,7 +1132,6 @@ public class CaptureView {
cam.getChildren().add(child);
cam.widthProperty().addListener(observable ->{
//System.out.println("Width property, cam "+camid+" width="+cam.getWidth()+" height="+cam.getHeight());
if (cam.getWidth()!=0) {
if (cam.getHeight()!=0){
AnchorPane.setTopAnchor(child, 0.0);
@@ -1156,7 +1142,6 @@ public class CaptureView {
}
});
cam.heightProperty().addListener(observable -> {
//System.out.println("Height property, cam "+camid+" width="+cam.getWidth()+" height="+cam.getHeight());
if (cam.getWidth()!=0) {
if (cam.getHeight()!=0){
AnchorPane.setTopAnchor(child, 0.0);
@@ -1199,4 +1184,24 @@ public class CaptureView {
Sqlite sql = new Sqlite();
sql.Insert(prc);
}
private void PlayFileWithoutEvent(String filename){
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),filename)) {
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(filename, null);
}
}
}
private void PlayFileWithEvent(String filename, PlaybackStatus ps){
if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),filename)) {
audioPlayer.StopCurrentPlayback();
Wait(500);
audioPlayer.PlayFile(filename, ps);
}
}
}
}

View File

@@ -24,8 +24,14 @@ public class DetectorResult {
Eyes.add(eye);
}
// trouble di sini
public void FaceRectangle(UMat mat){
if (mat == null || mat.empty()) return;
if (Face == null || Face.width() <= 0 || Face.height() <= 0) return;
if (Face.x() < 0 || Face.y() < 0) return; // ignore negative coordinates
if (Face.x() + Face.width() > mat.cols() || Face.y() + Face.height() > mat.rows()) return; // ignore out of bounds
if (haveFace()){
try{
rectangle(mat, Face, Scalar.GREEN, linethickness, linetype, lineshift);
@@ -33,9 +39,17 @@ public class DetectorResult {
}
}
// trouble di sini
public void EyesRectangle(UMat mat){
if (mat == null || mat.empty()) return;
if (haveEyes()){
for(Rect eye : Eyes){
if (eye == null || eye.width() <= 0 || eye.height() <= 0) continue;
if (eye.x() < 0 || eye.y() < 0) continue; // ignore negative coordinates
if (eye.x() + eye.width() > mat.cols() || eye.y() + eye.height() > mat.rows()) continue; // ignore out of bounds
try{
rectangle(mat, eye, Scalar.BLUE);

View File

@@ -10,72 +10,55 @@ import java.util.ArrayList;
import java.util.List;
public class Detectors {
public static CascadeClassifier frontalfaceDetector;
private static CascadeClassifier eyeDetector;
private static CascadeClassifier profilefaceDetector;
public CascadeClassifier frontalfaceDetector;
private CascadeClassifier eyeDetector;
private CascadeClassifier profilefaceDetector;
private static double scaleFactor = 1.2; // revisi 09/05/2025, dari nilai 1.05
private final static int minNeighbors = 5; // revisi 09/05/2025, dari nilai 3
private final static int flags = 0;
private static Size FaceminSize;
private static Size FacemaxSize;
public static void LoadAllDetectors(){
private double scaleFactor = 1.05; // revisi 09/05/2025, dari nilai 1.05
private final int minNeighbors = 3; // revisi 09/05/2025, dari nilai 3
private final int flags = 0;
private Size FaceminSize;
private Size FacemaxSize;
public Detectors(){
LoadFrontalFaceDetector();
LoadEyeDetector();
LoadProfileFaceDetector();
}
private static void LoadFrontalFaceDetector(){
private void LoadFrontalFaceDetector(){
// revisi 09/05/2025, dari filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) {
Logger.info("Face Detector file : " + filename);
if (frontalfaceDetector==null) {
try{
frontalfaceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading FaceDetector : " + e.getMessage());
}
} else Logger.info("FaceDetector already loaded");
} else Logger.error("Unable to extract face detector file");
}
private static void LoadProfileFaceDetector(){
private void LoadProfileFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
if (filename!=null) {
Logger.info("Profile Face Detector file : " + filename);
if (profilefaceDetector==null) {
try{
profilefaceDetector = new CascadeClassifier(filename);
Logger.info("ProfileFaceDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading ProfileFaceDetector : " + e.getMessage());
}
} else Logger.info("ProfileFaceDetector already loaded");
} else Logger.error("Unable to extract profile face detector file");
}
private static void LoadEyeDetector(){
private void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml");
if (filename!=null) {
Logger.info("Eye Detector file : " + filename);
if (eyeDetector==null) {
try{
eyeDetector = new CascadeClassifier(filename);
Logger.info("EyeDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading EyeDetector : " + e.getMessage());
}
} else Logger.info("EyeDetector already loaded");
} else Logger.error("Unable to extract eye detector file");
}
@@ -84,30 +67,31 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @return List of Rect if face detected, otherwise empty list
*/
public static @NonNull List<DetectorResult> HaveFrontalFace(UMat graymat){
public @NonNull List<DetectorResult> HaveFrontalFace(Mat graymat){
List<DetectorResult> result = new ArrayList<>();
//System.out.println("Detecting frontal from "+ graymat.size().width() + "x" + graymat.size().height());
RectVector faces = DetectFrontalFace(graymat);
if (faces!=null && faces.size()>0){
//System.out.println("faces size = " + faces.size());
for(Rect face : faces.get()){
RectVector eyes = DetectEye(graymat, face.width());
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>=2){
//System.out.println("eyes size = " + eyes.size());
if (eyes.size()>=2){
for(Rect eye : eyes.get()){
if (SomeCodes.IsInsideRect(eye, face)) {
dr.AddEye(eye);
System.out.println("face width : " + face.width() + " eye width : " + eye.width());
}
}
}
result.add(dr);
}
}
} //else System.out.println("faces size = 0");
return result;
}
public static @NonNull List<DetectorResult> HaveLeft45Face(UMat graymat){
public @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){
List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat);
if (faces!=null && faces.size()>0){
@@ -116,7 +100,7 @@ public class Detectors {
RectVector eyes = DetectEye(graymat, face.width());
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>0){
if (eyes.size()>0){
for(Rect eye : eyes.get()){
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
}
@@ -130,40 +114,38 @@ public class Detectors {
public static void setScaleFactor(double value){
public void setScaleFactor(double value){
if (scaleFactor!=value) scaleFactor = value;
}
public static void setFaceMinSize(int value){
public void setFaceMinSize(int value){
if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
FaceminSize = new Size(value, value);
//Logger.info("FaceMinSize changed to : " + FaceminSize.width());
Logger.info("FaceMinSize changed to : " + FaceminSize.width());
}
} else {
FaceminSize = new Size(value, value);
//Logger.info("FaceMinSize created with value : " + FaceminSize.width());
Logger.info("FaceMinSize created with value : " + FaceminSize.width());
}
System.out.println("Face Min Size : " + FaceminSize.width());
}
public static void setFaceMaxSize(int value){
public void setFaceMaxSize(int value){
if (FacemaxSize!=null){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
FacemaxSize = new Size(value, value);
//Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
}
} else {
FacemaxSize = new Size(value, value);
//Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
}
System.out.println("Face Max Size : " + FacemaxSize.width());
}
public static RectVector DetectProfileFace(UMat graymat){
public RectVector DetectProfileFace(Mat graymat){
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
@@ -172,7 +154,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise null
*/
public static RectVector DetectFrontalFace(UMat graymat){
public RectVector DetectFrontalFace(Mat graymat){
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
@@ -182,38 +164,39 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @return RectVector if eye detected, otherwise null
*/
public static RectVector DetectEye(UMat graymat, int facewidth){
public RectVector DetectEye(Mat graymat, int facewidth){
//return Detect(graymat, eyeDetector);
int minwidth = (int)(facewidth*0.2);
int maxwidth = (int)(facewidth*0.4);
Size minsize = new Size(minwidth, minwidth);
Size maxsize = new Size(maxwidth, maxwidth);
//System.out.println("Detecting Eye with minsize = " + minsize.width() + "x" + minsize.height() + ", maxsize = " + maxsize.width() + "x" + maxsize.height());
return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, minsize, maxsize);
}
@SuppressWarnings("SameParameterValue")
private static RectVector Detect(UMat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
if (detector!=null){
if (graymat!=null && graymat.channels()==1){
if (!graymat.empty()){
if (minSize!=null){
if (maxSize!=null){
try{
private RectVector Detect(Mat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
if (detector!=null && !detector.empty()){
if (graymat!=null && graymat.channels()==1 && !graymat.empty()){
if (minSize!=null && maxSize!=null){
if (minSize.width()< maxSize.width() && minSize.height() < maxSize.height()){
if (graymat.cols()> minSize.width() && graymat.rows() > minSize.height()) {
try {
RectVector detected = new RectVector();
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, maxSize);
// try defaulting minSize and maxSize
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, new Size());
return detected;
} catch (Exception e){
System.out.println("Detectors Detect Error, Message : "+e.getMessage());
} catch (Exception e) {
System.out.println("Detectors Detect Error, Message : " + e.getMessage());
}
} else System.out.println("graymat is smaller than minSize");
}
}
} else System.out.println("minSize is larger than maxSize");
} else System.out.println("minSize or maxSize is null");
} else System.out.println("graymat is null, not 1 channel, or empty");
}
}
}
} else System.out.println("detector empty");
return null;
}

View File

@@ -1,6 +1,7 @@
package id.co.gtc.erhacam;
import Config.SomeCodes;
import Database.PhotoCleaner;
import SecureDongle.SecureDongle;
import SecureDongle.SecureDongleEvent;
import javafx.application.Application;
@@ -14,23 +15,29 @@ import javafx.stage.Stage;
import org.tinylog.Logger;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static Config.SomeCodes.ShowAlert;
import static Config.SomeCodes.config;
import static Config.SomeCodes.*;
public class MainApplication extends Application {
final String version = "29102025-STAGING-1.0.8";
PhotoCleaner photoCleaner;
public static Map<Integer, Detectors> detectorsList = new HashMap<>();
@Override
public void start(Stage stage) throws IOException {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (photoCleaner!=null) photoCleaner.Stop();
System.out.println("ShutdownHook Checking running threads...");
Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
for(Thread thread : allThreads.keySet()){
System.out.println("Thread: " + thread.getName()+", State: " + thread.getState()+", Daemon: " + thread.isDaemon());
//thread.interrupt();
}
// Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
// for(Thread thread : allThreads.keySet()){
// System.out.println("Thread: " + thread.getName()+", State: " + thread.getState()+", Daemon: " + thread.isDaemon());
// thread.interrupt();
// }
}));
@@ -40,13 +47,29 @@ public class MainApplication extends Application {
String UserID = Integer.toHexString(sd.ReadUserID()) ;
sd.Close();
if (UserID.equals("14022025")){
Logger.info("Secure Dongle UserID valid");
if (UserID.equals("14022025") || UserID.equals("3102025")){
// 14022025 = Erha, 3102025 = Dermies
DermiesMode = !UserID.equals("14022025");
Logger.info("Secure Dongle UserID valid for "+(DermiesMode?"Dermies":"Erha"));
if (DermiesMode){
boolean needsave = false;
if (!config.getCameraRight45().isEmpty()){
System.out.println("Dermies mode, disable Camera 4");
config.SetCameraRight45("");
needsave = true;
}
if (!config.getCameraRight90().isEmpty()){
System.out.println("Dermies mode, disable Camera 5");
config.SetCameraRight90("");
needsave = true;
}
if (needsave) config.Save();
}
FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("main-view.fxml"));
Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
stage.setTitle("MultiCam Capture App for ERHA 09052025-001");
stage.setTitle("MultiCam Capture App for "+(DermiesMode?"Dermies ":"Erha ") + version);
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);
@@ -58,13 +81,16 @@ public class MainApplication extends Application {
Logger.info("Application closed");
});
SomeCodes.LoadQRReader();
Detectors.LoadAllDetectors();
// buang, pindah ke Cameradetail
//Detectors.LoadAllDetectors();
stage.show();
AutoCloseAlert.init();
Logger.info("Application started");
System.out.println("Application version : " + version+" started");
System.out.println("Using "+(config.isProduction()?"Production":"Staging")+" API URL ");
sd.setEvent(new SecureDongleEvent() {
@Override
public void onDongleMissing() {
@@ -82,6 +108,9 @@ public class MainApplication extends Application {
});
sd.StartMonitor();
photoCleaner = new PhotoCleaner(90);
photoCleaner.Start();
} else {
ShowAlert(Alert.AlertType.ERROR, "Secure Dongle UserID not valid", "Secure Dongle UserID not valid", "Secure Dongle UserID not valid");
Logger.error("Secure Dongle UserID not valid");
@@ -102,13 +131,6 @@ public class MainApplication extends Application {
}
@Override
public void stop() throws Exception {
Logger.info("Application stopped");
super.stop();
}
public static void main(String[] args) {
SomeCodes.ExtractResource("/tinylog.properties");
launch();

View File

@@ -9,6 +9,7 @@ import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import org.tinylog.Logger;
import static Config.SomeCodes.DermiesMode;
import static Config.SomeCodes.ValidString;
@SuppressWarnings("unused")
@@ -41,8 +42,9 @@ public class MainView {
@FXML
private void CaptureClick(ActionEvent event){
if (currentselected.equals("capture-view.fxml")) return;
loadContent("capture-view.fxml");
String fxmlfile = DermiesMode?"capture-view-dermies.fxml":"capture-view.fxml";
if (currentselected.equals(fxmlfile)) return;
loadContent(fxmlfile);
}
@FXML

View File

@@ -45,17 +45,8 @@ public class PhotoRow {
imgview.setStyle(borderstyle);
imgview.setOnMouseClicked(e->{
if (e.getClickCount()>=2){
//System.out.println("Photo path: "+photopath);
File ff = new File(photopath);
// System.out.println("Config exists : "+(config!=null));
// System.out.println("Photo directory: "+config.getPhotoDirectory());
// System.out.println("Full quality directory: "+config.getFullQualityDirectory());
// System.out.println("Full Quality Crop directory: "+config.getFullQualityCropDirectory());
// System.out.println("Reduced quality directory: "+config.getCompressedDirectory());
// System.out.println("Reduced quality crop directory: "+config.getCompressedCropDirectory());
//String hires = Path.of(config.getPhotoDirectory(), ff.getName()).toString();
String hires = Path.of(config.getFullQualityDirectory(), ff.getName()).toString();
//System.out.println("Hires: "+hires);
File hiresfile = new File(hires);
if (hiresfile.isFile()){
System.out.println("Opening file: "+hires);

View File

@@ -3,10 +3,7 @@ package id.co.gtc.erhacam;
import FTP.FTPCheck;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import org.bytedeco.javacv.VideoInputFrameGrabber;
@@ -16,15 +13,37 @@ import static Config.SomeCodes.*;
public class SettingView {
@FXML
private ComboBox<String> CameraLeft90;
private Label lblCamera1;
@FXML
private ComboBox<String> CameraLeft45;
private Label lblCamera2;
@FXML
private ComboBox<String> CameraCenter;
private Label lblCamera3;
@FXML
private ComboBox<String> CameraRight45;
private Label lblCamera4;
@FXML
private ComboBox<String> CameraRight90;
private Label lblCamera5;
@FXML
private ComboBox<String> Camera1;
@FXML
private ComboBox<String> Camera2;
@FXML
private ComboBox<String> Camera3;
@FXML
private ComboBox<String> Camera4;
@FXML
private ComboBox<String> Camera5;
@FXML
private Button ApplyCamera1;
@FXML
private Button ApplyCamera2;
@FXML
private Button ApplyCamera3;
@FXML
private Button ApplyCamera4;
@FXML
private Button ApplyCamera5;
@FXML
private TextField FTPHost;
@@ -49,6 +68,158 @@ public class SettingView {
@FXML
private CheckBox FlipCamera;
@FXML
private TextField Cam1TopCrop;
@FXML
private TextField Cam1BottomCrop;
@FXML
private TextField Cam1LeftCrop;
@FXML
private TextField Cam1RightCrop;
@FXML
private TextField Cam2TopCrop;
@FXML
private TextField Cam2BottomCrop;
@FXML
private TextField Cam2LeftCrop;
@FXML
private TextField Cam2RightCrop;
@FXML
private TextField Cam3TopCrop;
@FXML
private TextField Cam3BottomCrop;
@FXML
private TextField Cam3LeftCrop;
@FXML
private TextField Cam3RightCrop;
@FXML
private TextField Cam4TopCrop;
@FXML
private TextField Cam4BottomCrop;
@FXML
private TextField Cam4LeftCrop;
@FXML
private TextField Cam4RightCrop;
@FXML
private TextField Cam5TopCrop;
@FXML
private TextField Cam5BottomCrop;
@FXML
private TextField Cam5LeftCrop;
@FXML
private TextField Cam5RightCrop;
@FXML
private RadioButton apiStaging;
@FXML
private RadioButton apiProduction;
@FXML
public void changeAPIClick(){
if (apiStaging.isSelected()){
config.setAPI(false);
config.Save();
ShowAlert(Alert.AlertType.INFORMATION, "API Change", "API Change", "API Staging is selected, API will use Staging URL");
} else if (apiProduction.isSelected()){
config.setAPI(true);
config.Save();
ShowAlert(Alert.AlertType.INFORMATION, "API Change", "API Change", "API Production is selected, API will use Production URL");
} else {
ShowAlert(Alert.AlertType.ERROR, "API Change Error", "API Change Error", "Please select API Staging or API Production");
}
}
@FXML
private void ApplyCropClick(){
// Apply crop settings for each camera
boolean[] all_correct = {true};
CheckTextField(Cam1TopCrop,all_correct);
CheckTextField(Cam1BottomCrop,all_correct);
CheckTextField(Cam1LeftCrop,all_correct);
CheckTextField(Cam1RightCrop,all_correct);
CheckTextField(Cam2TopCrop,all_correct);
CheckTextField(Cam2BottomCrop,all_correct);
CheckTextField(Cam2LeftCrop,all_correct);
CheckTextField(Cam2RightCrop,all_correct);
CheckTextField(Cam3TopCrop,all_correct);
CheckTextField(Cam3BottomCrop,all_correct);
CheckTextField(Cam3LeftCrop,all_correct);
CheckTextField(Cam3RightCrop,all_correct);
CheckTextField(Cam4TopCrop,all_correct);
CheckTextField(Cam4BottomCrop,all_correct);
CheckTextField(Cam4LeftCrop,all_correct);
CheckTextField(Cam4RightCrop,all_correct);
CheckTextField(Cam5TopCrop,all_correct);
CheckTextField(Cam5BottomCrop,all_correct);
CheckTextField(Cam5LeftCrop,all_correct);
CheckTextField(Cam5RightCrop,all_correct);
if (all_correct[0]){
config.setCam1TopCrop(Cam1TopCrop.getText());
config.setCam1BottomCrop(Cam1BottomCrop.getText());
config.setCam1LeftCrop(Cam1LeftCrop.getText());
config.setCam1RightCrop(Cam1RightCrop.getText());
config.setCam2TopCrop(Cam2TopCrop.getText());
config.setCam2BottomCrop(Cam2BottomCrop.getText());
config.setCam2LeftCrop(Cam2LeftCrop.getText());
config.setCam2RightCrop(Cam2RightCrop.getText());
config.setCam3TopCrop(Cam3TopCrop.getText());
config.setCam3BottomCrop(Cam3BottomCrop.getText());
config.setCam3LeftCrop(Cam3LeftCrop.getText());
config.setCam3RightCrop(Cam3RightCrop.getText());
config.setCam4TopCrop(Cam4TopCrop.getText());
config.setCam4BottomCrop(Cam4BottomCrop.getText());
config.setCam4LeftCrop(Cam4LeftCrop.getText());
config.setCam4RightCrop(Cam4RightCrop.getText());
config.setCam5TopCrop(Cam5TopCrop.getText());
config.setCam5BottomCrop(Cam5BottomCrop.getText());
config.setCam5LeftCrop(Cam5LeftCrop.getText());
config.setCam5RightCrop(Cam5RightCrop.getText());
config.Save();
} else {
ShowAlert(Alert.AlertType.ERROR, "Crop Setting Error", "Crop Setting Error", "Please check your crop settings, some values are invalid");
}
}
private void CheckTextField(TextField tf, boolean[] value){
if (ValidCropValue(tf)){
tf.setStyle("");
} else {
tf.setStyle("-fx-border-color: red;");
value[0] = false;
}
}
private boolean ValidCropValue(TextField tf){
if (tf != null){
double value;
String name = tf.getId();
try {
value = Double.parseDouble(tf.getText());
if (value >= 0.0){
if (name.contains("Top")){
return value <= config.getTopcropmax();
} else if (name.contains("Bottom")){
return value <= config.getBottomcropmax();
} else if (name.contains("Left")){
return value <= config.getLeftcropmax();
} else if (name.contains("Right")){
return value <= config.getRightcropmax();
}
}
} catch (NumberFormatException ignored) {
}
}
return false;
}
final FileChooser jfc = new FileChooser();
@@ -108,9 +279,20 @@ public class SettingView {
config.setCascadeScaleFactor(scale);
config.Save();
Detectors.setFaceMaxSize(max);
Detectors.setFaceMinSize(min);
Detectors.setScaleFactor(scale);
if (MainApplication.detectorsList!=null){
MainApplication.detectorsList.forEach((i,d)-> {
d.setFaceMaxSize(max);
d.setFaceMinSize(min);
d.setScaleFactor(scale);
});
} else {
Logger.error("MainApplication.detectorsList is null, unable to set cascade settings");
}
// Detectors.setFaceMaxSize(max);
// Detectors.setFaceMinSize(min);
// Detectors.setScaleFactor(scale);
ShowAlert(Alert.AlertType.INFORMATION, "Cascade Setting", "Cascade Setting Saved", "Cascade Setting Saved Successfully");
} else show_cascade_alert("Max Size must be greater than Min Size");
@@ -144,13 +326,11 @@ public class SettingView {
}
MirrorCamera.selectedProperty().addListener(((observable, oldValue, newValue) -> {
System.out.println("Mirror option changed to : "+newValue);
config.setMirrorCamera(newValue);
config.Save();
}));
FlipCamera.selectedProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Flip option changed to : "+newValue);
config.setFlipCamera(newValue);
config.Save();
});
@@ -158,32 +338,60 @@ public class SettingView {
Platform.runLater(()->{
CameraLeft90.getItems().clear();
CameraLeft45.getItems().clear();
CameraCenter.getItems().clear();
CameraRight45.getItems().clear();
CameraRight90.getItems().clear();
if (DermiesMode){
lblCamera4.setVisible(false);
lblCamera5.setVisible(false);
Camera4.setVisible(false);
Camera5.setVisible(false);
ApplyCamera4.setVisible(false);
ApplyCamera5.setVisible(false);
Cam4BottomCrop.setVisible(false);
Cam5BottomCrop.setVisible(false);
Cam4TopCrop.setVisible(false);
Cam5TopCrop.setVisible(false);
Cam4LeftCrop.setVisible(false);
Cam5LeftCrop.setVisible(false);
Cam4RightCrop.setVisible(false);
Cam5RightCrop.setVisible(false);
}
Camera1.getItems().clear();
Camera2.getItems().clear();
Camera3.getItems().clear();
if (!DermiesMode){
Camera4.getItems().clear();
Camera5.getItems().clear();
}
Camera1.getItems().add("");
Camera2.getItems().add("");
Camera3.getItems().add("");
if (!DermiesMode){
Camera4.getItems().add("");
Camera5.getItems().add("");
}
CameraLeft90.getItems().add("");
CameraLeft45.getItems().add("");
CameraCenter.getItems().add("");
CameraRight45.getItems().add("");
CameraRight90.getItems().add("");
for(String camera: cameranames){
Logger.info("adding camera : "+camera+" to camera list");
CameraLeft90.getItems().add(camera);
CameraLeft45.getItems().add(camera);
CameraCenter.getItems().add(camera);
CameraRight45.getItems().add(camera);
CameraRight90.getItems().add(camera);
Camera1.getItems().add(camera);
Camera2.getItems().add(camera);
Camera3.getItems().add(camera);
if (!DermiesMode){
Camera4.getItems().add(camera);
Camera5.getItems().add(camera);
}
}
Camera1.setValue(config.getCameraLeft90());
Camera2.setValue(config.getCameraLeft45());
Camera3.setValue(config.getCameraCenter());
if (!DermiesMode){
Camera4.setValue(config.getCameraRight45());
Camera5.setValue(config.getCameraRight90());
}
CameraLeft90.setValue(config.getCameraLeft90());
CameraLeft45.setValue(config.getCameraLeft45());
CameraCenter.setValue(config.getCameraCenter());
CameraRight45.setValue(config.getCameraRight45());
CameraRight90.setValue(config.getCameraRight90());
TextFieldSetText(FTPHost,config.getFTPHost());
TextFieldSetText(FTPPort,config.getFTPPort());
@@ -200,8 +408,34 @@ public class SettingView {
MirrorCamera.setSelected(config.isMirrorCamera());
FlipCamera.setSelected(config.isFlipCamera());
apiStaging.setSelected(!config.isProduction());
apiProduction.setSelected(config.isProduction());
TextFieldSetText(Sharpness,String.valueOf(config.getSharpnessThreshold()));
TextFieldSetText(Cam1TopCrop,String.valueOf(config.getCam1TopCrop()));
TextFieldSetText(Cam1BottomCrop,String.valueOf(config.getCam1BottomCrop()));
TextFieldSetText(Cam1LeftCrop,String.valueOf(config.getCam1LeftCrop()));
TextFieldSetText(Cam1RightCrop,String.valueOf(config.getCam1RightCrop()));
TextFieldSetText(Cam2TopCrop,String.valueOf(config.getCam2TopCrop()));
TextFieldSetText(Cam2BottomCrop,String.valueOf(config.getCam2BottomCrop()));
TextFieldSetText(Cam2LeftCrop,String.valueOf(config.getCam2LeftCrop()));
TextFieldSetText(Cam2RightCrop,String.valueOf(config.getCam2RightCrop()));
TextFieldSetText(Cam3TopCrop,String.valueOf(config.getCam3TopCrop()));
TextFieldSetText(Cam3BottomCrop,String.valueOf(config.getCam3BottomCrop()));
TextFieldSetText(Cam3LeftCrop,String.valueOf(config.getCam3LeftCrop()));
TextFieldSetText(Cam3RightCrop,String.valueOf(config.getCam3RightCrop()));
if (!DermiesMode){
TextFieldSetText(Cam4TopCrop,String.valueOf(config.getCam4TopCrop()));
TextFieldSetText(Cam4BottomCrop,String.valueOf(config.getCam4BottomCrop()));
TextFieldSetText(Cam4LeftCrop,String.valueOf(config.getCam4LeftCrop()));
TextFieldSetText(Cam4RightCrop,String.valueOf(config.getCam4RightCrop()));
TextFieldSetText(Cam5TopCrop,String.valueOf(config.getCam5TopCrop()));
TextFieldSetText(Cam5BottomCrop,String.valueOf(config.getCam5BottomCrop()));
TextFieldSetText(Cam5LeftCrop,String.valueOf(config.getCam5LeftCrop()));
TextFieldSetText(Cam5RightCrop,String.valueOf(config.getCam5RightCrop()));
}
});
}
@@ -211,27 +445,27 @@ public class SettingView {
@FXML
private void ApplyCameraLeft90(){
config.SetCameraLeft90(CameraLeft90.getValue());
config.SetCameraLeft90(Camera1.getValue());
}
@FXML
private void ApplyCameraLeft45(){
config.SetCameraLeft45(CameraLeft45.getValue());
config.SetCameraLeft45(Camera2.getValue());
}
@FXML
private void ApplyCameraFront(){
config.SetCameraCenter(CameraCenter.getValue());
config.SetCameraCenter(Camera3.getValue());
}
@FXML
private void ApplyCameraRight45(){
config.SetCameraRight45(CameraRight45.getValue());
config.SetCameraRight45(Camera4.getValue());
}
@FXML
private void ApplyCameraRight90(){
config.SetCameraRight90(CameraRight90.getValue());
config.SetCameraRight90(Camera5.getValue());
}
@FXML

View File

@@ -16,6 +16,7 @@ module id.co.gtc.erhacam {
requires java.sql;
requires javafx.graphics;
requires java.net.http;
requires org.tinylog.impl;
opens id.co.gtc.erhacam to javafx.fxml;

View File

@@ -39,7 +39,6 @@ import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicBoolean;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.frontalfaceDetector;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
import static org.bytedeco.opencv.global.opencv_core.mean;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
@@ -776,11 +775,11 @@ public class Cameradetail_Arducam {
* @return true if face detected, otherwise false
*/
private RectVector DetectFace(UMat graymat){
if (frontalfaceDetector!=null){
val face = new RectVector();
frontalfaceDetector.detectMultiScale(graymat, face);
return face;
}
// if (frontalfaceDetector!=null){
// val face = new RectVector();
// frontalfaceDetector.detectMultiScale(graymat, face);
// return face;
// }
return null;
}

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="CaptureViewAnchor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.CaptureView">
<children>
<GridPane layoutX="147.0" layoutY="239.0" AnchorPane.bottomAnchor="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane fx:id="cam1" prefHeight="200.0" prefWidth="200.0" />
<AnchorPane fx:id="cam2" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
<AnchorPane fx:id="cam3" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" />
</children>
</GridPane>
<GridPane layoutX="99.0" layoutY="147.0" style="-fx-grid-lines-visible: true;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="10.0" prefHeight="175.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane fx:id="controlpane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<padding>
<Insets top="5.0" />
</padding>
<children>
<Button fx:id="TakePhotoButton" disable="true" mnemonicParsing="false" onAction="#TakePhotos" prefHeight="175.0" prefWidth="512.0" text="Take Photo" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
<font>
<Font size="48.0" />
</font>
</Button>
</children></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<GridPane layoutX="68.0" layoutY="14.0" prefHeight="175.2" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="31.0" layoutY="6.0" prefHeight="30.0" prefWidth="154.0" text="Nomor Barcode" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label layoutX="63.0" layoutY="6.0" prefHeight="30.4" prefWidth="154.4" text="Medical Record ID" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label layoutX="63.0" layoutY="5.0" prefHeight="30.4" prefWidth="154.4" text="Patient Name" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextArea fx:id="barcodeData" editable="false" layoutX="-21.0" layoutY="-85.0" prefHeight="115.0" prefWidth="358.0" promptText="barcode read result" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextArea fx:id="medicalRecordID" editable="false" layoutX="14.0" layoutY="-84.0" prefHeight="116.0" prefWidth="358.4" promptText="medical record ID" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<TextArea fx:id="PatientName" editable="false" layoutX="-21.0" layoutY="-84.0" prefHeight="116.0" prefWidth="358.4" promptText="patient name" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
</children>
</GridPane>
</children></AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>

View File

@@ -30,20 +30,23 @@
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane fx:id="camerassetting" prefHeight="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
<ColumnConstraints percentWidth="40.0" />
<ColumnConstraints percentWidth="40.0" />
<ColumnConstraints percentWidth="20.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<GridPane>
<AnchorPane>
<children>
<GridPane fx:id="cameraselection" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="25.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<ColumnConstraints percentWidth="25" />
<ColumnConstraints percentWidth="50" />
<ColumnConstraints percentWidth="25" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
@@ -53,124 +56,148 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="30.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Left 90" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label layoutX="44.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Left 45" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label fx:id="lblCamera1" layoutX="30.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Cam 1" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label layoutX="30.0" layoutY="6.0" prefHeight="40.8" prefWidth="87.2" text="Center" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label fx:id="lblCamera2" layoutX="44.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Cam 2" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<Label layoutX="24.0" layoutY="6.0" prefHeight="40.0" prefWidth="87.2" text="Right 45" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label fx:id="lblCamera3" layoutX="30.0" layoutY="6.0" prefHeight="40.8" prefWidth="87.2" text="Cam 3" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<Label layoutX="36.0" layoutY="11.0" prefHeight="40.0" prefWidth="87.2" text="Right 90" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<ComboBox fx:id="CameraLeft90" layoutX="54.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<ComboBox fx:id="CameraLeft45" layoutX="26.0" layoutY="14.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<ComboBox fx:id="CameraCenter" layoutX="88.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<children>
<ComboBox fx:id="CameraRight45" layoutX="54.0" layoutY="8.0" prefHeight="40.0" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="4">
<children>
<ComboBox fx:id="CameraRight90" layoutX="75.0" layoutY="1.0" prefHeight="40.0" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Button layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraLeft90" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
<children>
<Button layoutX="22.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraLeft45" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="2">
<children>
<Button layoutX="18.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraFront" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="3">
<children>
<Button layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight45" prefHeight="40.0" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="4">
<children>
<Button layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight90" prefHeight="40.0" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
<Label fx:id="lblCamera4" layoutX="24.0" layoutY="6.0" prefHeight="40.0" prefWidth="87.2" text="Cam 4" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">
<children>
<Label layoutX="60.0" prefHeight="40.0" prefWidth="175.0" text="Mirror Camera" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label fx:id="lblCamera5" layoutX="36.0" layoutY="11.0" prefHeight="40.0" prefWidth="87.2" text="Cam 5" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<ComboBox fx:id="Camera1" layoutX="54.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<ComboBox fx:id="Camera2" layoutX="26.0" layoutY="14.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<children>
<ComboBox fx:id="Camera3" layoutX="88.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="4">
<children>
<ComboBox fx:id="Camera4" layoutX="54.0" layoutY="8.0" prefHeight="40.0" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="5">
<children>
<CheckBox fx:id="MirrorCamera" layoutX="30.0" layoutY="6.0" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
<ComboBox fx:id="Camera5" layoutX="75.0" layoutY="1.0" prefHeight="40.0" prefWidth="408.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
<children>
<Button fx:id="ApplyCamera1" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraLeft90" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="2">
<children>
<Button fx:id="ApplyCamera2" layoutX="22.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraLeft45" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="3">
<children>
<Button fx:id="ApplyCamera3" layoutX="18.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraFront" prefHeight="40.8" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="4">
<children>
<Button fx:id="ApplyCamera4" layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight45" prefHeight="40.0" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="5">
<children>
<Button fx:id="ApplyCamera5" layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight90" prefHeight="40.0" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="6">
<children>
<Label prefHeight="40.0" prefWidth="175.0" text="Flip Camera" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label layoutX="60.0" prefHeight="40.0" prefWidth="175.0" text="Mirror" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="6">
<children>
<CheckBox fx:id="FlipCamera" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
<CheckBox fx:id="MirrorCamera" layoutX="30.0" layoutY="6.0" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="7">
<children>
<Label layoutX="32.0" layoutY="19.0" prefHeight="37.0" prefWidth="92.0" text="Sharpness Threshold" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Label prefHeight="40.0" prefWidth="175.0" text="Flip" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="7">
<children>
<CheckBox fx:id="FlipCamera" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="32.0" layoutY="19.0" prefHeight="37.0" prefWidth="92.0" text="Sharpness" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Sharpness" layoutX="35.0" layoutY="2.0" prefHeight="37.0" prefWidth="368.0" promptText="if Sharpness below this number, photos considered as blurred" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="2" GridPane.rowIndex="7">
<AnchorPane GridPane.columnIndex="2">
<children>
<Button mnemonicParsing="false" onAction="#SharpnessApply" prefHeight="37.0" prefWidth="92.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="8">
<children>
<Label text="API Type" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="8">
<children>
<RadioButton fx:id="apiStaging" layoutX="14.0" layoutY="8.0" mnemonicParsing="false" text="Staging" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.topAnchor="2.0">
<toggleGroup>
<ToggleGroup fx:id="apiselect" />
</toggleGroup></RadioButton>
<RadioButton fx:id="apiProduction" layoutX="103.0" layoutY="11.0" mnemonicParsing="false" text="Production" toggleGroup="$apiselect" AnchorPane.bottomAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="2" GridPane.rowIndex="8">
<children>
<Button mnemonicParsing="false" onAction="#changeAPIClick" prefHeight="33.6" prefWidth="102.4" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
</children>
</GridPane>
<GridPane GridPane.columnIndex="1">
</children>
</AnchorPane>
<AnchorPane maxWidth="400.0" GridPane.columnIndex="2">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints prefWidth="300" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
@@ -190,14 +217,10 @@
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<ScrollPane layoutX="5.0" prefHeight="200.8" prefWidth="410.4" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200.0" minWidth="0.0" prefWidth="350.0">
<children>
<GridPane prefHeight="200.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane prefHeight="200.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints percentWidth="70.0" />
<ColumnConstraints percentWidth="30.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
@@ -207,27 +230,27 @@
<children>
<AnchorPane>
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Scale Factor" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Label prefHeight="40.0" text="Scale Factor" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Minimum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Label prefHeight="40.0" text="Minimum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="2">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Maximum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Label prefHeight="40.0" text="Maximum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<TextField fx:id="cascadeScaleFactor" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="1.2" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<TextField fx:id="cascadeScaleFactor" alignment="CENTER" prefHeight="40.0" prefWidth="175.0" text="1.2" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="cascadeMinSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="200" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
<TextField fx:id="cascadeMinSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.0" text="200" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="2">
@@ -239,13 +262,252 @@
</GridPane>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<GridPane fx:id="cropsetting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="50.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<GridPane layoutX="-21.0" layoutY="-31.0" prefHeight="30.4" prefWidth="399.2" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label alignment="CENTER" layoutX="36.0" layoutY="6.0" prefHeight="30.4" prefWidth="100.0" text="Top" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Label alignment="CENTER" text="Bottom" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Label alignment="CENTER" layoutX="7.0" layoutY="8.0" text="Left" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<Label alignment="CENTER" layoutX="36.0" layoutY="8.0" text="Right" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<GridPane prefHeight="50.4" prefWidth="399.2" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="Cam1TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Cam1BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="Cam1LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<TextField fx:id="Cam1RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<GridPane layoutX="-27.0" layoutY="-31.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="Cam2TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Cam2BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="Cam2LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<TextField fx:id="Cam2RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="Cam3TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Cam3BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="Cam3LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<TextField fx:id="Cam3RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="Cam4TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Cam4BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="Cam4LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<TextField fx:id="Cam4RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="Cam5TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="Cam5BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<TextField fx:id="Cam5LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
<children>
<TextField fx:id="Cam5RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children></AnchorPane>
<AnchorPane GridPane.rowIndex="6">
<children>
<Button fx:id="btnApplyCrop" mnemonicParsing="false" onAction="#ApplyCropClick" prefHeight="40.0" prefWidth="399.2" text="Apply Crop" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.