Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webinterface): add Trendmark advanced settings #139

Merged
merged 8 commits into from
Nov 28, 2024
2 changes: 1 addition & 1 deletion docs/docs/03-usage/11-cli/01-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Use Gradle to build the CLI tool:
*Note:* You must replace `<version>` in the following commands (e.g. `0.1.0-SNAPSHOT`)

1. `cd cli` (if not already there)
2. `./gradlew shadowJar"`
2. `./gradlew shadowJar`
- This will create a standalone jar file: `./build/libs/cli-<version>-all.jar`
3. `java -jar build/libs/cli-<version>-all.jar --help`
- This will print all possible commands of the CLI tool.
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/03-usage/12-webinterface/01-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ the following commands from the root directory of the project:
1. `cd watermarker`
2. `./gradlew publishToMavenLocal`

:::info
The source code comes with enabled source maps to allow frontend debugging. They should be disabled
in production to prevent the exposure of source code. To disable it, add `sourceMaps = false` inside
the `build.gradle.kts`.
:::

## Building from Source (Manual Build)

Use Gradle to manually build and run the webinterface:
Expand Down
17 changes: 17 additions & 0 deletions watermarker/src/commonTest/kotlin/unitTest/WatermarkerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package unitTest

import Platform
import de.fraunhofer.isst.trend.watermarker.SupportedFileType
import de.fraunhofer.isst.trend.watermarker.Watermarker
import de.fraunhofer.isst.trend.watermarker.fileWatermarker.DefaultTranscoding
Expand Down Expand Up @@ -167,6 +168,22 @@ class WatermarkerTest {
assertEquals(expected, result.value)
}

@Test
fun textGetWatermarks_exactlyOneWatermark_successAndWatermark() {
// Arrange
val expected =
listOf(
Watermark.fromString("a"),
)

// Act
val result = watermarker.textGetWatermarks("a a a a a a a a a a")

// Assert
assertTrue(result.isSuccess)
assertEquals(expected, result.value)
}

@Test
fun textGetWatermarks_differentWatermarks_successAndNotSquashedWatermarks() {
// Arrange
Expand Down
1 change: 0 additions & 1 deletion webinterface/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ kotlin {
runTask(
Action {
mainOutputFileName = "main.bundle.js"
sourceMaps = false
devServerProperty =
KotlinWebpackConfig.DevServer(
open = false,
Expand Down
125 changes: 122 additions & 3 deletions webinterface/src/jsMain/kotlin/WatermarkTextEmbedTab.kt
mhellmeier marked this conversation as resolved.
Show resolved Hide resolved
mhellmeier marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import de.fraunhofer.isst.trend.watermarker.Watermarker
import de.fraunhofer.isst.trend.watermarker.fileWatermarker.TextWatermarker
import de.fraunhofer.isst.trend.watermarker.returnTypes.Result
import de.fraunhofer.isst.trend.watermarker.watermarks.TextWatermark
import de.fraunhofer.isst.trend.watermarker.watermarks.Watermark
import io.kvision.core.FontWeight
import io.kvision.core.Placement
import io.kvision.core.TooltipOptions
import io.kvision.core.Trigger
import io.kvision.core.enableTooltip
import io.kvision.core.onInput
import io.kvision.form.FormMethod
import io.kvision.form.check.CheckBox
import io.kvision.form.formPanel
import io.kvision.form.text.Text
import io.kvision.form.text.TextArea
Expand All @@ -24,10 +25,13 @@ import io.kvision.html.ButtonStyle
import io.kvision.html.button
import io.kvision.html.div
import io.kvision.html.span
import io.kvision.i18n.tr
import io.kvision.modal.Confirm
import io.kvision.modal.Modal
import io.kvision.panel.HPanel
import io.kvision.panel.SimplePanel
import io.kvision.panel.fieldsetPanel
import io.kvision.panel.hPanel
import io.kvision.progress.Progress
import io.kvision.progress.progressNumeric
import io.kvision.state.ObservableValue
Expand All @@ -43,6 +47,10 @@ import kotlin.math.round
data class WatermarkerTextForm(
val watermark: String,
val text: String,
val trendmarkCompressed: Boolean,
val trendmarkSized: Boolean,
val trendmarkCRC32: Boolean,
val trendmarkSHA3256: Boolean,
)

class WatermarkTextEmbedTab : SimplePanel() {
Expand Down Expand Up @@ -72,6 +80,62 @@ class WatermarkTextEmbedTab : SimplePanel() {
)
}

private val compressedCheckBox =
CheckBox(label = "Compressed &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Compress the watermark content before embedding into" +
" the text. Good for longer watermarks.",
triggers = listOf(Trigger.HOVER),
),
)
}

private val sizedCheckBox =
CheckBox(label = "Sized &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Include the size of the watermark for additional " +
"verification. Needs a longer cover text content.",
triggers = listOf(Trigger.HOVER),
),
)
}

@Suppress("ktlint:standard:property-naming")
private val CRC32CheckBox =
CheckBox(label = "CRC32 &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Uses the Cyclic Redundancy Check (CRC) " +
"error-detecting code for additional robustness. " +
"Needs a longer cover text content.",
triggers = listOf(Trigger.HOVER),
),
)
}

@Suppress("ktlint:standard:property-naming")
private val SHA3256CheckBox =
CheckBox(label = "SHA3-256 &#9432;", rich = true) {
paddingRight = 20.px
enableTooltip(
TooltipOptions(
title =
"Include a SHA3-256 hash of the watermark for " +
"additional verification. Needs a longer cover text " +
"content.",
triggers = listOf(Trigger.HOVER),
),
)
}

