GIMP "selection to row of tiles" plugin

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

GIMP "selection to row of tiles" plugin

Post by danboid »

The mode 74 tile conversion program expects the input to be one row of 8x8 pixel tiles. Currently, the Uzebox developer has to prepare their graphics working by 8x8 tiles and then manually cut the sprites and other graphical resources into individual 8x8 tiles and then manually move each tile into a single row to feed it into the tile conversion program. Pretty tedious stuff.

This process would be much easier if we had a GIMP plugin to automate most of this process by turning a rectangular GIMP selection into a row of (8x8, or whatever the user specifies) tiles. I've found a GIMP plugin that does a pretty similar thing so it shouldn't be too hard for us to modify this to create a new image composed of a row of tiles sourced from the current selection.

https://github.com/Saiapatsu/random-tiling
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

I'll ask on the GIMP forum first, there's a good chance this plugin exists already but I can't find it.

EDIT

https://www.gimp-forum.net/Thread-Conve ... w-of-tiles
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

It's ChatLGBT time!

Here are the steps you can follow:

Create a new plugin file in GIMP using the "Script-Fu" console.
Define the parameters for the plugin, including the source image, the rectangular selection, and the tile resolution.
Open the source image and select the rectangular area to be used as the source for the tiles.
Determine the dimensions of the rectangular selection and calculate the number of tiles that can fit in one row based on the tile resolution.
Create a new image with the appropriate dimensions to accommodate the row of tiles.
Loop through the number of tiles and copy the rectangular selection to a new layer in the new image.
Align the layers horizontally and flatten the image to create the final row of tiles.
Save the image as a new file.


Code: Select all

#!/usr/bin/env python
from gimpfu import *

def create_tile_row(image, selection, resolution):
    # Get the dimensions of the rectangular selection
    x, y, width, height = selection
    
    # Calculate the number of tiles that can fit in one row
    num_tiles = int(width / resolution)
    
    # Create a new image to hold the row of tiles
    new_width = num_tiles * resolution
    new_height = resolution
    new_image = gimp.Image(new_width, new_height, RGB)
    
    # Loop through the number of tiles and copy the rectangular selection to a new layer in the new image
    for i in range(num_tiles):
        # Create a new layer for the tile
        new_layer = gimp.Layer(new_image, f"Tile {i+1}", resolution, resolution, RGB_IMAGE, 100, NORMAL_MODE)
        
        # Copy the rectangular selection to the new layer
        pdb.gimp_edit_copy(image.layers[0], True)
        floating_sel = pdb.gimp_edit_paste(new_layer, True)
        
        # Align the layers horizontally
        new_layer.translate(i * resolution, 0)
        
        # Add the layer to the new image
        new_image.add_layer(new_layer, i)
    
    # Flatten the image to create the final row of tiles
    new_image.flatten()
    
    # Save the image as a new file
    pdb.file_save(new_image, new_image.active_layer, "/path/to/new/image.png", "image.png")

register(
    "python_fu_create_tile_row",
    "Create a row of tiles from a rectangular selection",
    "Creates a new image composed of one row of horizontally aligned tiles of a user-specified resolution",
    "Author Name",
    "Author Name",
    "2023",
    "<Image>/Filters/Tile Row...",
    "*",
    [
        (PF_IMAGE, "image", "Source Image", None),
        (PF_RECTANGLE, "selection", "Rectangular Selection", None),
        (PF_INT, "resolution", "Tile Resolution", 32)
    ],
    [],
    create_tile_row)

main()
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

I've attempted to use that script under Debian testing but there's a couple of issues.

Its wrote for the gimpfu module which is python2 only and python2 is no longer packaged by recent versions of Debian. If I was to build python2 I would probably have to rebuild GIMP with pygtk support too.
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

Here's take 2:

To create a GIMP plugin in the scheme language that uses a rectangular selection of part of an image as the source to create a new image composed of one row of horizontally aligned tiles of a user-specified resolution, you can use the following code:

(EDIT by me: place this is a file like ~/.config/GIMP/2.10/scripts/selection-to-tiles.scm - replacing 2.10 with your installed GIMP version)

Code: Select all

(define (create-tile-row-image drawable width height)
  (let* ((tile-width (gimp-drawable-width drawable))
         (tile-height (gimp-drawable-height drawable))
         (image-width (* width tile-width))
         (image-height height))
    (let ((image (car (gimp-image-new image-width image-height RGB))))
      (gimp-image-undo-disable image)
      (gimp-context-push)
      (gimp-context-set-interpolation 0)
      (let loop ((col 0))
        (unless (>= col width)
          (let* ((x (* col tile-width))
                 (y 0)
                 (src-x (car (gimp-selection-offsets drawable))))
            (gimp-edit-copy drawable)
            (let ((paste-layer (car (gimp-edit-paste-as-new))))
              (gimp-floating-sel-anchor paste-layer)
              (gimp-layer-set-offsets paste-layer x y)
              (gimp-layer-scale paste-layer tile-width tile-height TRUE)
              (gimp-layer-set-offsets paste-layer x y)
              (gimp-image-add-layer image paste-layer col)
              (gimp-drawable-set-visible paste-layer TRUE)))
          (loop (+ col 1))))
      (gimp-context-pop)
      (gimp-display-new image)
      (gimp-image-undo-enable image))))
      
