<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Knowledge Base (Posts about images)</title><link>https://bgstack15.ddns.net/blog/</link><description></description><atom:link href="https://bgstack15.ddns.net/blog/categories/images.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2024 &lt;a href="mailto:bgstack15@gmail.com"&gt;bgstack15&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-SA"
style="border-width:0; margin-bottom:12px;"
src="https://bgstack15.ddns.net/.images/l_by-sa_4.0_88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Fri, 11 Oct 2024 13:00:36 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Crop screenshots to same window area</title><link>https://bgstack15.ddns.net/blog/posts/2024/10/11/crop-screenshots-to-same-window-area/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I had problems getting exact screenshots of some work, and was merely able to get full desktop screenshots. So I needed to crop to just the relevant portion. In my case, I wanted an 800x600 picture, from my second monitor (first being the left monitor, and second being the right monitor), starting at 1920+560 pixels by 240 pixels.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;for word in *png ; do convert "&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;" -crop 800x600+2480+240 foo/&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt; ; done
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Really small, and dumb, but I'll need this again someday.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/askubuntu.com/questions/631689/cropping-images-using-command-line-tools-only"&gt;Cropping Images using Command Line Tools Only - Ask Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>convert</category><category>images</category><guid>https://bgstack15.ddns.net/blog/posts/2024/10/11/crop-screenshots-to-same-window-area/</guid><pubDate>Fri, 11 Oct 2024 12:46:00 GMT</pubDate></item><item><title>Make optionMenu with images in python tkinter</title><link>https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;Here is another fantastic trick in &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/docs.python.org/3/library/tkinter.html"&gt;tkinter&lt;/a&gt;: get images on an optionmenu (drop down, or combobox).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/files/2024/listings/demo-optionmenu-with-images.py.html"&gt;files/2024/listings/demo-optionmenu-with-images.py&lt;/a&gt;  &lt;a href="https://bgstack15.ddns.net/blog/files/2024/listings/demo-optionmenu-with-images.py"&gt;(Source)&lt;/a&gt;&lt;/p&gt;&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Startdate: 2024-04-08-2 13:44&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Purpose: demo of the cool features of tkstackrpms&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Reference:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    [python - Can I possibly put an image/label into an option box in Tkinter? - Stack Overflow](https://stackoverflow.com/questions/67334913/can-i-possibly-put-an-image-label-into-an-option-box-in-tkinter/67337760#67337760)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# demo 1: optionmenu with images and text&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tkinter&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;tk&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tkstackrpms&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;stk&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Demo of tkstackrpms features"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;imgicon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_scaled_icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"battery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"apps"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"wm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"iconphoto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;imgicon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Yellow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Purple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# prepare set of images that corresponse to the options&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-20"&gt;&lt;code data-line-number="20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img_colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-21"&gt;&lt;code data-line-number="21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-22"&gt;&lt;code data-line-number="22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;t_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PhotoImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-23"&gt;&lt;code data-line-number="23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;t_image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-24"&gt;&lt;code data-line-number="24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img_colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-25"&gt;&lt;code data-line-number="25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-26"&gt;&lt;code data-line-number="26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OptionMenu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_choice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-27"&gt;&lt;code data-line-number="27"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# indicatoron=False turns off the weird second-button item within the button.&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-28"&gt;&lt;code data-line-number="28"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# minimize the padding so the box is not huge&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-29"&gt;&lt;code data-line-number="29"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# takefocus allows navigation to this widget with Tab&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-30"&gt;&lt;code data-line-number="30"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# compound means when an image is present, put it to the left of the text.&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-31"&gt;&lt;code data-line-number="31"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indicatoron&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;padx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pady&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;takefocus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;compound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-32"&gt;&lt;code data-line-number="32"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_choice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-33"&gt;&lt;code data-line-number="33"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-34"&gt;&lt;code data-line-number="34"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;ow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nametowidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;menuname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-35"&gt;&lt;code data-line-number="35"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-36"&gt;&lt;code data-line-number="36"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-37"&gt;&lt;code data-line-number="37"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;ow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entryconfigure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img_colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;compound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-38"&gt;&lt;code data-line-number="38"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-39"&gt;&lt;code data-line-number="39"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_choice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_selected_optmenu_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-40"&gt;&lt;code data-line-number="40"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_selected_optmenu_entry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-41"&gt;&lt;code data-line-number="41"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-42"&gt;&lt;code data-line-number="42"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_selected_optmenu_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-43"&gt;&lt;code data-line-number="43"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;this_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-44"&gt;&lt;code data-line-number="44"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-45"&gt;&lt;code data-line-number="45"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-46"&gt;&lt;code data-line-number="46"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_choice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-47"&gt;&lt;code data-line-number="47"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt_menu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img_colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-48"&gt;&lt;code data-line-number="48"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-49"&gt;&lt;code data-line-number="49"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-50"&gt;&lt;code data-line-number="50"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-51"&gt;&lt;code data-line-number="51"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# main&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-52"&gt;&lt;code data-line-number="52"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-53"&gt;&lt;code data-line-number="53"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;app_tk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/#-54"&gt;&lt;code data-line-number="54"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;app_tk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mainloop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;So you have an optionMenu widget, where each option has an image associated with it. We're using very basic samples here; any real-world use of this trick would have a more complex list of images and options.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/2024/scrot-optionmenu-with-images-2.png"&gt;&lt;img alt="" src="https://bgstack15.ddns.net/blog/2024/scrot-optionmenu-with-images-2.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can even set the front label of it to have an image, so you can view the currently selected image without having to open the drop-down.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/2024/scrot-optionmenu-with-images-1.png"&gt;&lt;img alt="" src="https://bgstack15.ddns.net/blog/2024/scrot-optionmenu-with-images-1.png"&gt;&lt;/a&gt;&lt;/p&gt;</description><category>images</category><category>python</category><category>tkinter</category><guid>https://bgstack15.ddns.net/blog/posts/2024/04/27/make-optionmenu-with-images-in-python-tkinter/</guid><pubDate>Sat, 27 Apr 2024 12:45:24 GMT</pubDate></item><item><title>Poor man's html image gallery</title><link>https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;For a personal website for which I hand-roll the html code, I wrote a small shell image link+thumbnail generator script. I shouldn't be proud, but I am.&lt;/p&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Startdate: 2020-11-27 15:09&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/public/www/images
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;DIRPREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"images"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;THUMBNAIL_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;USE_THUMBNAILS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USE_THUMBNAILS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USE_THUMBNAILS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   mkdir -p &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.thumbnails"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;tfs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; find &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; -mindepth &lt;span class="m"&gt;1&lt;/span&gt; -maxdepth &lt;span class="m"&gt;1&lt;/span&gt; ! -type d ! -name &lt;span class="s1"&gt;'.*.swp'&lt;/span&gt; ! -name &lt;span class="s1"&gt;'*.sh'&lt;/span&gt; ! -name &lt;span class="s1"&gt;'*.html'&lt;/span&gt; -printf &lt;span class="s1"&gt;'%T@ %f\n'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sort -n &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;'{print $NF}'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; word &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tfs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;tf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIRPREFIX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;tf_thumb_web&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tf&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USE_THUMBNAILS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USE_THUMBNAILS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;tf_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-20"&gt;&lt;code data-line-number="20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;tf_thumb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.thumbnails/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;&lt;span class="p"&gt;%%.???&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-21"&gt;&lt;code data-line-number="21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;tf_thumb_web&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DIRPREFIX&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.thumbnails/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;word&lt;/span&gt;&lt;span class="p"&gt;%%.???&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-22"&gt;&lt;code data-line-number="22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      convert -filter Lanczos -resize &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THUMBNAIL_SIZE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;THUMBNAIL_SIZE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tf_in&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tf_thumb&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-23"&gt;&lt;code data-line-number="23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-24"&gt;&lt;code data-line-number="24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;a href=\"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tf&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\"&amp;gt;&amp;lt;img src=\"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tf_thumb_web&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\" class=\"thumb\"&amp;gt;&amp;lt;/a&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/#-25"&gt;&lt;code data-line-number="25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;find | sort | awk&lt;/code&gt; line is my preferred method for sorting by timestamp. It is not safe for files with spaces in the name, but who does that anyways?! (Ahem. [Well, not here obviously!]). Of course there are ways to make that happen, but it would be even less clean looking, and avoiding spaces is easy enough.&lt;/p&gt;
&lt;p&gt;So like all good unix scripts, this just prints to stdout. I then copy-paste the contents and update my html file.&lt;/p&gt;
&lt;p&gt;I haven't done extensive testing with non-square images. I'm pretty sure most images on my gallery are non-square, but everything seems to line up adequately.&lt;/p&gt;
&lt;p&gt;And what gives away the fact that I'm a vim user?&lt;/p&gt;
&lt;p&gt;And of course, some applicable css:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="na"&gt;.thumb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;max-width:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;300&lt;/span&gt;&lt;span class="nf"&gt;px&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;max-height:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;300&lt;/span&gt;&lt;span class="nf"&gt;px&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>html</category><category>images</category><category>shell</category><guid>https://bgstack15.ddns.net/blog/posts/2023/07/06/poor-mans-html-image-gallery/</guid><pubDate>Thu, 06 Jul 2023 13:00:10 GMT</pubDate></item><item><title>Use Images from Google Photos album as screensaver on Linux</title><link>https://bgstack15.ddns.net/blog/posts/2020/05/21/use-images-from-google-photos-album-as-screensaver-on-linux/</link><dc:creator>bgstack15</dc:creator><description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I wanted to set up a (shared) Google Photos album as my screensaver on Devuan
GNU/Linux. I accomplished this with the venerable
&lt;a href="https://www.jwz.org/xscreensaver/"&gt;xscreensaver&lt;/a&gt; and a useful tool named
&lt;a href="https://rclone.org/"&gt;rclone&lt;/a&gt; which I was already using.&lt;/p&gt;
&lt;h2&gt;Downloading images from Google Photos&lt;/h2&gt;
&lt;p&gt;On my CentOS 7 server, I already am using rclone. Starting with version
&lt;a href="https://rclone.org/changelog/#v1-49-0-2019-08-26"&gt;1.49&lt;/a&gt;, rclone supports
Google Photos. EPEL provides rclone but only version
&lt;a href="http://mirror.shastacoe.net/epel/7/x86_64/Packages/r/rclone-1.47.0-1.el7.x86_64.rpm"&gt;1.47&lt;/a&gt;.
So download the upstream rpm release: &lt;a href="https://rclone.org/downloads/"&gt;Downloads
page&lt;/a&gt; or &lt;a href="https://downloads.rclone.org/v1.51.0/rclone-v1.51.0-linux-amd64.rpm"&gt;direct
link&lt;/a&gt;.
The utility comes with a cli-based configurator. Use &lt;strong&gt;rclone config&lt;/strong&gt; and add
a remote. I failed to save the output of when I configured it, but it's as
easy following the prompts to add a Google Photos remote. Choose the headless
option, and it will show you a link to open in a browser where you can
authenticate to Google Photos and then approve this application to use a token
tied to your account. The browser will show you a code you paste back into the
configurator. In the end, what matters is that the
~/.config/rclone/rclone.conf includes a section like so:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[photos]&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;google photos&lt;/span&gt;
&lt;span class="na"&gt;read_only&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;{"access_token":"za29.a0AfH6SMC9bVDgJTPZTPfvMd5MyplOehAgldvibfrlmMwOBFUSCATEDuDd6tMuWm13YOryXXpUWP4EkHO-oNoa92I6WN7rzrS4y6hquw3zPFXOayEZv-3uv9_NfYNUyctoBq_OUQ9lrqoH3U7J40crJW2NZ","token_type":"Bearer","refresh_token":"1//013Vdw5CGVJ3zCgZIARAAGAFSNwF-L9IricqZmAio2CqpFJ8nM0OuXmsorNlVHRmX5w_KeIgvwvrxsJl5hJT30jT9ET-9mh612-0","expiry":"2020-05-19T10:49:30.709779985-04:00"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then my sync script is this:&lt;/p&gt;
&lt;table class="codehilitetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c1"&gt;# File: /etc/installed/sync-photos.sh&lt;/span&gt;
&lt;span class="c1"&gt;# Location: storage1:/etc/installed&lt;/span&gt;
&lt;span class="c1"&gt;# Author: bgstack15@gmail.com&lt;/span&gt;
&lt;span class="c1"&gt;# Startdate: 2020-05-19&lt;/span&gt;
&lt;span class="c1"&gt;# Title: Script that Pulls Down Album from Google Drive&lt;/span&gt;
&lt;span class="c1"&gt;# Purpose: Pull photos down for a screensaver for the living room HTPC&lt;/span&gt;
&lt;span class="c1"&gt;# History:&lt;/span&gt;
&lt;span class="c1"&gt;# Usage:&lt;/span&gt;
&lt;span class="c1"&gt;#    in a cron entry:&lt;/span&gt;
&lt;span class="c1"&gt;# References:&lt;/span&gt;
&lt;span class="c1"&gt;#    man rclone(1)&lt;/span&gt;
&lt;span class="c1"&gt;#    https://rclone.org/googlephotos/&lt;/span&gt;
&lt;span class="c1"&gt;# Dependencies:&lt;/span&gt;
&lt;span class="c1"&gt;#    ~/.config/rclone/rclone.conf with a section named "photos"&lt;/span&gt;
&lt;span class="c1"&gt;# Documentation:&lt;/span&gt;
&lt;span class="c1"&gt;#    --dry-run is useful. Sync command runs from left side to right side only.&lt;/span&gt;
&lt;span class="nv"&gt;REMOTE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"photos"&lt;/span&gt;
&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"shared-album/Album Name"&lt;/span&gt;
&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/public/Images/google-drive/photos
&lt;span class="nv"&gt;LOGFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/public/Support/Systems/storage1/var/log/sync-photos/rclone.photos.&lt;span class="k"&gt;$(&lt;/span&gt; date &lt;span class="s2"&gt;"+%F"&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;.log
mkdir -p &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; dirname &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LOGFILE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;PLECHO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; which plecho &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; which cat &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;time&lt;/span&gt; rclone -v --gphotos-read-only sync &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PLECHO&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tee -a &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LOGFILE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;The script itself ran great the first time, and downloaded all images (and
videos) from the album. Upon second run though, the task seems stuck. Ah,
well, I'll solve that over time. For a cron job to run this daily, add file
/etc/cron.d/90_google-photos-sync.cron&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# &lt;span class="nv"&gt;File&lt;/span&gt;: &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;cron&lt;/span&gt;.&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="nv"&gt;_google&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;photos&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;sync&lt;/span&gt;.&lt;span class="nv"&gt;cron&lt;/span&gt;
# &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;google&lt;/span&gt; &lt;span class="nv"&gt;photos&lt;/span&gt; &lt;span class="nv"&gt;album&lt;/span&gt; &lt;span class="nv"&gt;shared&lt;/span&gt; &lt;span class="nv"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;another&lt;/span&gt; &lt;span class="nv"&gt;google&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;. &lt;span class="nv"&gt;Save&lt;/span&gt; &lt;span class="nv"&gt;down&lt;/span&gt; &lt;span class="nv"&gt;all&lt;/span&gt; &lt;span class="nv"&gt;images&lt;/span&gt; &lt;span class="nv"&gt;so&lt;/span&gt; &lt;span class="nv"&gt;that&lt;/span&gt; &lt;span class="nv"&gt;HTPC&lt;/span&gt; &lt;span class="nv"&gt;can&lt;/span&gt; &lt;span class="nv"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;them&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;screensaver&lt;/span&gt;.
&lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="mi"&gt;04&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;  &lt;span class="nv"&gt;root&lt;/span&gt;  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;installed&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;photos&lt;/span&gt;.&lt;span class="nv"&gt;sh&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="nv"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;null&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And as with all good cron jobs, suppress the standard output and standard
error and use the job itself to store logs.&lt;/p&gt;
&lt;h2&gt;Using images in xscreensaver&lt;/h2&gt;
&lt;p&gt;On my Devuan GNU+Linux home theater PC, I use xscreensaver. To take advantage
of a simple slideshow feature, make sure to have package &lt;strong&gt;xscreensaver-gl&lt;/strong&gt;
installed. &lt;img alt="Xscreensaver settings on main tab showing GLSlideshow
selected" src="https://bgstack15.ddns.net/blog/2020/05/choose-glslideshow.png"&gt; Select GLSlideshow and option "Only one screen saver." The
Tesselimage screensaver was very entertaining when used on personal photos but
not all end users agreed with me. &lt;img alt="Xscreensaver GLSlideshow settings page
showing sliders with useful
settings" src="https://bgstack15.ddns.net/blog/2020/05/glslideshow-settings.png"&gt; Adjust sliders as necessary. I found that on the default
settings, the slideshow would fade out and back in, on the same photo, about
three times, before finally moving on to the next image. So these sliders'
positions were successful in always showing a new image on each fadeout, which
was also slowed down. On the advanced settings tab of GLSlideshow, the sliders
were instantiated as:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;glslideshow -root -delay 30081 -duration 10 -pan 10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img alt="Xcreensaver settings on the advanced tab showing what directory to pull
random images from" src="https://bgstack15.ddns.net/blog/2020/05/set-directory.png"&gt; And of course, choose the destination directory (nfs mounted in
my case) on the advanced settings. For the really hardcore users, some of the
relevant .xscreensaver values I could find include:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;chooseRandomImages&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;imageDirectory&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="sr"&gt;/mnt/public/Images/google-drive/&lt;/span&gt;&lt;span class="n"&gt;photos&lt;/span&gt;
&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;one&lt;/span&gt;
&lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="mi"&gt;143&lt;/span&gt;
&lt;span class="n"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                              &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;GL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;             &lt;span class="n"&gt;glslideshow&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="mi"&gt;30081&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;      &lt;span class="o"&gt;\&lt;/span&gt;
              &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pan&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;                &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It is worth noting that the glslideshow entry is 143 lines below the
&lt;strong&gt;programs:&lt;/strong&gt; line.&lt;/p&gt;
&lt;h2&gt;Extra thoughts&lt;/h2&gt;
&lt;p&gt;Even though a Google Photos album that is shared might be accessed
anonymously, the rclone utility requires an account. Linux – keep it simple.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://rclone.org/docs/"&gt;https://rclone.org/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rclone.org/googlephotos/"&gt;https://rclone.org/googlephotos/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jwz.org/xscreensaver/faq.html#slideshow"&gt;https://www.jwz.org/xscreensaver/faq.html#slideshow&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>devuan</category><category>epel</category><category>google</category><category>images</category><category>photo</category><category>rclone</category><category>screensaver</category><category>upstream</category><category>xscreensaver</category><guid>https://bgstack15.ddns.net/blog/posts/2020/05/21/use-images-from-google-photos-album-as-screensaver-on-linux/</guid><pubDate>Thu, 21 May 2020 12:41:12 GMT</pubDate></item><item><title>Upload user photo to AD</title><link>https://bgstack15.ddns.net/blog/posts/2019/12/14/upload-user-photo-to-ad/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;I wrote a series of Powershell functions and scripts to perform a set of
tasks. The new hires get their photo taken, and those photos need to be
applied to the various systems that store user photos. More will be added over
time, but now, I have functions that upload to Active Directory, Azure AD,
Exchange, and a SQL Server database. As you might be aware, most of those
systems only accept images up to a certain size. So I ripped off a function
that resizes an image. I wrote a wrapper to shrink an image a little at a time
until its size is smaller than the indicated value. Check out the whole
repository at &lt;a href="https://gitlab.com/bgstack15/former-%0Agists/tree/master/userphotos"&gt;https://gitlab.com/bgstack15/former-
gists/tree/master/userphotos&lt;/a&gt;. The basic task is to upload an image to Active
Directory. A workflow in a Sharepoint instance handles the image uploads from
users and the approval by a security officer, but then a script downloads all
the photos &lt;a href="https://gitlab.com/bgstack15/former-gists/blob/master/userphotos/Apply-Photos-From-SharePoint.ps1"&gt;Apply-Photos-From-
SharePoint.ps1&lt;/a&gt;. The images are
named according to the email address of the user already, so they're just
downloaded wholesale. Once the files are on the local filesystem, that script
loops through them and uploads them.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ForEach ($file in Get-ChildItem $Outdir | Where-Object { -Not ( $_.Name -Match ".*(_[0-9]{2}|[0-9]{6})\.[^.]{1,6}" ) } )
{
    $null = Process-User-Photo -File $file
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the &lt;a href="https://gitlab.com/bgstack15/former-gists/blob/master/userphotos/userphotolib.ps1"&gt;library&lt;/a&gt;, the function Process-User-Photo extracts the user in question based on the name and calls the wrapper
function for uploading to all services.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        &lt;span class="nv"&gt;$Result&lt;/span&gt; = Set-Photo-All -User &lt;span class="nv"&gt;$samaccountname&lt;/span&gt; -Filename &lt;span class="nv"&gt;$file.Fullname&lt;/span&gt;
        if (&lt;span class="nv"&gt;$Result&lt;/span&gt; -eq 0)
        {
            Log "Success: &lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"
            Move-With-Rename -Path &lt;span class="nv"&gt;$file.Fullname&lt;/span&gt; -Destination "&lt;span class="nv"&gt;$MoveToOutdir&lt;/span&gt;\"
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And Set-Photo-All is pretty simple. It will return an integer which represents
the number of failures of the individual set-photo functions.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;All&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;User&lt;/span&gt; $&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Filename&lt;/span&gt; &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
&lt;span class="nv"&gt;Function&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;All&lt;/span&gt; {
    &lt;span class="nv"&gt;Param&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;
        [&lt;span class="nv"&gt;Parameter&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;$&lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;] $&lt;span class="nv"&gt;User&lt;/span&gt;,
        [&lt;span class="nv"&gt;Parameter&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;$&lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;] &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
    &lt;span class="ss"&gt;)&lt;/span&gt;
    $&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    $&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;AD&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;User&lt;/span&gt; $&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Filename&lt;/span&gt; &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
    # &lt;span class="nv"&gt;AzureAD&lt;/span&gt; &lt;span class="nv"&gt;synchronizes&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;prem&lt;/span&gt; &lt;span class="nv"&gt;AD&lt;/span&gt; &lt;span class="nv"&gt;approximately&lt;/span&gt; &lt;span class="nv"&gt;every&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="nv"&gt;minutes&lt;/span&gt;.
    #$&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;AzureAD&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;User&lt;/span&gt; $&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Filename&lt;/span&gt; &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
    $&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Outlook&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;User&lt;/span&gt; $&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Filename&lt;/span&gt; &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
    $&lt;span class="nb"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;SQLServer&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;User&lt;/span&gt; $&lt;span class="nv"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;Filename&lt;/span&gt; &lt;span class="mh"&gt;$F&lt;/span&gt;&lt;span class="nv"&gt;ilename&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; $&lt;span class="nb"&gt;Result&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Uploading to AD is actually really easy.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# Set-Photo-AD -User &lt;span class="nv"&gt;$User&lt;/span&gt; -Filename &lt;span class="nv"&gt;$Filename&lt;/span&gt;
Function Set-Photo-AD {
    Param(
        [Parameter(Mandatory=&lt;span class="nv"&gt;$true&lt;/span&gt;)] &lt;span class="nv"&gt;$User&lt;/span&gt;,
        [Parameter(Mandatory=&lt;span class="nv"&gt;$true&lt;/span&gt;)] &lt;span class="nv"&gt;$Filename&lt;/span&gt;
    )
    &lt;span class="nv"&gt;$Result&lt;/span&gt; = -1
    &lt;span class="nv"&gt;$newfile&lt;/span&gt; = Get-Photo-Below-Size -Filename &lt;span class="nv"&gt;$filename&lt;/span&gt; -MaxSize 100000
    &lt;span class="nv"&gt;$photo&lt;/span&gt; = [byte[]](Get-Content &lt;span class="nv"&gt;$newfile&lt;/span&gt; -Encoding byte)
    Try
    {
        Get-ADUser &lt;span class="nv"&gt;$User&lt;/span&gt; | Set-ADUser -Replace @{thumbnailPhoto=&lt;span class="nv"&gt;$photo&lt;/span&gt;}
        If (&lt;span class="nv"&gt;$newfile&lt;/span&gt; -ne &lt;span class="nv"&gt;$Filename&lt;/span&gt;) { Remove-Item -Path &lt;span class="nv"&gt;$newfile&lt;/span&gt; }
        Log "Set AD photo for &lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt; to &lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;newfile&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"
        &lt;span class="nv"&gt;$Result&lt;/span&gt; = 0
    }
    Catch
    {
        Write-Error &lt;span class="nv"&gt;$_&lt;/span&gt;
    }
    Remove-Variable newfile
    return &lt;span class="nv"&gt;$Result&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course there's a getter function as well, for each service.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Get-Photo-AD -User $user -Filename $filename&lt;/span&gt;
&lt;span class="n"&gt;Function&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AD&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Param&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=$&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# save photo down from AD to inspect it&lt;/span&gt;
    &lt;span class="c1"&gt;# https://devblogs.microsoft.com/scripting/weekend-scripter-exporting-and-importing-photos-in-active-directory/&lt;/span&gt;
    &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;aduser&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="n"&gt;thumbnailphoto&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;WriteAllBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;thumbnailphoto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So the whole library is modular. You can dot-source the whole thing and run
just individual statements ad-hoc, or use the library for a wholistic solution
which is why I needed it.&lt;/p&gt;</description><category>ad</category><category>images</category><category>photo</category><category>powershell</category><guid>https://bgstack15.ddns.net/blog/posts/2019/12/14/upload-user-photo-to-ad/</guid><pubDate>Sat, 14 Dec 2019 14:02:01 GMT</pubDate></item><item><title>Remove docker "none" images</title><link>https://bgstack15.ddns.net/blog/posts/2018/12/15/remove-docker-images/</link><dc:creator>bgstack15</dc:creator><description>&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;docker rmi $( docker images -f "dangling=true" -q )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Shamelessly stolen from: &lt;a href="https://forums.docker.com/t/how-to-remove-none-%0Aimages-after-building/7050"&gt;https://forums.docker.com/t/how-to-remove-none-
images-after-building/7050&lt;/a&gt;&lt;/p&gt;</description><category>docker</category><category>images</category><category>oneliner</category><guid>https://bgstack15.ddns.net/blog/posts/2018/12/15/remove-docker-images/</guid><pubDate>Sat, 15 Dec 2018 13:57:29 GMT</pubDate></item><item><title>Irfanview on Linux</title><link>https://bgstack15.ddns.net/blog/posts/2017/01/19/irfanview-on-linux/</link><dc:creator>bgstack15</dc:creator><description>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.irfanview.info/"&gt;Irfanview&lt;/a&gt; is a fantastic image viewer and batch
utility for the Windows platform. But did you know that you can run Irfanview
on GNU/Linux, and this post will show you how to do that. There is a caveat,
though: Irfanview is not open source. It's freeware. That might turn off some
people, but I still choose to use it. It's unparalleled in the GNU world.
There are several ways to get Irfanview on a GNU/Linux system, and they all
use &lt;a href="https://www.winehq.org/"&gt;Wine&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Installing Irfanview with Winetricks&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://wiki.winehq.org/Winetricks"&gt;Winetricks&lt;/a&gt; is a fancy helper script that
makes repetitive tasks in wine easier. It has an option built-in for
installing Irfanview. It's a piece of cake. Make sure you have wine with your
package manager. &lt;code&gt;dnf install wine&lt;/code&gt; Then download winetricks from the link
above and run the install irfanview command. &lt;code&gt;./winetricks -q irfanview&lt;/code&gt; The
-q is for unattended install. If you want to adjust the settings, run it
without the -q. Observe that winetricks mentions installing mfc42.dll for you.
That is needed for the installer only.&lt;/p&gt;
&lt;h3&gt;Installing Irfanview with a custom-rolled package&lt;/h3&gt;
&lt;p&gt;You can choose to install Irfanview by assembling a package from the rpm spec
and debian control scripts I've assembled at
&lt;a href="https://gitlab.com/bgstack15/irfan"&gt;https://gitlab.com/bgstack15/irfan&lt;/a&gt;. &lt;code&gt;git pull
https://gitlab.com/bgstack15/irfan.git&lt;/code&gt; What is in the git repository is the
source for just the packaging. The actual software source code is downloaded
from official web sources upon building the rpm, and upon the installation of
the dpkg file. As I said above, the software itself is freeware, so the source
is not available for distribution. A wrapper for rpmbuild and dpkg-deb is
provided, as usr/share/irfan/build/pack. Run ./pack rpm or ./pack deb and the
system will build you the type of package you specified, provided you have the
&lt;strong&gt;rpm-build&lt;/strong&gt; or &lt;strong&gt;dpkg-dev&lt;/strong&gt; package. For the rpm, you might need to generate
some directories: &lt;code&gt;mkdir -p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS
~/rpmbuild/RPMS ~/rpmbuild/BUILD ~/rpmbuild/BUILDROOT&lt;/code&gt; In fact, you should run
all this, which will download from gitlab for you the package source. &lt;code&gt;mkdir
-p ~/rpmbuild/SOURCES ~/rpmbuild/SPECS ~/rpmbuild/RPMS ~/rpmbuild/BUILD
~/rpmbuild/BUILDROOT cd ~/rpmbuild/SOURCES mkdir irfan-4.44-1; cd irfan-4.44-1
git init git pull https://gitlab.com/bgstack15/irfan.git cd irfan-4.44-1
usr/share/irfan/inc/pack rpm&lt;/code&gt; The generated rpm will appear in
~/rpmbuild/RPMS/noarch. Then you can run dnf install
./irfan-4.44-1.noarch.rpm.&lt;/p&gt;
&lt;h4&gt;The benefits of rolling your own package&lt;/h4&gt;
&lt;p&gt;The package provided on gitlab includes a menu shortcut to Irfanview, as well
as mimetype defaults for jpg and png. You will be able to see Irfanview in the
list of applications when you select a file in the file manager, right click,
and select "Open with..." The winetricks option does not include that.&lt;/p&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Main irfanview site &lt;a href="http://www.irfanview.info/"&gt;http://www.irfanview.info/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.boekhoff.info/?pid=linux&amp;amp;tip=install-irfan-view-on-linux"&gt;http://www.boekhoff.info/?pid=linux&amp;amp;tip=install-irfan-view-on-linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Main wine site &lt;a href="https://www.winehq.org/"&gt;https://www.winehq.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Latest winetricks script &lt;a href="https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks"&gt;https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Irfan rpm and deb package source &lt;a href="https://gitlab.com/bgstack15/irfan"&gt;https://gitlab.com/bgstack15/irfan&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>images</category><category>irfanview</category><category>linux</category><category>wine</category><guid>https://bgstack15.ddns.net/blog/posts/2017/01/19/irfanview-on-linux/</guid><pubDate>Thu, 19 Jan 2017 20:00:34 GMT</pubDate></item></channel></rss>