{"id":249,"date":"2026-04-05T15:02:48","date_gmt":"2026-04-05T12:02:48","guid":{"rendered":"https:\/\/tel-zur.net\/blog\/?p=249"},"modified":"2026-04-05T19:32:08","modified_gmt":"2026-04-05T16:32:08","slug":"ai-generated-images-using-opensource-tools-and-on-local-resources","status":"publish","type":"post","link":"https:\/\/tel-zur.net\/blog\/2026\/04\/05\/ai-generated-images-using-opensource-tools-and-on-local-resources\/","title":{"rendered":"AI generated images using opensource tools and on local resources"},"content":{"rendered":"\n<p>In this blog post, I describe a method for generating AI images locally using open-source tools. This approach is both free and privacy-preserving. However, there are no free lunches; it comes with trade-offs, including slower performance and occasional quality limitations.<\/p>\n\n\n\n<p>The content of this post is as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Introduction (motivation + constraints) <\/li>\n\n\n\n<li>System Architecture <\/li>\n\n\n\n<li>Setup and integration: \n<ul class=\"wp-block-list\">\n<li>Ollama + LLM<\/li>\n\n\n\n<li>Open WebUI<\/li>\n\n\n\n<li>Automatic1111<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Experiments <\/li>\n\n\n\n<li>Limitations &amp; Lessons Learned <\/li>\n\n\n\n<li>Conclusions and recommendations<\/li>\n<\/ol>\n\n\n\n<p>Let&#8217;s begin&#8230;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Introduction<\/strong>. Image generation using AI is a hot topic; however, it usually involve a paid plan from one of the commercial providers. I wanted to investigate the possibilities to create images for free and locally using only open-source tools.<\/li>\n\n\n\n<li><strong>System architecture<\/strong>. My computer is running Ubuntu 24.04.4 LTS (Noble Numbat).  The computer has an Intel i9 processor with 32GB RAM and an Nvidia GeForce RTX4060 with 8GB VRAM. Therefore the combined GPU\/CPU memory constraints must be carefully considered. This is a constraint that should be taken into account when choosing an LLM. In that respect I recommend selecting an LLM according to <a href=\"https:\/\/www.llmfit.org\/\" data-type=\"link\" data-id=\"https:\/\/www.llmfit.org\/\">llmfit<\/a> ranking. LLMFIT provides a compatibility score of many LLMs to your specific platform, see Figure 1. <\/li>\n\n\n\n<li><strong>Setup and integration<\/strong>. As an AI hosting platform I use <a href=\"https:\/\/ollama.com\/\" data-type=\"link\" data-id=\"https:\/\/ollama.com\/\">Ollama<\/a> which can easily be installed using a one line command:<\/li>\n<\/ol>\n\n\n\n<p class=\"has-text-align-center\" style=\"font-size:14px\"><code>curl -fsSL https:\/\/ollama.com\/install.sh | sh<\/code><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"418\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/Screenshot-from-2026-04-05-11-10-40-1024x418.png\" alt=\"\" class=\"wp-image-285\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/Screenshot-from-2026-04-05-11-10-40-1024x418.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/Screenshot-from-2026-04-05-11-10-40-300x123.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/Screenshot-from-2026-04-05-11-10-40-768x314.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/Screenshot-from-2026-04-05-11-10-40.png 1427w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 1. LLMFIT<\/figcaption><\/figure>\n\n\n\n<p>After a few trial and error cycles I finally chose <a href=\"https:\/\/huggingface.co\/Qwen\/Qwen2.5-7B\" data-type=\"link\" data-id=\"https:\/\/huggingface.co\/Qwen\/Qwen2.5-7B\">qwen2.5:7b<\/a> (which occupies about 4.7GB of disk space). The installation and verification is done like this&#8221;<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"Bash\" data-theme=\"default\"><code class=\"language-bash\">$ sudo systemctl status ollama  # is ollama running ok? see Figure 2\n$ ollama pull qwen2.5:7b        # download and install the model\n$ ollama list | grep qwen2.5:7b # verify the model installation\nqwen2.5:7b          845dbda0ea48    4.7 GB    6 weeks ago    \n$ ps -ef | grep ollama\nollama  15871  1  0 09:14 ?    00:01:10 \/usr\/local\/bin\/ollama serve<\/code><\/pre>\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"383\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-7-1024x383.png\" alt=\"\" class=\"wp-image-258\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-7-1024x383.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-7-300x112.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-7-768x288.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-7.png 1490w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 2. The output of sudo systemctl status ollama.<\/figcaption><\/figure>\n\n\n\n<p>To provide a user-friendly interface, I used Open <a href=\"https:\/\/docs.openwebui.com\/\" data-type=\"link\" data-id=\"https:\/\/docs.openwebui.com\/\">WebUI<\/a>, which is started from the command line with:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"Bash\" data-theme=\"default\"><code class=\"language-bash\">$ open-webui serve<\/code><\/pre>\n\n\n<p>see Figure 3.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"624\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-3-1024x624.png\" alt=\"\" class=\"wp-image-253\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-3-1024x624.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-3-300x183.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-3-768x468.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-3.png 1486w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 3. Starting Open WebUI<\/figcaption><\/figure>\n\n\n\n<p>Then, point the browser to <a href=\"http:\/\/localhost:8080\">http:\/\/localhost:8080<\/a> to access the dashboard, Figure 4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-8-1024x584.png\" alt=\"\" class=\"wp-image-260\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-8-1024x584.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-8-300x171.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-8-768x438.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-8.png 1277w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 4. Open WebUI dashboard<\/figcaption><\/figure>\n\n\n\n<p>At this stage you can enjoy chatting with the model but it is still not ready for generating images. For that you need to install another, external, tool and create a link between the Open WebUI and the image generation tool. The tool I am referring to is called <a href=\"https:\/\/github.com\/AUTOMATIC1111\/stable-diffusion-webui\" data-type=\"link\" data-id=\"https:\/\/github.com\/AUTOMATIC1111\/stable-diffusion-webui\">Automatic1111<\/a> which is a web interface for Stable Diffusion, implemented using the Gradio library. Automatic1111 can also work as a stand-alone tool. In order to start Automatic1111 execute the script <em>webui.sh<\/em> under the installation folder which is obtained from their <a href=\"https:\/\/github.com\/AUTOMATIC1111\/stable-diffusion-webui\" data-type=\"link\" data-id=\"https:\/\/github.com\/AUTOMATIC1111\/stable-diffusion-webui\">GitHub<\/a> repository. However, in my case I had to modify the starting shell command by introducing a few flags so the invocation, in my case, is as follows:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"Bash\" data-theme=\"default\"><code class=\"language-bash\">LD_PRELOAD=\/usr\/lib\/x86_64-linux-gnu\/libtcmalloc_minimal.so.4 .\/webui.sh --lowvram --api --cors-allow-origins &quot;*&quot; --no-half --no-half-vae --skip-python-version-check<\/code><\/pre>\n\n\n<p>The <code>--lowvram<\/code> flag is essential for GPUs with limited memory (such as 8GB), while <code>--api<\/code> enables integration with external tools like Open WebUI. Upon starting Automatic1111 a new tab in the browser will be opened, see Figure 5.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"490\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-1024x490.png\" alt=\"\" class=\"wp-image-262\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-1024x490.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-300x143.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-768x367.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-1536x734.png 1536w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10-1568x750.png 1568w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-10.png 1847w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 5. Automatic1111 dashboard<\/figcaption><\/figure>\n\n\n\n<p>As can be seen in Figure 5 it is ready for creating images. For example I asked it to create a panda bear riding a bicycle in the prompt field under <em>txt2img<\/em> and after a few seconds the image was generated. This standalone tool is not sufficient for a continuous AI workflow because if one wants to continue the conversation with the AI about the images it must rely on conversational context and memory. Therefore, there is a need to create a link between Automatic1111 and the Open WebUI. In order to do that navigate, in Open WebUI, to the <em>admin<\/em> menu and from there to <em>images<\/em> and do a few configurations, see the next screenshot<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"337\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-1024x337.png\" alt=\"\" class=\"wp-image-261\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-1024x337.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-300x99.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-768x253.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-1536x506.png 1536w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9-1568x517.png 1568w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-9.png 1593w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 6. Linking between Open WebUI and Automatic111<\/figcaption><\/figure>\n\n\n\n<p>Because of the limited memory on the GPU I configured the LLM in Open WebUI to run on the CPU, reserving GPU memory for image generation via Automatic1111. In the nvidia-smi screenshot, Figure 7, below one can see that ollama is absent but there is a running a Python script (Automatic1111).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"918\" height=\"561\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-12.png\" alt=\"\" class=\"wp-image-268\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-12.png 918w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-12-300x183.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-12-768x469.png 768w\" sizes=\"auto, (max-width: 918px) 100vw, 918px\" \/><figcaption class=\"wp-element-caption\">Figure 7. Output of nvidia-smi showing the python code (Automatic1111) running on the GPU<\/figcaption><\/figure>\n\n\n\n<p>To sum up this paragraph, the complete workflow of the image generation process is as follows:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"\" data-theme=\"default\"><code class=\"language-auto\">User \u2192 Open WebUI \u2192 (LLM via Ollama) \u2192 Image Request \u2192 Automatic1111 (Stable Diffusion v1.5-pruned-emaonly) \u2192 Generated Image<\/code><\/pre>\n\n\n<p>Where: <strong>Ollama<\/strong> does the LLM orchestration, <strong>Open WebUI<\/strong> does the frontend and orchestration layer, and finally <strong>Automatic1111<\/strong> is used as the image generation backend.<br>It is important to note that the LLM (via Ollama) generates the textual prompt and orchestration, while the actual image generation is performed by Stable Diffusion through Automatic1111, version <em>1.5-pruned-emaonly<\/em>, which is lightweight and well-suited for GPUs with limited VRAM (such as 8GB).<\/p>\n\n\n\n<p>4. <strong>Testing the model for graphics creation<\/strong><\/p>\n\n\n\n<p>Before creating images you need to click on &#8220;Integrations&#8221; at the bottom left of the prompt area and select images. An <em>image<\/em> icon will appear right to the Integration icon &#8211; see Figure 8.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"182\" height=\"123\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-13.png\" alt=\"\" class=\"wp-image-271\" style=\"aspect-ratio:1.4797014503355679;width:235px;height:auto\"\/><figcaption class=\"wp-element-caption\">Figure 8. The chat window is ready  to deal with images<\/figcaption><\/figure>\n<\/div>\n\n\n<p>I made a request <em>&#8220;Draw a panda bear riding a blue bicycle&#8221;<\/em> and Figure 9 illustrates the result.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-11.png\" alt=\"\" class=\"wp-image-267\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-11.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-11-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-11-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><figcaption class=\"wp-element-caption\">Figure 9. &#8220;<em>Draw a Panda bear riding a blue bicycles<\/em>&#8220;&#8230;<\/figcaption><\/figure>\n\n\n\n<p>In another example I asked: &#8220;Create an image of a farm house with a single large black cat lying by the entrance door&#8221; and the result (after a few iterations), see Figure 10. Despite my request the cat isn&#8217;t located according to the instruction.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-14.png\" alt=\"\" class=\"wp-image-272\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-14.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-14-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-14-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><figcaption class=\"wp-element-caption\">Figure 10. A cat NOT lying by the entrance door<\/figcaption><\/figure>\n\n\n\n<p>In fact, other tests were disappointing most of the time. Part of it is because the prompt wasn&#8217;t accurate enough. Prompts must be precise and structured, often requiring explicit constraints and compositional guidance. <\/p>\n\n\n\n<p>At this point I wanted to test the newly released Gemma 4 model with the hope to obtain better images. The full Gemma 4 is too heavy for my computer so I tried the 4-bit quantized model and in addition I had to  do additional tricks in order to test it. Gemma 4 installation under ollama is simple:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"\" data-theme=\"default\"><code class=\"language-auto\">ollama run gemma4:31b-it-q4_K_M<\/code><\/pre>\n\n\n<p>Gemma 4 used a significant part of the VRAM and together with Automatic1111 it was too much for the GPU to handle, see Figure 11.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"173\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-15-1024x173.png\" alt=\"\" class=\"wp-image-273\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-15-1024x173.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-15-300x51.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-15-768x130.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-15.png 1234w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 11. Gemma 4 along with Automatic 111 are running on the GPU. See &#8220;C&#8221; for Compute. <\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"925\" height=\"598\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-16.png\" alt=\"\" class=\"wp-image-274\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-16.png 925w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-16-300x194.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-16-768x497.png 768w\" sizes=\"auto, (max-width: 925px) 100vw, 925px\" \/><figcaption class=\"wp-element-caption\">Figure 11. Ollama (Gemma 4) and Automatic1111 running on the GPU<\/figcaption><\/figure>\n\n\n\n<p>This experiment failed due to insufficient memory:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"\" data-theme=\"default\"><code class=\"language-auto\">CUDA out of memory. Tried to allocate 20.00 MiB. GPU 0 has a total capacty of 7.62 GiB of which 55.25 MiB is free. Including non-PyTorch memory, this process has 566.00 MiB memory in use. Process 191483 has 6.34 GiB memory in use. Of the allocated memory 403.14 MiB is allocated by PyTorch, and 30.86 MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF<\/code><\/pre>\n\n\n<p>At this point I had to free additional memory and offload Gemma 4 to the CPU in order to allow Automatic1111 to use it as it needs. I closed my default Firefox browser which I always use with many open tabs and I switched to Brave browser with just 2 open tabs &#8211; see Figure 12. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"214\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-17-1024x214.png\" alt=\"\" class=\"wp-image-276\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-17-1024x214.png 1024w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-17-300x63.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-17-768x161.png 768w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-17.png 1110w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Figure 12. Output of &#8220;top&#8221; showing ollama and 2 brave tabs running on the CPU<\/figcaption><\/figure>\n\n\n\n<p>In addition, I attempted to run a CPU-only variant of the Gemma 4 model (forcing execution without GPU acceleration). I called this modified model <em>gemma4-31b-cpu<\/em>. Finally I used a very pedantic prompt:<\/p>\n\n\n<pre class=\"wp-block-code synano has-header\" data-header=\"\" data-theme=\"default\"><code class=\"language-auto\">&quot;I want an image of a **rustic farmhouse entrance** [Style Clause].&quot;\n&quot;There must be a **single large black cat** lying on the welcome mat right by the **front door** [Core Target].&quot;\n&quot;You must prioritize the cat as the central focus of the composition [Restriction Clause].&quot;<\/code><\/pre>\n\n\n<p>After a long waiting time, the generated image appeared &#8211; Figure 13:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-18.png\" alt=\"\" class=\"wp-image-278\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-18.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-18-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-18-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><figcaption class=\"wp-element-caption\">Figure 13. A cat lying by the door. An image that was created locally by Gemma 4<\/figcaption><\/figure>\n\n\n\n<p>5.<strong> Limitations &amp; Lessons Learned<\/strong>. The image generation process was extremely slow and caused significant memory pressure, eventually leading to CUDA stalls due to conflicts between Ollama\u2019s memory management and GPU offloading mechanisms. So I had to give up <em>Gemma 4<\/em> for image generation and I switched back to <em>qwen2.5:7b<\/em>. Using the same prompt through the integrated pipeline (Open WebUI + Automatic1111), the following image was generated while using qwen2.5:7b as the LLM, see Figure 14.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-19.png\" alt=\"\" class=\"wp-image-282\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-19.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-19-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-19-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><figcaption class=\"wp-element-caption\">Figure 14 The same prompt as was used in Figure 13 with <em>qwen2.5:7b <\/em>instead of <em>gemma4-31b-cpu<\/em><\/figcaption><\/figure>\n\n\n\n<p>Repeating this query once more generated the image shown in Figure 15.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-20.png\" alt=\"\" class=\"wp-image-283\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-20.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-20-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-20-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><figcaption class=\"wp-element-caption\">Figure 15.  Another test with the same prompt as was used in Figures 13 and 14 using <em>qwen2.5:7b<\/em><\/figcaption><\/figure>\n\n\n\n<p>6. <strong>Conclusions and recommendations<\/strong><\/p>\n\n\n\n<p>In summary, this approach successfully demonstrates that local AI image generation using open-source tools is feasible. However, on commodity hardware, it remains limited by memory constraints and performance bottlenecks.<\/p>\n\n\n\n<p>While not yet practical for everyday use, it provides valuable insight into the trade-offs involved and serves as a solid foundation for further experimentation as hardware and models continue to improve.<\/p>\n\n\n\n<p>I hope you found this exploration useful.<\/p>\n\n\n\n<p>-Guy<br>********Addendum********<br>After publishing this post, I tested a smaller variant of Gemma 4 (<code>gemma4:e4b-it-q4_K_M<\/code>) instead of the larger 31B model.<\/p>\n\n\n\n<p>Interestingly, the smaller model worked out-of-the-box and was able to participate in the image generation pipeline without the severe memory issues encountered previously.<\/p>\n\n\n\n<p>This reinforces an important practical insight:<\/p>\n\n\n\n<p><em>The main limitation is not the model family itself, but rather the model size relative to available GPU memory.<\/em><\/p>\n\n\n\n<p>In constrained environments (e.g., 8GB VRAM), smaller quantized models can provide a workable balance between performance and resource usage. Enjoy the new black cat image:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"512\" height=\"512\" src=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-21.png\" alt=\"\" class=\"wp-image-318\" srcset=\"https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-21.png 512w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-21-300x300.png 300w, https:\/\/tel-zur.net\/blog\/wp-content\/uploads\/2026\/04\/image-21-150x150.png 150w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post, I describe a method for generating AI images locally using open-source tools. This approach is both free and privacy-preserving. However, there are no free lunches; it comes with trade-offs, including slower performance and occasional quality limitations. The content of this post is as follows: Let&#8217;s begin&#8230; curl -fsSL https:\/\/ollama.com\/install.sh | sh &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/tel-zur.net\/blog\/2026\/04\/05\/ai-generated-images-using-opensource-tools-and-on-local-resources\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;AI generated images using opensource tools and on local resources&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-249","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/comments?post=249"}],"version-history":[{"count":47,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions"}],"predecessor-version":[{"id":320,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions\/320"}],"wp:attachment":[{"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/media?parent=249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/categories?post=249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tel-zur.net\/blog\/wp-json\/wp\/v2\/tags?post=249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}