annotate src/name/blackcap/imageprep/RotateDialog.kt @ 0:e0efe7848130

Initial commit. Untested!
author David Barts <davidb@stashtea.com>
date Thu, 16 Jul 2020 19:57:23 -0700
parents
children 0bded24f746e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
1 /*
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
2 * Represents a file being edited (rotated)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
3 */
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
4 package name.blackcap.imageprep
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
5
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
6 import java.awt.Graphics2D
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
7 import java.awt.RenderingHints
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
8 import java.awt.image.BufferedImage
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
9 import java.io.File
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
10 import java.io.IOException
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
11 import javax.imageio.ImageIO
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
12 import javax.swing.*
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
13 import kotlin.math.*
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
14
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
15 class RotateDialog(val file: File, initialImage: BufferedImage) : JDialog(Application.mainFrame) {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
16 private val BW = 9
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
17 private val BW2 = BW * 2
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
18 private val MINWIDTH = 512
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
19 private val MINHEIGHT = 384
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
20
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
21 private class DrawingPane() : JPanel() {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
22 var image: BufferedImage = initialImage
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
23 set(value) {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
24 field = value
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
25 revalidate()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
26 repaint()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
27 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
28
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
29 override val preferredSize
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
30 get { return image.preferredSize }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
31
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
32 protected paintComponent(g: Graphics): Unit {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
33 g.drawImage(image, 0, 0, null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
34 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
35 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
36 private val drawingPane = DrawingPane()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
37
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
38 val image: BufferedImage
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
39 get() { return drawingPane.image }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
40
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
41 private val r90cw = JButton("90° CW").apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
42 it.addActionListener(ActionListener { doRotate(90) })
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
43 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
44
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
45 private val r180 = JButton("180°").apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
46 it.addActionListener(ActionListener { doRotate(180) })
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
47 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
48
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
49 private val r90ccw = JButton("90° CCW").apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
50 it.addActionListener(ActionListener { doRotate(270) })
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
51 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
52
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
53 /* Theoretically, this should do the rotation in a background thread.
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
54 Practically, that is fraught with difficulties, as it involves
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
55 manipulating data used by Swing itself. Since the size of the images
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
56 being rotated are small, we do it in the foreground. */
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
57 private fun doRotate(deg: Int) {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
58 // https://stackoverflow.com/questions/15927014/rotating-an-image-90-degrees-in-java
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
59 val rad = java.lang.Math.toRadians(deg.toDouble())
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
60 val sinx = sin(rad)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
61 val cosx = cos(rad)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
62 val w = floor(image.width * cosx + image.height * sinx).toInt()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
63 val h = floor(image.height * cosx + image.width * sinx).toInt()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
64 val rotatedImage = BufferedImage(w, h, image.type)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
65 rotatedImage.createGraphics().run {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
66 translate((w - image.width) / 2, (h - image.height) / 2)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
67 rotate(rad, image.width / 2, image.height / 2)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
68 drawRenderedImage(image, null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
69 dispose()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
70 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
71 drawingPane.image = rotatedImage
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
72 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
73
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
74 init {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
75 defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
76 title = "Untitled"
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
77 contentPane.apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
78 layout = BoxLayout(this, BoxLayout.Y_AXIS)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
79 add(JScrollpane(drawingPane).apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
80 alignmentX = JScrollPane.CENTER_ALIGNMENT
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
81 addBorder(BorderFactory.createEmptyBorder(BW2, BW2, BW, BW2))
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
82 verticalScrollBarPolicy = ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
83 horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
84 background = Application.mainFrame.background
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
85 })
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
86 add(Box(BoxLayout.X_AXIS).apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
87 alignmentX = Box.CENTER_ALIGNMENT
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
88 addBorder(BorderFactory.createEmptyBorder(BW, BW2, BW2, BW2))
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
89 add(JLabel("Rotate:"))
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
90 add(Box.createHorizontalGlue())
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
91 add(r90cw)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
92 add(Box.createHorizontalGlue())
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
93 add(r180)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
94 add(Box.createHorizontalGlue())
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
95 add(r90ccw)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
96 })
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
97 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
98 pack()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
99 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
100
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
101 companion object Factory {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
102 /**
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
103 * Make a dialog asynchronously.
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
104 *
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
105 * @param input java.io.File to read for image.
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
106 */
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
107 fun makeDialog(input: File): Unit {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
108 Application.mainFrame.useWaitCursor()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
109 swingWorker<Pair<BufferedImage?, IOException?> {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
110 inBackground {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
111 try {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
112 val imageIn = ImageIO.read(input) /* IOException */
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
113 val ratio = Settings.maxDimension.toDouble() / max(imageIn.width, imageIn.height).toDouble()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
114 if (ratio >= 1.0) {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
115 null
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
116 } else {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
117 val nWidth = (imageIn.width * ratio).toInt()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
118 val nHeight = (imageIn.height * ratio).toInt()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
119 val imageOut = BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_RGB)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
120 val graphics = imageOut.createGraphics().apply {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
121 setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
122 setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
123 setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
124 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
125 graphics.drawImage(imageIn, 0, 0, nWidth, nHeight, null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
126 Pair(imageOut, null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
127 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
128 } catch (e: IOException) {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
129 Pair(null, e)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
130 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
131 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
132 whenDone {
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
133 Application.mainFrame.useNormalCursor()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
134 val (image, error) = get()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
135 if (error != null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
136 ioExceptionDialog(Application.mainFrame, input, "read", error)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
137 if (image != null)
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
138 RotateDialog(input, image).title = input.getName()
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
139 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
140 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
141 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
142 }
e0efe7848130 Initial commit. Untested!
David Barts <davidb@stashtea.com>
parents:
diff changeset
143 }