Skip to content

Commit

Permalink
Merge pull request #211 from amosproj/gui/feature/export-inserted-frames
Browse files Browse the repository at this point in the history
export for inserted frames
  • Loading branch information
akriese authored Jan 17, 2024
2 parents deb355b + 5680963 commit dc9c37f
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
18 changes: 18 additions & 0 deletions GUI/src/main/kotlin/frameNavigation/FrameNavigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import util.ColoredFrameGenerator
import wrappers.Resettable2DFrameConverter
import java.awt.Color
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
import kotlin.math.roundToInt

/**
Expand Down Expand Up @@ -357,6 +358,23 @@ class FrameNavigation(state: MutableState<AppState>, val scope: CoroutineScope)
javax.imageio.ImageIO.write(collage, "png", file)
}

/**
* Filters all inserted frames.
* @return [List]<[ImageBitmap]> containing the inserted frames.
*/
fun getInsertedFrames(): List<ImageBitmap> {
val insertedFrames = mutableListOf<ImageBitmap>()

for (i in diffSequence.indices) {
if (diffSequence[i] == AlignmentElement.INSERTION) {
video2Grabber.setVideoFrameNumber(video2Frames[i])
insertedFrames.add(getBitmap(video2Grabber))
}
}

return insertedFrames
}

/**
* Get the images at a certain diff index.
*
Expand Down
2 changes: 2 additions & 0 deletions GUI/src/main/kotlin/models/AppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import java.nio.file.FileSystems
* @param saveCollagePath the last path where a collage was saved
* @param saveProjectPath the last path where a project was saved
* @param openProjectPath the last path where a project was opened
* @param saveInsertionsPath the last path where insertions were saved
* @param saveFramePath the last path where a frame was saved
* @param maskPath the path of the mask
* @param sequenceObj the sequence object
Expand All @@ -33,6 +34,7 @@ data class AppState(
var saveProjectPath: String? = null,
var openProjectPath: String? = null,
var saveFramePath: String? = null,
var saveInsertionsPath: String? = null,
var maskPath: String = getPath("mask.png"),
var sequenceObj: Array<AlignmentElement> = arrayOf(),
var gapOpenPenalty: Double = 0.2,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package ui.components.diffScreen

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toAwtImage
import androidx.compose.ui.unit.dp
import frameNavigation.FrameNavigation
import models.AppState
import ui.components.general.openFileSaverAndGetPath
import ui.components.general.showOverwriteConfirmation
import java.io.File
import javax.imageio.ImageIO

/**
* Button to save all inserted frames as pngs to a zip File Archive.
*
* @param navigator The navigator to use to create the archive
* @param modifier The modifier for the button
* @return [Unit]
*/
@Composable
fun SaveInsertedFramesButton(
navigator: FrameNavigation,
modifier: Modifier,
state: MutableState<AppState>,
) {
Button(
modifier = modifier.padding(8.dp).fillMaxSize(),
onClick = {
openFileSaverAndGetPath(
state.value.saveInsertionsPath,
) { path -> saveInsertedFramesCallback(navigator, path, state) }
},
) {
Text(text = "Export Inserted")
}
}

/**
* Callback for when the user selects a file to save.
* Saves the path and creates the zip archive.
* @param navigator The navigator to use to create the archive
* @param path The path to the file to save to
* @param state The state of the app
*/
fun saveInsertedFramesCallback(
navigator: FrameNavigation,
path: String,
state: MutableState<AppState>,
) {
// check path for suffix
var savePath = path
if (!savePath.endsWith(".zip")) {
savePath = "$savePath.zip"
}
if (File(savePath).exists()) {
val overwrite = showOverwriteConfirmation()
if (!overwrite) {
return
}
}
state.value = state.value.copy(saveInsertionsPath = savePath)

createInsertionsExport(savePath, navigator.getInsertedFrames())
}

/**
* Creates a zip archive containing all inserted frames as pngs.
* @param outputPath The path to the zip archive
* @param frames The frames to save
*/
fun createInsertionsExport(
outputPath: String,
frames: List<ImageBitmap>,
) {
val zipFile = File(outputPath)

val zip = java.util.zip.ZipOutputStream(zipFile.outputStream())

for (i in frames.indices) {
zip.putNextEntry(java.util.zip.ZipEntry("insertion_$i.png"))
val awtInsertImage = frames[i].toAwtImage()
ImageIO.write(awtInsertImage, "PNG", zip)
}
zip.close()
}
3 changes: 2 additions & 1 deletion GUI/src/main/kotlin/ui/screens/DiffScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ fun DiffScreen(state: MutableState<AppState>) {
Row(modifier = Modifier.fillMaxWidth()) {
ProjectMenu(state, Modifier.weight(0.1f))
SaveCollageButton(navigator, Modifier.weight(0.1f), state)
Spacer(modifier = Modifier.weight(0.7f))
SaveInsertedFramesButton(navigator, Modifier.weight(0.1f), state)
Spacer(modifier = Modifier.weight(0.6f))
HelpMenu(Modifier.weight(0.1f))
}
}
Expand Down

0 comments on commit dc9c37f

Please sign in to comment.