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

252 lines
8.1 KiB
Kotlin

package nl.aegeedelft.watermarker
import org.intellij.lang.annotations.Language
import java.awt.BorderLayout
import java.awt.Component
import java.awt.Dimension
import java.awt.Image
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.concurrent.atomic.AtomicInteger
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.fixedRateTimer
import kotlin.concurrent.thread
@Language("RegExp")
val filenameRegex = ".*\\.(png|jpe?g|bmp)".toRegex()
val jf = JFrame("WaterMarker")
val counter = AtomicInteger()
val runbtn = JButton("Run!")
val pbar = JProgressBar()
val dlg = JDialog(jf, "Progress Dialog", true)
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())
runbtn.apply {
addActionListener {
if (watermark != null && outdir != null && basedir != null) {
this.isEnabled = false
thread {
doTheThing(basedir!!, outdir!!, watermark!!)
}
} else {
JOptionPane.showMessageDialog(
jf,
"You have left one of the files empty!",
"Error!",
JOptionPane.ERROR_MESSAGE
)
}
}
}
box.add(runbtn.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
dlg.add(BorderLayout.CENTER, pbar)
dlg.defaultCloseOperation = JDialog.DO_NOTHING_ON_CLOSE
dlg.setSize(300, 75)
dlg.setLocationRelativeTo(jf)
}
fun doTheThing(basedir: File, outdir: File, watermarkpath: File) {
val wmbase = ImageIO.read(watermarkpath)
val scale = 3.6
//JOptionPane.showMessageDialog(jf, "", "Inserting watermark!", JOptionPane.INFORMATION_MESSAGE, ImageIcon(watermark))
//FrmPopUpInfo("Inserting Watermark", watermark)
val files = basedir.listFiles().filter { filenameRegex.matches(it.name) }.chunked(5)
val propersize = files.sumBy { it.size }
counter.set(0)
SwingUtilities.invokeLater {
pbar.value = 0
pbar.maximum = propersize
dlg.isVisible = true
}
fixedRateTimer("theWait", period = 500, initialDelay = 0) {
if (counter.get() == propersize) {
SwingUtilities.invokeLater {
dlg.isVisible = false
runbtn.isEnabled = true
this.cancel()
}
}
}
for (fl in files) {
thread {
for (f in fl) {
if (filenameRegex.matches(f.name.toString()) && !"jpe?g".toRegex().matches(f.extension)) {
val image = ImageIO.read(f)
val combined =
addWM(resize(wmbase, wmbase.width / scale, wmbase.height / scale), 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(resize(wmbase, wmbase.width / scale, wmbase.height / scale), 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()
}
SwingUtilities.invokeLater {
pbar.value = counter.incrementAndGet()
}
}
}
}
}
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
}
fun resize(img: BufferedImage, newW: Double, newH: Double): BufferedImage {
val tmp = img.getScaledInstance(newW.toInt(), newH.toInt(), Image.SCALE_SMOOTH)
val dimg = BufferedImage(newW.toInt(), newH.toInt(), BufferedImage.TYPE_INT_ARGB)
val g2d = dimg.createGraphics()
g2d.drawImage(tmp, 0, 0, null)
g2d.dispose()
return dimg
}
//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 { _, _ ->
// java.util.Timer().schedule(timerTask {
//
// }, 5 * 1000)
// this@FrmPopUpInfo.isVisible = false
//
// this@FrmPopUpInfo.dispose()
// }
//
// this.isVisible = true
// }
//}