// Progress bar
private var min: Int = -1
private val capacityObservable = ObservableValue(-1)
Expand Down Expand Up @@ -151,7 +215,30 @@ class WatermarkTextEmbedTab : SimplePanel() {
coverTextInput,
required = true,
)
fieldsetPanel(tr("Advanced Settings")) {
hPanel {
div("Trendmark: &#9432;", rich = true) {
paddingRight = 10.px
fontWeight = FontWeight.BOLD
enableTooltip(
TooltipOptions(
title =
"A special type of watermarks using additional " +
"features.",
triggers = listOf(Trigger.HOVER),
),
)
}

add(compressedCheckBox.bind(WatermarkerTextForm::trendmarkCompressed))

add(sizedCheckBox.bind(WatermarkerTextForm::trendmarkSized))

add(CRC32CheckBox.bind(WatermarkerTextForm::trendmarkCRC32))

add(SHA3256CheckBox.bind(WatermarkerTextForm::trendmarkSHA3256))
}
}
add(progressBar)
span().bind(capacityObservable) {
val percentage =
Expand All @@ -164,6 +251,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
// Check if watermark fits into the cover text
watermarkerInput.onInput { updateCapacity() }
coverTextInput.onInput { updateCapacity() }
compressedCheckBox.onInput { updateCapacity() }
sizedCheckBox.onInput { updateCapacity() }
CRC32CheckBox.onInput { updateCapacity() }
SHA3256CheckBox.onInput { updateCapacity() }

mhellmeier marked this conversation as resolved.
Show resolved Hide resolved
textFormPanel.add(
HPanel {
Expand All @@ -178,6 +269,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
addWatermarkToText(
textFormPanel.getData().watermark,
textFormPanel.getData().text,
textFormPanel.getData().trendmarkCompressed,
textFormPanel.getData().trendmarkSized,
textFormPanel.getData().trendmarkCRC32,
textFormPanel.getData().trendmarkSHA3256,
)

if (watermarkedResult.isSuccess) {
Expand Down Expand Up @@ -253,6 +348,10 @@ class WatermarkTextEmbedTab : SimplePanel() {
watermarkFitsInText(
watermarkerInput.value.toString(),
coverTextInput.value.toString(),
compressedCheckBox.value,
sizedCheckBox.value,
CRC32CheckBox.value,
SHA3256CheckBox.value,
)

// Enable or disable the submit form button and user hint
Expand All @@ -277,9 +376,19 @@ class WatermarkTextEmbedTab : SimplePanel() {
private fun addWatermarkToText(
watermarkString: String,
text: String,
trendmarkCompressed: Boolean = false,
trendmarkSized: Boolean = false,
trendmarkCRC32: Boolean = false,
trendmarkSHA3256: Boolean = false,
): Result<String> {
val watermarker = Watermarker()
val watermark = TextWatermark.new(watermarkString)
val watermark =
TextWatermark.raw(watermarkString).apply {
if (trendmarkCompressed) compressed()
if (trendmarkSized) sized()
if (trendmarkCRC32) CRC32()
if (trendmarkSHA3256) SHA3256()
}
return watermarker.textAddWatermark(text, watermark)
}

Expand All @@ -294,8 +403,18 @@ class WatermarkTextEmbedTab : SimplePanel() {
private fun watermarkFitsInText(
watermark: String,
text: String,
trendmarkCompressed: Boolean,
trendmarkSized: Boolean,
trendmarkCRC32: Boolean,
trendmarkSHA3256: Boolean,
): Int {
val parsedWatermark = Watermark.fromString(watermark)
val parsedWatermark =
TextWatermark.raw(watermark).apply {
if (trendmarkCompressed) compressed()
if (trendmarkSized) sized()
if (trendmarkCRC32) CRC32()
if (trendmarkSHA3256) SHA3256()
}

val numberOfInsertPositions = textWatermarker.placement(text).count()
val numberOfNeededPositions = textWatermarker.getMinimumInsertPositions(parsedWatermark)
Expand Down
10 changes: 5 additions & 5 deletions webinterface/src/jsMain/kotlin/WatermarkTextExtractTab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class WatermarkTextExtractTab : SimplePanel() {
if (watermarkedResult.value.isNullOrEmpty()) {
modal.add(
div(
"Could not find any valid watermark in the" +
"Could not find any valid watermark in the " +
"text.",
className = "alert alert-secondary",
),
Expand Down Expand Up @@ -167,22 +167,22 @@ class WatermarkTextExtractTab : SimplePanel() {
modal.add(watermarkDetailsPanel)
}
// Warning
} else if (watermarkedResult.status.isWarning) {
} else if (watermarkedResult.isWarning) {
modal.add(
div(
"Some problems occur during the extraction: " +
watermarkedResult.status.getMessage(),
watermarkedResult.getMessage(),
className = "alert alert-warning",
),
)
modal.add(strong("Extracted Data: "))
modal.add(p(getWatermarkStringList(watermarkedResult).toString()))
// Error
} else if (watermarkedResult.status.isError) {
} else if (watermarkedResult.isError) {
modal.add(
div(
"An error occurs during the extraction: " +
watermarkedResult.status.getMessage(),
watermarkedResult.getMessage(),
className = "alert alert-danger",
),
)
Expand Down
1 change: 0 additions & 1 deletion webinterface/webpack.config.d/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ config.resolve.conditionNames = ['import', 'require', 'default'];

if (config.devServer) {
config.devServer.hot = true;
config.devtool = 'eval-cheap-source-map';
} else {
config.devtool = undefined;
}
Expand Down
Loading