Skip to content

Commit 0bb403b

Browse files
committed
Render GIFs in color, add an animation of solution 2025-07 to the README
1 parent f8b729a commit 0bb403b

File tree

7 files changed

+53
-10
lines changed

7 files changed

+53
-10
lines changed

2025-07_laboratories-animation.gif

473 KB
Loading

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Welcome to the Advent of Code[^aoc] Kotlin project created by [rhaendel][github]
44

55
In this repository, rhaendel is about to provide solutions for the puzzles using [Kotlin][kotlin] language.
66

7+
![Laboratories animation](2025-07_laboratories-animation.gif)
8+
79
## It's all about Learning
810

911
I started this repository in december 2024 using the [Advent of Code Kotlin Template][template] delivered by JetBrains.
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package de.ronny_h.aoc.extensions.animation
22

33
import de.ronny_h.aoc.extensions.asList
4+
import java.awt.Color
5+
import java.awt.Color.DARK_GRAY
46
import java.io.File
57

68
class AnimationRecorder {
@@ -10,7 +12,7 @@ class AnimationRecorder {
1012
frames.add(frame.asList())
1113
}
1214

13-
fun saveTo(fileName: String) = frames
14-
.map(List<String>::createImage)
15+
fun saveTo(fileName: String, colors: Map<Char, Color> = emptyMap(), background: Color = DARK_GRAY) = frames
16+
.map { it.createImage(colors, background) }
1517
.writeToGifFile(File(fileName))
1618
}

src/main/kotlin/de/ronny_h/aoc/extensions/animation/GifSequenceWriter.kt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package de.ronny_h.aoc.extensions.animation
22

3+
import java.awt.Color
4+
import java.awt.Color.LIGHT_GRAY
35
import java.awt.Font
46
import java.awt.Font.MONOSPACED
57
import java.awt.Font.PLAIN
@@ -16,22 +18,36 @@ import javax.imageio.metadata.IIOMetadataNode
1618
import javax.imageio.stream.FileImageOutputStream
1719
import javax.imageio.stream.ImageOutputStream
1820

21+
val green = Color(0, 153, 0)
22+
val lightGreen = Color(0, 186, 13)
23+
val purpleBlue = Color(15, 15, 35)
24+
val lightGrey = Color(204, 204, 204)
25+
val gray = Color(70, 70, 70)
26+
val darkGrey = Color(16, 16, 26)
1927

20-
private const val fontSize = 20
28+
private const val scale = 1
29+
private const val fontSize = scale * 20
2130
private const val drawStartX = 3
22-
private const val rowHeight = fontSize + 1
31+
private const val rowHeight = fontSize + scale
2332
private const val colWidth = 3 / 5.0 * fontSize
33+
private const val timeBetweenFramesMS = 250
2434
private val font = Font(MONOSPACED, PLAIN, fontSize)
2535

26-
fun List<String>.createImage(): BufferedImage {
36+
fun List<String>.createImage(colors: Map<Char, Color>, background: Color): BufferedImage {
37+
val gifColors = colors.withDefault { LIGHT_GRAY }
2738
val width = 2 * drawStartX + (this.first().length * colWidth).toInt()
28-
val height = size * rowHeight - 13
39+
val height = size * rowHeight - scale * 13
2940
val bufferedImage = BufferedImage(width, height, TYPE_INT_RGB)
3041
val graphics2D = bufferedImage.graphics as Graphics2D
3142
graphics2D.font = font
3243
graphics2D.setRenderingHint(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON)
44+
graphics2D.background = background
45+
graphics2D.clearRect(0, 0, width, height)
3346
forEachIndexed { rowNo, row ->
34-
graphics2D.drawString(row, drawStartX, rowNo * rowHeight)
47+
row.forEachIndexed { colNo, char ->
48+
graphics2D.color = gifColors.getValue(char)
49+
graphics2D.drawString("$char", (drawStartX + colNo * colWidth).toInt(), rowNo * rowHeight)
50+
}
3551
}
3652
return bufferedImage
3753
}
@@ -113,10 +129,13 @@ class GifSequenceWriter(
113129

114130
fun List<BufferedImage>.writeToGifFile(file: File) {
115131
FileImageOutputStream(file).use { out ->
116-
GifSequenceWriter(out, first().type, 200, true).use { gifWriter ->
132+
GifSequenceWriter(out, first().type, timeBetweenFramesMS, true).use { gifWriter ->
117133
forEach { image ->
118134
gifWriter.write(image)
119135
}
136+
repeat(3) {
137+
gifWriter.write(last())
138+
}
120139
}
121140
}
122141
}

src/main/kotlin/de/ronny_h/aoc/year2025/day07/Laboratories.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
package de.ronny_h.aoc.year2025.day07
22

33
import de.ronny_h.aoc.AdventOfCode
4+
import de.ronny_h.aoc.extensions.animation.gray
5+
import de.ronny_h.aoc.extensions.animation.lightGreen
6+
import de.ronny_h.aoc.extensions.animation.purpleBlue
47
import de.ronny_h.aoc.extensions.grids.Coordinates
58
import de.ronny_h.aoc.extensions.grids.Direction.*
69
import de.ronny_h.aoc.extensions.grids.SimpleCharGrid
10+
import java.awt.Color.white
711

812
fun main() = Laboratories().run(1600, 8632253783011)
913

1014
class Laboratories : AdventOfCode<Long>(2025, 7) {
11-
override fun part1(input: List<String>): Long = TachyonManifoldDiagram(input).followTheBeam().splitterCount
15+
override fun part1(input: List<String>): Long {
16+
val diagram = TachyonManifoldDiagram(input)
17+
// diagram.recorder = AnimationRecorder()
18+
val splitterCount = diagram.followTheBeam().splitterCount
19+
diagram.recorder?.saveTo(
20+
"2025-07_laboratories-animation.gif",
21+
mapOf(
22+
emptySpace to gray,
23+
splitter to lightGreen,
24+
beam to white,
25+
),
26+
purpleBlue,
27+
)
28+
return splitterCount
29+
}
1230

1331
override fun part2(input: List<String>): Long = TachyonManifoldDiagram(input).followTheBeam().numberOfTimeLines
1432
}

src/test/kotlin/de/ronny_h/aoc/extensions/animation/GifSequenceWriterTest.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package de.ronny_h.aoc.extensions.animation
33
import io.kotest.core.spec.style.FunSpec
44
import io.kotest.engine.spec.tempfile
55
import io.kotest.matchers.shouldBe
6+
import java.awt.Color.BLACK
67
import javax.imageio.ImageIO
78

89

@@ -13,8 +14,9 @@ class GifSequenceWriterTest : FunSpec({
1314
test("a GIF can be rendered from a list of Strings and be written to a file") {
1415
val frames = List(3) { i ->
1516
val text = buildList { repeat(5) { add("$i".repeat(5)) } }
16-
text.createImage()
17+
text.createImage(emptyMap(), BLACK)
1718
}
19+
// frames.writeToGifFile(File("reference.gif"))
1820
frames.writeToGifFile(file)
1921

2022
val newImage = ImageIO.read(file)

src/test/resources/reference.gif

-62.4 KB
Loading

0 commit comments

Comments
 (0)