Skip to content

Instantly share code, notes, and snippets.

@retheviper
Created September 1, 2024 12:34
Show Gist options
  • Save retheviper/e9e0f0d5c4041e8bde14356ec54e8056 to your computer and use it in GitHub Desktop.
Save retheviper/e9e0f0d5c4041e8bde14356ec54e8056 to your computer and use it in GitHub Desktop.
Create LGTM image (GIF) with Scrimage
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2024-09-01T12:31:50.482340Z",
"start_time": "2024-09-01T12:31:50.454739Z"
}
},
"source": [
"import com.sksamuel.scrimage.graphics.RichGraphics2D\n",
"import com.sksamuel.scrimage.nio.AnimatedGifReader\n",
"import com.sksamuel.scrimage.nio.StreamingGifWriter\n",
"import com.sksamuel.scrimage.nio.ImageSource\n",
"import java.awt.Color\n",
"import java.awt.Font\n",
"import java.awt.RenderingHints\n",
"import java.awt.geom.Rectangle2D\n",
"import java.awt.image.BufferedImage"
],
"outputs": [],
"execution_count": 15
},
{
"metadata": {},
"cell_type": "code",
"source": [
"// Read image\n",
"val imageFile = File(\"test-image.gif\")\n",
"val gif = AnimatedGifReader.read(ImageSource.of(imageFile))"
],
"outputs": [],
"execution_count": null
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-09-01T12:31:50.574634Z",
"start_time": "2024-09-01T12:28:09.454085Z"
}
},
"cell_type": "code",
"source": [
"// Prepare text\n",
"val text = \"LGTM\"\n",
"val fontSize = gif.frames.first().width / 3\n",
"val font = Font(\"Arial\", Font.BOLD, fontSize)"
],
"outputs": [],
"execution_count": 12
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-09-01T12:31:50.574770Z",
"start_time": "2024-09-01T12:28:47.262121Z"
}
},
"cell_type": "code",
"source": [
"// Render text on each frame\n",
"val framesWithText = gif.frames.map { image ->\n",
" val g2 = RichGraphics2D(image.awt().createGraphics())\n",
" g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)\n",
"\n",
" g2.font = font\n",
" val textBounds = g2.fontMetrics.getStringBounds(text, g2)\n",
" val x = (image.width - textBounds.width) / 2\n",
" val y = (image.height - textBounds.height) / 2 + g2.fontMetrics.ascent\n",
"\n",
" // Draw outline\n",
" val outlineOffset = 3\n",
" g2.color = Color.BLACK\n",
" for (dx in -outlineOffset..outlineOffset) {\n",
" for (dy in -outlineOffset..outlineOffset) {\n",
" if (dx != 0 || dy != 0) {\n",
" g2.drawString(text, (x + dx).toFloat(), (y + dy).toFloat())\n",
" }\n",
" }\n",
" }\n",
"\n",
" // Draw text\n",
" g2.color = Color.WHITE\n",
" g2.drawString(text, x.toFloat(), y.toFloat())\n",
" g2.dispose()\n",
" \n",
" image\n",
"}"
],
"outputs": [],
"execution_count": 13
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2024-09-01T12:31:50.574855Z",
"start_time": "2024-09-01T12:28:57.563913Z"
}
},
"cell_type": "code",
"source": [
"// Save image\n",
"val writer = StreamingGifWriter()\n",
"val newGif = writer.prepareStream(\"test-image-lgtm.gif\", BufferedImage.TYPE_INT_ARGB)\n",
"newGif.use {\n",
" framesWithText.forEachIndexed { index, image ->\n",
" newGif.writeFrame(image, gif.getDelay(index))\n",
" }\n",
"}"
],
"outputs": [],
"execution_count": 14
}
],
"metadata": {
"kernelspec": {
"display_name": "Kotlin",
"language": "kotlin",
"name": "kotlin"
},
"language_info": {
"name": "kotlin",
"version": "1.9.23",
"mimetype": "text/x-kotlin",
"file_extension": ".kt",
"pygments_lexer": "kotlin",
"codemirror_mode": "text/x-kotlin",
"nbconvert_exporter": ""
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment