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) { 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 } }