Compare commits
17 commits
metadata-f
...
master
Author | SHA1 | Date | |
---|---|---|---|
bf031ded63 | |||
d6328b9089 | |||
69e1bf4d3c | |||
8f424f81dc | |||
b4ae206fbf | |||
fbbf698aea | |||
1d4e451d09 | |||
bd3cf72931 | |||
535f437ba4 | |||
a54bd586d4 | |||
a150952990 | |||
76f2ea7ce7 | |||
af578f09f4 | |||
87737a5261 | |||
a3fa9590d1 | |||
facea33735 | |||
|
9ac8b808bf |
24 changed files with 289 additions and 97 deletions
|
@ -1 +0,0 @@
|
|||
ImageTagger-Solution
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.8.22" />
|
||||
<option name="version" value="1.9.25" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,4 +1,3 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<list size="1">
|
||||
|
|
3
flatpak/build.sh
Executable file
3
flatpak/build.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
# Script to debug the Flatpak application.
|
||||
flatpak-builder --user --install --force-clean build-dir dev.nuculabs.ImageTagger.yaml
|
||||
flatpak run dev.nuculabs.ImageTagger
|
|
@ -1,3 +0,0 @@
|
|||
# Script to debug the Flatpak application.
|
||||
flatpak-builder --sandbox --user --install --force-clean build-dir dev.nuculabs.ImageTagger.yaml
|
||||
flatpak run dev.nuculabs.ImageTagger
|
|
@ -1,6 +1,6 @@
|
|||
[Desktop Entry]
|
||||
Name=ImageTagger
|
||||
Exec=/app/bin/image/bin/ImageTagger
|
||||
Exec=/app/bin/ImageTagger/bin/ImageTagger
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=dev.nuculabs.ImageTagger
|
||||
|
|
|
@ -2,38 +2,47 @@ id: dev.nuculabs.ImageTagger
|
|||
runtime: org.freedesktop.Platform
|
||||
runtime-version: '23.08'
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: /app/bin/image/bin/ImageTagger
|
||||
sdk-extensions:
|
||||
- org.freedesktop.Sdk.Extension.openjdk17
|
||||
command: /app/bin/ImageTagger/bin/ImageTagger
|
||||
finish-args:
|
||||
# X11 + XShm access
|
||||
- --share=ipc
|
||||
- --socket=fallback-x11
|
||||
# Wayland access
|
||||
# - --socket=wayland
|
||||
- --socket=wayland
|
||||
# GPU acceleration if needed
|
||||
- --device=dri
|
||||
# Needs to save files locally
|
||||
- --filesystem=xdg-pictures
|
||||
- --filesystem=home
|
||||
modules:
|
||||
- name: ImageTagger
|
||||
buildsystem: simple
|
||||
build-options:
|
||||
env:
|
||||
PATH: /app/bin:/usr/bin:/usr/lib/sdk/openjdk17/bin
|
||||
JAVA_HOME: /usr/lib/sdk/openjdk17/jvm/openjdk-17
|
||||
build-args:
|
||||
- --share=network
|
||||
build-commands:
|
||||
- mkdir -p /app/bin/image/
|
||||
- cp -R bin /app/bin/image/
|
||||
- cp -R lib /app/bin/image/
|
||||
- cp -R conf /app/bin/image/
|
||||
- cp -R legal /app/bin/image/
|
||||
- cp -R release /app/bin/image/
|
||||
- cp prediction.onnx img-ai/src/main/resources/dev/nuculabs/imagetagger/ai/
|
||||
- cp prediction_categories.txt img-ai/src/main/resources/dev/nuculabs/imagetagger/ai/
|
||||
- gradle jpackageImage
|
||||
- mkdir -p /app/bin/
|
||||
# Copy ImageTagger folder to /app/bin
|
||||
- ls img-ui/build/jpackage
|
||||
- cp -R img-ui/build/jpackage/ImageTagger /app/bin/
|
||||
- ls /app/bin/
|
||||
# Desktop Integration
|
||||
- chmod +x /app/bin/image/lib/jexec
|
||||
- chmod +x /app/bin/image/lib/jspawnhelper
|
||||
- mkdir -p bin /app/share/{applications,icons/hicolor/512x512/apps,metainfo}
|
||||
- mv ${FLATPAK_ID}.desktop /app/share/applications/${FLATPAK_ID}.desktop
|
||||
- mv ${FLATPAK_ID}.png /app/share/icons/hicolor/512x512/apps/${FLATPAK_ID}.png
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/dnutiu/ImageTagger
|
||||
- type: archive
|
||||
path: ../img-ui/build/distributions/ImageTagger-linux.zip
|
||||
# url: "https://github.com/dnutiu/ImageTagger/releases/download/v1.3/ImageTagger-linux-1.3.zip"
|
||||
# sha256: 0f086e6a738b3d59e3d05cce9174316d95886e50278c03e5b452a67fd264ea40
|
||||
url: https://github.com/dnutiu/ImageTagger/releases/download/v1/AIModels.zip
|
||||
sha256: "bbe80bf135621897bc6186d8f17b889064717ed3b9951702b33be869e522321c"
|
||||
- type: file
|
||||
path: dev.nuculabs.ImageTagger.png
|
||||
- type: file
|
||||
|
|
|
@ -2,17 +2,8 @@
|
|||
|
||||
This directory contains the flatpak build files.
|
||||
|
||||
If you are on Linux and would like to install this application as a Flatpak image then
|
||||
build the application with gradle:
|
||||
|
||||
```
|
||||
# in parrent folder:
|
||||
./gradlew jlinkZip
|
||||
```
|
||||
|
||||
And execute:
|
||||
If you are on Linux and would like to install this application as a Flatpak then execute
|
||||
|
||||
```shell
|
||||
cd flatpak
|
||||
./debug.sh
|
||||
./build.sh
|
||||
```
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
plugins {
|
||||
id("java")
|
||||
kotlin("jvm") version "1.8.22"
|
||||
kotlin("jvm") version "1.9.25"
|
||||
id("org.javamodularity.moduleplugin") version "1.8.12"
|
||||
|
||||
}
|
||||
|
||||
var junitVersion = "5.10.0"
|
||||
group = "dev.nuculabs.imagetagger.ai"
|
||||
version = "1.1"
|
||||
version = "1.4"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
plugins {
|
||||
id("java")
|
||||
kotlin("jvm") version "1.8.22"
|
||||
kotlin("jvm") version "1.9.25"
|
||||
id("org.javamodularity.moduleplugin") version "1.8.12"
|
||||
}
|
||||
|
||||
group = "dev.nuculabs.imagetagger.core"
|
||||
version = "1.1"
|
||||
version = "1.4"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
plugins {
|
||||
id("java")
|
||||
id("application")
|
||||
id("org.jetbrains.kotlin.jvm") version "1.8.22"
|
||||
id("org.jetbrains.kotlin.jvm") version "1.9.25"
|
||||
id("org.javamodularity.moduleplugin") version "1.8.12"
|
||||
id("org.openjfx.javafxplugin") version "0.0.13"
|
||||
id("org.beryx.jlink") version "2.25.0"
|
||||
}
|
||||
|
||||
group "com.nuculabs.dev"
|
||||
version "1.3"
|
||||
version "1.4"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -63,6 +63,9 @@ jlink {
|
|||
unixScriptTemplate = project.file("${layout.projectDirectory}/src/main/resources/unixExecutableScriptTemplate.txt")
|
||||
name = "ImageTagger"
|
||||
}
|
||||
jpackage {
|
||||
icon = "${layout.projectDirectory}/src/main/resources/dev/nuculabs/imagetagger/ui/image-analysis.png"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.jlinkZip {
|
||||
|
|
|
@ -18,7 +18,7 @@ module dev.nuculabs.imagetagger.ui {
|
|||
requires org.apache.commons.lang3;
|
||||
|
||||
opens dev.nuculabs.imagetagger.ui to javafx.fxml, javafx.graphics;
|
||||
opens dev.nuculabs.imagetagger.ui.controls to javafx.fxml, javafx.graphics;
|
||||
opens dev.nuculabs.imagetagger.ui.controls to javafx.fxml, javafx.graphics, javafx.base;
|
||||
opens dev.nuculabs.imagetagger.ui.pages to javafx.fxml, javafx.graphics;
|
||||
exports dev.nuculabs.imagetagger.ui;
|
||||
}
|
|
@ -43,16 +43,13 @@ class MainPage : Application() {
|
|||
// Set up the stage.
|
||||
stage.title = "Image Tagger"
|
||||
stage.scene = scene
|
||||
stage.minWidth = 640.0
|
||||
stage.minWidth = 960.0
|
||||
stage.minHeight = 760.0
|
||||
// Whe the main window is hidden we exit the application.
|
||||
stage.setOnHidden {
|
||||
Platform.exit()
|
||||
}
|
||||
|
||||
// Add menu bar
|
||||
// (scene.root as BorderPane).children.add(ApplicationMenuBar(mainPageController))
|
||||
|
||||
stage.show()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package dev.nuculabs.imagetagger.ui
|
||||
|
||||
import dev.nuculabs.imagetagger.core.AnalyzedImage
|
||||
import dev.nuculabs.imagetagger.ui.controls.ImageTagsDisplayMode
|
||||
import dev.nuculabs.imagetagger.ui.controls.ImageTagsEntryControl
|
||||
import dev.nuculabs.imagetagger.ui.controls.ImageTagsSessionHeader
|
||||
import javafx.application.Platform
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.fxml.FXML
|
||||
import javafx.scene.control.Button
|
||||
import javafx.scene.control.ChoiceBox
|
||||
import javafx.scene.control.ProgressBar
|
||||
import javafx.scene.control.Separator
|
||||
import javafx.scene.layout.HBox
|
||||
|
@ -58,6 +61,16 @@ class MainPageController {
|
|||
*/
|
||||
private var isCurrentTagsOperationCancelled: Boolean = false
|
||||
|
||||
/**
|
||||
* Holds a list of predicted images controls that are rendered in the view.
|
||||
*/
|
||||
private var predictedImages: MutableList<ImageTagsEntryControl> = ArrayList()
|
||||
|
||||
/**
|
||||
* Controls how image tags are displayed on the screen.
|
||||
*/
|
||||
private var tagsDisplayMode: ImageTagsDisplayMode = ImageTagsDisplayMode.Comma
|
||||
|
||||
@FXML
|
||||
private lateinit var progressBar: ProgressBar
|
||||
|
||||
|
@ -68,7 +81,10 @@ class MainPageController {
|
|||
private lateinit var cancelButton: Button
|
||||
|
||||
@FXML
|
||||
lateinit var tagImagesButton: Button
|
||||
private lateinit var tagImagesButton: Button
|
||||
|
||||
@FXML
|
||||
private lateinit var tagsDisplayModeSelection: ChoiceBox<String>
|
||||
|
||||
/**
|
||||
* Initializes the controller. Needs to be called after the dependencies have been injected.
|
||||
|
@ -76,6 +92,28 @@ class MainPageController {
|
|||
fun initialize() {
|
||||
HBox.setHgrow(progressBar, Priority.ALWAYS)
|
||||
HBox.setHgrow(cancelButton, Priority.ALWAYS)
|
||||
|
||||
initializeTagsDisplayMode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the tags display mode.
|
||||
*/
|
||||
private fun initializeTagsDisplayMode() {
|
||||
// Tags display mode
|
||||
tagsDisplayModeSelection.items = FXCollections.observableArrayList(
|
||||
ImageTagsDisplayMode.entries.map { it.toString() }
|
||||
)
|
||||
tagsDisplayModeSelection.value = ImageTagsDisplayMode.default().toString()
|
||||
|
||||
tagsDisplayModeSelection.selectionModel.selectedItemProperty().addListener { _, oldValue, newValue ->
|
||||
if (oldValue != newValue && newValue != null) {
|
||||
tagsDisplayMode = ImageTagsDisplayMode.fromString(newValue)
|
||||
predictedImages.forEach {
|
||||
it.setTagsDisplayMode(tagsDisplayMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,7 +186,10 @@ class MainPageController {
|
|||
fun addNewImagePredictionEntry(
|
||||
analyzedImage: AnalyzedImage,
|
||||
) {
|
||||
verticalBox.children.add(ImageTagsEntryControl(analyzedImage))
|
||||
val control = ImageTagsEntryControl(analyzedImage)
|
||||
control.setTagsDisplayMode(tagsDisplayMode)
|
||||
verticalBox.children.add(control)
|
||||
predictedImages.add(control)
|
||||
verticalBox.children.add(Separator())
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package dev.nuculabs.imagetagger.ui.controls
|
||||
|
||||
/**
|
||||
* Determines how tags are displayed
|
||||
*/
|
||||
enum class ImageTagsDisplayMode {
|
||||
Comma,
|
||||
HashTags,
|
||||
Space;
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Builds the enum value from a given string.
|
||||
*
|
||||
* @param value - The string
|
||||
* @throws IllegalArgumentException when an invalid value is provided.
|
||||
*/
|
||||
fun fromString(value: String): ImageTagsDisplayMode {
|
||||
return when (value) {
|
||||
"Comma" -> Comma
|
||||
"Space" -> Space
|
||||
"HashTags" -> HashTags
|
||||
else -> throw IllegalArgumentException("Invalid argument $value")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default tags display mode.
|
||||
*/
|
||||
fun default(): ImageTagsDisplayMode {
|
||||
return Comma
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,11 +2,13 @@ package dev.nuculabs.imagetagger.ui.controls
|
|||
|
||||
import dev.nuculabs.imagetagger.core.AnalyzedImage
|
||||
import dev.nuculabs.imagetagger.ui.alerts.ErrorAlert
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.fxml.FXML
|
||||
import javafx.fxml.FXMLLoader
|
||||
import javafx.scene.control.Button
|
||||
import javafx.scene.control.Label
|
||||
import javafx.scene.control.TableView
|
||||
import javafx.scene.control.TextArea
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.image.ImageView
|
||||
|
@ -15,6 +17,7 @@ import javafx.scene.input.ClipboardContent
|
|||
import javafx.scene.input.MouseEvent
|
||||
import javafx.scene.layout.HBox
|
||||
import javafx.scene.layout.VBox
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import java.awt.Desktop
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
@ -40,6 +43,16 @@ class ImageTagsEntryControl(private val image: AnalyzedImage) : HBox() {
|
|||
@FXML
|
||||
private lateinit var predictedImageTags: TextArea
|
||||
|
||||
/**
|
||||
* Holds the tags.
|
||||
*/
|
||||
private var tags: List<String> = ArrayList()
|
||||
|
||||
/**
|
||||
* Sets the default image tags display mode.
|
||||
*/
|
||||
private var tagsDisplayMode: ImageTagsDisplayMode = ImageTagsDisplayMode.Comma
|
||||
|
||||
/**
|
||||
* The file name label.
|
||||
*/
|
||||
|
@ -59,22 +72,7 @@ class ImageTagsEntryControl(private val image: AnalyzedImage) : HBox() {
|
|||
private lateinit var metadataVbox: VBox
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataAuthor: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataCamera: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataLens: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataISO: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataAperture: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var metadataShutterSpeed: Label
|
||||
private lateinit var metadataTableView: TableView<ImageTagsEntryModel>
|
||||
|
||||
init {
|
||||
val resource = ImageTagsEntryControl::class.java.getResource("image-tags-entry.fxml")
|
||||
|
@ -89,10 +87,10 @@ class ImageTagsEntryControl(private val image: AnalyzedImage) : HBox() {
|
|||
}
|
||||
setImage(image)
|
||||
if (image.hasError()) {
|
||||
setText(listOf(image.errorMessage()))
|
||||
setTags(listOf(image.errorMessage()))
|
||||
metadataVbox.isVisible = false
|
||||
} else {
|
||||
setText(image.tags())
|
||||
setTags(image.tags())
|
||||
setMetadata()
|
||||
}
|
||||
|
||||
|
@ -122,8 +120,38 @@ class ImageTagsEntryControl(private val image: AnalyzedImage) : HBox() {
|
|||
*
|
||||
* @param predictions The prediction list.
|
||||
*/
|
||||
private fun setText(predictions: List<String>) {
|
||||
predictedImageTags.text = predictions.joinToString { it }
|
||||
fun setTags(predictions: List<String>) {
|
||||
tags = predictions
|
||||
updateTags()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tags display mode.
|
||||
*
|
||||
* @param mode The image tags display mode.
|
||||
*/
|
||||
fun setTagsDisplayMode(mode: ImageTagsDisplayMode) {
|
||||
tagsDisplayMode = mode
|
||||
updateTags()
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the tags text.
|
||||
*/
|
||||
private fun updateTags() {
|
||||
predictedImageTags.text = when (tagsDisplayMode) {
|
||||
ImageTagsDisplayMode.Comma -> {
|
||||
tags.joinToString { it }
|
||||
}
|
||||
ImageTagsDisplayMode.HashTags -> {
|
||||
tags.joinToString(separator = " ") {
|
||||
"#${it}"
|
||||
}
|
||||
}
|
||||
ImageTagsDisplayMode.Space -> {
|
||||
tags.joinToString(separator = " ") { it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,12 +159,24 @@ class ImageTagsEntryControl(private val image: AnalyzedImage) : HBox() {
|
|||
*/
|
||||
private fun setMetadata() {
|
||||
val imageMetadata = image.metadata()
|
||||
metadataAuthor.text = "Author: ${imageMetadata.artist}"
|
||||
metadataCamera.text = "Camera: ${imageMetadata.cameraBrand} ${imageMetadata.cameraModel}"
|
||||
metadataLens.text = "Lens: ${imageMetadata.lensModel}"
|
||||
metadataISO.text = "ISO: ${imageMetadata.iso}"
|
||||
metadataAperture.text = "Aperture: ${imageMetadata.aperture}"
|
||||
metadataShutterSpeed.text = "Shutter Speed: ${imageMetadata.shutterSpeed}"
|
||||
val metadataValues = listOf(
|
||||
ImageTagsEntryModel("Author", imageMetadata.artist),
|
||||
ImageTagsEntryModel("Brand", imageMetadata.cameraBrand),
|
||||
ImageTagsEntryModel("Model", imageMetadata.cameraModel),
|
||||
ImageTagsEntryModel("Lens", imageMetadata.lensModel),
|
||||
ImageTagsEntryModel("ISO", imageMetadata.iso),
|
||||
ImageTagsEntryModel("Aperture", imageMetadata.aperture),
|
||||
ImageTagsEntryModel("Shutter Speed", imageMetadata.shutterSpeed),
|
||||
).filterNot { it.getValue() == "Unknown" }
|
||||
val data: ObservableList<ImageTagsEntryModel> = FXCollections.observableArrayList(
|
||||
metadataValues
|
||||
)
|
||||
if (data.size == 0) {
|
||||
metadataVbox.isVisible = false
|
||||
return
|
||||
}
|
||||
metadataTableView.items = data
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package dev.nuculabs.imagetagger.ui.controls
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.beans.property.StringProperty
|
||||
|
||||
/**
|
||||
* ImageTagsEntryModel represents a metadata and it's associated value.
|
||||
*/
|
||||
class ImageTagsEntryModel(metadata: String, value: String) {
|
||||
private val metadata: StringProperty = SimpleStringProperty(metadata)
|
||||
private val value: StringProperty = SimpleStringProperty(value)
|
||||
|
||||
fun getMetadata(): String {
|
||||
return metadata.get()
|
||||
}
|
||||
|
||||
fun setMetadata(metadata: String) {
|
||||
this.metadata.set(metadata)
|
||||
}
|
||||
|
||||
fun metadataProperty(): StringProperty {
|
||||
return metadata
|
||||
}
|
||||
|
||||
fun getValue(): String {
|
||||
return value.get()
|
||||
}
|
||||
|
||||
fun setValue(value: String) {
|
||||
this.value.set(value)
|
||||
}
|
||||
|
||||
fun valueProperty(): StringProperty {
|
||||
return value
|
||||
}
|
||||
}
|
|
@ -65,7 +65,8 @@ class ImageTagsSessionHeader : HBox() {
|
|||
|
||||
// update header title
|
||||
val shortDate = dateTimeProvider.getTodayShortDate()
|
||||
this.title.text = "$shortDate ($numberOfImages Images)"
|
||||
val shortTime = dateTimeProvider.getTodayTime()
|
||||
this.title.text = "$shortDate - $shortTime - ($numberOfImages Images)"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,8 @@ interface IDateTimeProvider {
|
|||
* Returns today's short date. For example: 09 April 2024
|
||||
*/
|
||||
fun getTodayShortDate(): String
|
||||
|
||||
fun getTodayTime(): String
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,4 +26,13 @@ class DateTimeProvider : IDateTimeProvider {
|
|||
val date = Date()
|
||||
return dateFormat.format(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns today's short time. Example: 15:30
|
||||
*/
|
||||
override fun getTodayTime(): String {
|
||||
val dateFormat: DateFormat = SimpleDateFormat("HH:mm", Locale.ENGLISH)
|
||||
val date = Date()
|
||||
return dateFormat.format(date)
|
||||
}
|
||||
}
|
|
@ -6,31 +6,22 @@
|
|||
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml" stylesheets="@image-tags-entry.css">
|
||||
<StackPane prefWidth="244" prefHeight="244">
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml" stylesheets="@image-tags-entry.css"
|
||||
minHeight="250">
|
||||
<StackPane minWidth="244" prefWidth="244" prefHeight="244">
|
||||
<ImageView fx:id="imageView"/>
|
||||
</StackPane>
|
||||
<VBox>
|
||||
<VBox minWidth="300" >
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<HBox>
|
||||
<VBox>
|
||||
<Label fx:id="fileNameLabel"/>
|
||||
<Label text="Predicted tags:"/>
|
||||
<Label text="Tags:"/>
|
||||
<TextArea fx:id="predictedImageTags" editable="false" wrapText="true" prefColumnCount="20"/>
|
||||
</VBox>
|
||||
<VBox fx:id="metadataVbox">
|
||||
<padding>
|
||||
<Insets left="10.0" top="35.0"/>
|
||||
</padding>
|
||||
<Label fx:id="metadataAuthor" text="Author: " />
|
||||
<Label fx:id="metadataCamera" text="Camera:" />
|
||||
<Label fx:id="metadataLens" text="Lens:" />
|
||||
<Label fx:id="metadataISO" text="ISO:" />
|
||||
<Label fx:id="metadataAperture" text="Aperture" />
|
||||
<Label fx:id="metadataShutterSpeed" text="Shutter Speed" />
|
||||
</VBox>
|
||||
</HBox>
|
||||
<HBox>
|
||||
<padding>
|
||||
|
@ -43,5 +34,20 @@
|
|||
</Button>
|
||||
</HBox>
|
||||
</VBox>
|
||||
|
||||
<VBox fx:id="metadataVbox" VBox.vgrow="ALWAYS">
|
||||
<TableView fx:id="metadataTableView" minWidth="400" maxWidth="Infinity" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn text="Metadata">
|
||||
<cellValueFactory>
|
||||
<PropertyValueFactory property="metadata"/>
|
||||
</cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn text="Value">
|
||||
<cellValueFactory>
|
||||
<PropertyValueFactory property="value"/>
|
||||
</cellValueFactory>
|
||||
</TableColumn>
|
||||
</columns>
|
||||
</TableView>
|
||||
</VBox>
|
||||
</fx:root>
|
|
@ -14,7 +14,7 @@
|
|||
<top>
|
||||
<VBox>
|
||||
<ApplicationMenuBar/>
|
||||
<HBox alignment="CENTER_LEFT">
|
||||
<HBox alignment="CENTER_LEFT" spacing="10">
|
||||
<padding>
|
||||
<Insets bottom="5" left="5" right="5"/>
|
||||
</padding>
|
||||
|
@ -24,6 +24,12 @@
|
|||
</graphic>
|
||||
</Button>
|
||||
<Separator orientation="VERTICAL" style="-fx-padding: 10px"/>
|
||||
<Region HBox.hgrow="ALWAYS"/>
|
||||
<ChoiceBox fx:id="tagsDisplayModeSelection">
|
||||
<tooltip>
|
||||
<Tooltip text="Select how tags are displayed"/>
|
||||
</tooltip>
|
||||
</ChoiceBox>
|
||||
</HBox>
|
||||
</VBox>
|
||||
</top>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
fx:controller="dev.nuculabs.imagetagger.ui.pages.AboutPage"
|
||||
stylesheets="@about-page.css"
|
||||
>
|
||||
<VBox prefHeight="250.0" maxWidth="350" spacing="10">
|
||||
<VBox prefHeight="350.0" maxWidth="350" spacing="10">
|
||||
<padding>
|
||||
<Insets top="25" bottom="25" right="15" left="15"/>
|
||||
</padding>
|
||||
|
|
25
readme.md
25
readme.md
|
@ -49,14 +49,30 @@ To run:
|
|||
gradlew run
|
||||
```
|
||||
|
||||
### Building the FlatPak
|
||||
### Building the Flatpak
|
||||
|
||||
To build the Flatpak run the following commands:
|
||||
|
||||
```shell
|
||||
gradlew jlinkZip
|
||||
cd flatpak
|
||||
flatpak-builder --sandbox --user --install --force-clean build-dir dev.nuculabs.ImageTagger.yaml
|
||||
./build.sh
|
||||
```
|
||||
|
||||
It will build the flatpak using the latest sources from this repo.
|
||||
|
||||
### Building a package (Fedora Example)
|
||||
|
||||
To build a package run
|
||||
|
||||
```shell
|
||||
gradle jpackage <<< "--type rpm"
|
||||
```
|
||||
|
||||
To install and run the application:
|
||||
|
||||
```shell
|
||||
dnf install ./img-ui/build/jpackage/imagetagger-1.0-1.x86_64.rpm
|
||||
/opt/imagetagger/bin/ImageTagger
|
||||
```
|
||||
|
||||
# Blog
|
||||
|
@ -66,4 +82,5 @@ You can visit my tech blog at [https://blog.nuculabs.dev](https://blog.nuculabs.
|
|||
# Credits
|
||||
|
||||
- Icons: <a href="https://www.flaticon.com/free-icons/image-analysis" title="image analysis icons">Image analysis icons
|
||||
created by Dewi Sari - Flaticon</a>
|
||||
created by Dewi Sari - Flaticon</a>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
}
|
||||
rootProject.name = "ImageTagger-Solution"
|
||||
rootProject.name = "ImageTagger"
|
||||
include("img-ui")
|
||||
include("img-ai")
|
||||
include("img-core")
|
||||
|
|
Loading…
Reference in a new issue