WaterMarker/src/main/kotlin/nl/aegeedelft/watermarker/Main.kt

196 lines
6.3 KiB
Kotlin

package nl.aegeedelft.watermarker
import org.intellij.lang.annotations.Language
import java.awt.*
import java.awt.image.BufferedImage
import java.awt.image.RenderedImage
import java.io.BufferedInputStream
import java.io.ByteArrayInputStream
import java.io.File
import java.util.*
import javax.imageio.IIOImage
import javax.imageio.ImageIO
import javax.imageio.ImageWriteParam
import javax.imageio.stream.MemoryCacheImageOutputStream
import javax.swing.*
import javax.swing.filechooser.FileFilter
import kotlin.concurrent.timerTask
@Language("RegExp")
val filenameRegex = ".*\\.(png|jpe?g|bmp)".toRegex()
val jf = JFrame("WaterMarker")
object obs : Observable() {
fun observe() {
setChanged()
}
}
fun main(args: Array<String>) {
var watermark: File? = null
var outdir: File? = null
var basedir: File? = null
val basepicker = JFileChooser()
val bds = JLabel("Pick an input folder")
val outpicker = JFileChooser()
val ods = JLabel("Pick an output folder")
val wmpicker = JFileChooser()
val wms = JLabel("Pick a Watermark file")
val box = Box.createVerticalBox()
basepicker.currentDirectory = File(".")
basepicker.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
basepicker.isAcceptAllFileFilterUsed = false
outpicker.currentDirectory = File(".")
outpicker.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
outpicker.isAcceptAllFileFilterUsed = false
wmpicker.currentDirectory = File(".")
wmpicker.fileSelectionMode = JFileChooser.FILES_ONLY
wmpicker.fileFilter = object : FileFilter() {
override fun accept(f: File): Boolean = filenameRegex.matches(f.name) or f.isDirectory
override fun getDescription(): String = "Image Files"
}
wmpicker.isAcceptAllFileFilterUsed = false
box.add(
JButton("Select Input").apply {
addActionListener {
val c = basepicker.showOpenDialog(jf)
if (c == JFileChooser.APPROVE_OPTION) {
basedir = basepicker.selectedFile
bds.text = basepicker.selectedFile.path
}
}
}.forceToCenter()
)
box.add(bds.forceToCenter())
box.add(
JButton("Select Output").apply {
addActionListener {
val c = outpicker.showOpenDialog(jf)
if (c == JFileChooser.APPROVE_OPTION) {
outdir = outpicker.selectedFile
ods.text = outpicker.selectedFile.path
}
}
}.forceToCenter()
)
box.add(ods.forceToCenter())
box.add(
JButton("Select Watermark").apply {
addActionListener {
val c = wmpicker.showOpenDialog(jf)
if (c == JFileChooser.APPROVE_OPTION) {
watermark = wmpicker.selectedFile
wms.text = wmpicker.selectedFile.path
}
}
}.forceToCenter()
)
box.add(wms.forceToCenter())
box.add(JButton("Run!").apply {
addActionListener {
if (watermark != null && outdir != null && basedir != null) {
doTheThing(basedir!!, outdir!!, watermark!!)
} else {
JOptionPane.showMessageDialog(
jf,
"You have left one of the files empty!",
"Error!",
JOptionPane.ERROR_MESSAGE
)
}
}
}.forceToCenter())
jf.add(box, BorderLayout.CENTER)
jf.setLocationRelativeTo(null)
jf.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
jf.preferredSize = Dimension(300, 300)
jf.size = jf.preferredSize
jf.isVisible = true
}
fun doTheThing(basedir: File, outdir: File, watermarkpath: File) {
val watermark = ImageIO.read(watermarkpath)
//JOptionPane.showMessageDialog(jf, "", "Inserting watermark!", JOptionPane.INFORMATION_MESSAGE, ImageIcon(watermark))
FrmPopUpInfo("Inserting Watermark", watermark)
for (f in basedir.listFiles()) {
if (filenameRegex.matches(f.name.toString()) && !"jpe?g".toRegex().matches(f.extension)) {
val image = ImageIO.read(f)
val combined = addWM(watermark, image) as RenderedImage
ImageIO.write(combined, "JPG", File(outdir, f.nameWithoutExtension + ".jpg"))
} else {
val `is` = BufferedInputStream(ByteArrayInputStream(f.readBytes()))
val it = ImageIO.getImageReadersByMIMEType("image/jpeg")
val reader = it.next()
val iis = ImageIO.createImageInputStream(`is`)
reader.setInput(iis, false, false)
val image = reader.read(0)
val imageMetadata = reader.getImageMetadata(0)
val combined = addWM(watermark, image) as RenderedImage
val iter = ImageIO.getImageWritersByMIMEType("image/jpeg")
val writer = iter.next()
val iwp = writer.defaultWriteParam
iwp.compressionMode = ImageWriteParam.MODE_EXPLICIT
iwp.compressionQuality = 0.9f
val imgOut = MemoryCacheImageOutputStream(File(outdir, f.nameWithoutExtension + ".jpg").outputStream())
writer.output = imgOut
val ending = IIOImage(combined, null, imageMetadata)
writer.write(null, ending, iwp)
writer.dispose()
}
}
obs.observe()
obs.notifyObservers()
}
fun Component.forceToCenter(): Component = JPanel().apply { this.add(this@forceToCenter) }
fun addWM(watermark: BufferedImage, image: BufferedImage): Image {
val combined = BufferedImage(image.width, image.height, BufferedImage.TYPE_INT_RGB)
val g = combined.graphics
g.drawImage(image, 0, 0, null)
val x = image.width - watermark.width - 5
val y = image.height - watermark.height - 5
g.drawImage(watermark, x, y, null)
return combined
}
class FrmPopUpInfo(message: String, image: Image) : JFrame() {
init {
this.title = message
this.add(JLabel(ImageIcon(image)))
this.background = Color.WHITE
this.pack()
this.setLocationRelativeTo(null)
obs.addObserver { o, arg ->
java.util.Timer().schedule(timerTask {
}, 5 * 1000)
this@FrmPopUpInfo.isVisible = false
this@FrmPopUpInfo.dispose()
}
this.isVisible = true
}
}