design

GIMP 3.0.6: Expanding the Favicon Plugin into a Full Web Icon Generator

2026-03-12 design 3 min read

In the first part of this article series, we built a working Python plugin that automatically generates favicons from a GIMP .xcf project file. That alone can save a tremendous amount of time. In this second part, we take the concept further by expanding the plugin into a full web icon generator capable of exporting icons used across modern browsers, mobile devices, and progressive web apps.

Why Expand the Plugin?

While traditional favicons only required a few sizes, modern websites often require several additional icons for different devices and operating systems. Instead of exporting these manually, a plugin can generate them all instantly from the same source design.

Modern websites frequently include icons for:

  • Browser tabs and bookmarks
  • Windows shortcuts
  • Apple iOS home screen icons
  • Android Progressive Web App icons

By expanding our plugin, we can generate all of these automatically with a single click.

Modern Web Icon Sizes

The updated plugin will export several additional icons commonly used in modern web projects:

These icons support most modern browsers and mobile platforms without needing external favicon generation tools.

Design Requirement: Square Source Images

Before exporting icons, it is important that the design inside your GIMP project is square. Favicons and web icons rely on a 1:1 aspect ratio. If the source image is not square, the exported icons will appear distorted.

The updated plugin now includes a validation check that ensures the image width and height are equal before exporting any icons.

python
				 
width = image.get_width()
height = image.get_height()
if width != height:
    Gimp.message("Image must be square for icon generation.")
			

Using a Scalable Icon Map

Instead of manually writing export code for each icon, the plugin uses a simple dictionary that maps filenames to their target sizes. This makes the plugin easy to expand later if new icon standards appear.

Each entry represents a file that will be exported using the same process we built in Part One — duplicate the image, scale it, export it, and then delete the duplicate to preserve memory.

Full Plugin Example

Below is the expanded version of the plugin that generates both traditional favicons and modern mobile web icons.

python
				 
#!/usr/bin/env python3
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp, GLib, Gio
import os
import sys

# Localization helpers
def N_(message): return message
def _(message): return GLib.dgettext(None, message)

class WebIconGenerator(Gimp.PlugIn):

    # Register plugin procedure
    def do_query_procedures(self):
        return ["plug-in-web-icon-generator"]

    # Define plugin metadata and menu placement
    def do_create_procedure(self, name):
        procedure = Gimp.ImageProcedure.new(
            self, name, Gimp.PDBProcType.PLUGIN, self.run, None
        )

        procedure.set_image_types("*")
        procedure.set_sensitivity_mask(Gimp.ProcedureSensitivityMask.DRAWABLE)

        procedure.set_menu_label("Web Icon Generator")

        procedure.add_menu_path('<Image>/Filters/Development/Python-Fu/')

        procedure.set_documentation(
            "Generate modern web icons",
            "Exports favicon, Apple, and Android icons from the current image.",
            name
        )

        procedure.set_attribution("Kensley", "Kensley", "2026")

        return procedure

    # Main execution
    def run(self, procedure, run_mode, image, drawables, config, run_data):

        try:

            # Ensure the image has been saved so we know where to export
            file_obj = image.get_file()

            if not file_obj:
                Gimp.message("Please save the image as .xcf first.")
                return procedure.new_return_values(
                    Gimp.PDBStatusType.CALLING_ERROR, GLib.Error()
                )

            folder_path = os.path.dirname(file_obj.get_path())

            # Ensure the image is square (important for icons)
            width = image.get_width()
            height = image.get_height()

            if width != height:
                Gimp.message("Image must be square for icon generation.")
                return procedure.new_return_values(
                    Gimp.PDBStatusType.CALLING_ERROR, GLib.Error()
                )

            # Define all icons we want to generate
            icon_map = {
                "favicon-16.png": 16,
                "favicon-32.png": 32,
                "favicon-48.png": 48,
                "favicon-64.png": 64,
                "apple-touch-icon.png": 180,
                "android-chrome-192.png": 192,
                "android-chrome-512.png": 512
            }

            pdb = Gimp.get_pdb()
            proc = pdb.lookup_procedure("file-png-export")

            for filename, size in icon_map.items():

                # Duplicate original image
                dup = image.duplicate()

                # Resize duplicate
                dup.scale(size, size)

                export_path = os.path.join(folder_path, filename)

                gfile = Gio.File.new_for_path(export_path)

                # Configure export
                cfg = proc.create_config()
                cfg.set_property("run-mode", Gimp.RunMode.NONINTERACTIVE)
                cfg.set_property("image", dup)
                cfg.set_property("file", gfile)

                # Run export
                proc.run(cfg)

                # Clean memory
                dup.delete()

            Gimp.message(f"Web icons generated in:
{folder_path}")

        except Exception as e:

            Gimp.message(f"Error in Web Icon Generator:
{str(e)}")

            return procedure.new_return_values(
                Gimp.PDBStatusType.CALLING_ERROR,
                GLib.Error()
            )

        return procedure.new_return_values(
            Gimp.PDBStatusType.SUCCESS,
            GLib.Error()
        )

# Register plugin
Gimp.main(WebIconGenerator.__gtype__, sys.argv)
			

End Result

  • favicon-16.png
  • favicon-32.png
  • favicon-48.png
  • favicon-64.png
  • apple-touch-icon.png
  • android-chrome-192.png
  • android-chrome-512.png
Workflow Advantage:
  • No need for external favicon generators.
  • Maintain a single master design inside your .xcf file.
  • Ensure the design is square.
  • Select the final composite layer.
  • Run Filters → Development → Python-Fu → Web Icon Generator.
  • All modern web icons export instantly to the same project folder.

Conclusion

Expanding a simple favicon generator into a full web icon exporter demonstrates how powerful GIMP's Python plugin system can be. By automating repetitive export tasks, designers and developers can focus more on crafting strong visual assets rather than manually generating multiple icon sizes. This workflow becomes especially valuable when managing multiple web projects where consistency and speed are critical.