(script-fu-register "create-tile-row-image"
                     "<Image>/Filters/Tiles/Create Tile Row Image"
                     "Creates a new image with one row of horizontally aligned tiles"
                     "Author"
                     "Author"
                     "2023"
                     "RGB"
                     SF-DRAWABLE "Drawable" 0
                     SF-VALUE "Number of Tiles" "4"
                     SF-VALUE "Tile Height" "256")
The create-tile-row-image function takes in three arguments: drawable, width, and height. drawable is the image from which the rectangular selection will be taken. width is the number of tiles in the row, and height is the height of each tile.

The function first calculates the dimensions of the new image based on the specified tile width and height, and then creates a new image with those dimensions. It then loops through each column of the new image, copying the rectangular selection from the source image and pasting it as a new layer in the new image. The new layer is then resized to the specified tile size and positioned in the correct location in the new image. Finally, the new layer is added to the new image and made visible.

The script-fu-register function registers the create-tile-row-image function as a GIMP plugin, making it accessible from the "Filters" menu under "Tiles" as "Create Tile Row Image". The SF-DRAWABLE, SF-VALUE, and SF-VALUE arguments define the input parameters for the plugin.
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

I accidentally asked it the same question again ("Write a GIMP plugin in the scheme language that uses a rectangular selection of part of an image as the source to create a new image composed of one row of horizontally aligned tiles of a user specified resolution.") and it gave me quite a different solution so here's its third solution.

To create a GIMP plugin in the scheme language that uses a rectangular selection of part of an image as the source to create a new image composed of one row of horizontally aligned tiles of a user specified resolution, you can follow these steps:

Launch GIMP and select "Filters" from the menu bar. Then, choose "Script-Fu" and click on "Console" to open the Script-Fu console.

In the console, type the following code to define the function:

Code: Select all

(define (create-tiled-image source width height)
  (let* ((img (car (gimp-image-new width (* height (car (gimp-image-height source))) RGB)))
         (layer (car (gimp-layer-new img (* width (car (gimp-image-width source))) (* height (car (gimp-image-height source))) RGB-IMAGE "Tile Layer" 100 NORMAL-MODE))))
    (gimp-image-add-layer img layer 0)
    (let loop ((x 0) (y 0))
      (when (< y height)
        (gimp-selection-none source)
        (gimp-edit-copy source)
        (let ((tile (car (gimp-edit-paste layer FALSE)))))
        (gimp-layer-set-offsets tile x (* y (car (gimp-image-height source))))
        (loop (+ x (car (gimp-image-width source))) y))
    (gimp-display-new img)))
The function create-tiled-image takes three arguments: source is the source image, width is the width of each tile, and height is the height of each tile. The function creates a new image that is composed of one row of horizontally aligned tiles of the specified resolution. The source image is divided into tiles of the specified resolution and each tile is pasted onto the new image.

To use the function, you need to define a rectangular selection of part of an image as the source. Then, go back to the console and type the following command:

Code: Select all

(create-tiled-image <your-source-image> <tile-width> <tile-height>)
Replace <your-source-image> with the source image you selected and <tile-width> and <tile-height> with the desired width and height of each tile. For example, if your source image is named "source.jpg" and you want each tile to be 100 pixels wide and 50 pixels high, you would enter the following command:

lua

Code: Select all

(create-tiled-image "source.jpg" 100 50)
Press Enter to execute the command. The function will create a new image that is composed of one row of horizontally aligned tiles of the specified resolution. The new image will be displayed in a new window.

Note: You may need to install the Scheme console plugin to be able to run Scheme code in GIMP.
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

I've got this process semi-automated now, thanks to rich2005 from the GIMP forum:

https://uzebox.org/wiki/Convert_an_imag ... g_the_GIMP
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: GIMP "selection to row of tiles" plugin

Post by Artcfox »

danboid wrote: Sun Feb 19, 2023 6:16 pm I've got this process semi-automated now, thanks to rich2005 from the GIMP forum:

https://uzebox.org/wiki/Convert_an_imag ... g_the_GIMP
Nice.

To avoid broken links (As the years go by, I see that more and more in our forum and on our wiki), it might be best to also attach those files (and source code) to a post here on the forum, and then link to them from the wiki as an alternative download source/place for discussion.
User avatar
danboid
Posts: 2090
Joined: Sun Jun 14, 2020 12:14 am

Re: GIMP "selection to row of tiles" plugin

Post by danboid »

Thats what I wanted to do Artcfox but we can't share zip or tar files on the forum unfortunately. Those were my thoughts precisely.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: GIMP "selection to row of tiles" plugin

Post by Artcfox »

danboid wrote: Sun Feb 19, 2023 8:51 pm Thats what I wanted to do Artcfox but we can't share zip or tar files on the forum unfortunately. Those were my thoughts precisely.
I attach .zip files to posts here all the time. Under the [Save draft] [Preview] [Submit] buttons, there is a tabbed view with [Options] [Attachments]. Click on [Attachements], then on the [Add files] button below, and you can select .zip/.tar.gz files from your filesystem.

Edit: I added backup download links to the following attachments in the wiki.
Attachments
guillotine-into-layers-0.1.2.tar.gz
(27.44 KiB) Downloaded 57 times
Guillotine_and_guides_GIMP_plugins.zip
(11.28 KiB) Downloaded 45 times
Post Reply