#!/usr/bin/env python # License: Public Domain - https://creativecommons.org/share-your-work/public-domain/cc0/ from gimpfu import * import math def create_spritesheet(image, singleRow): # Grab all the layers from the original image, each one of which will become an animation frame layers = image.layers numLayers = len(layers) # Work out how many rows and columns we need for each of our layers/animation frames numRows = 1 if singleRow else int(math.ceil(math.sqrt(numLayers))) numCols = numLayers if singleRow else numRows # And then determine the size of our new image based on the number of rows and columns newImgWidth = image.width * numCols newImgHeight = image.height * numRows # Create a new image and a single layer that fills the entire canvas newImage = gimp.Image(newImgWidth, newImgHeight, RGB) newLayer = gimp.Layer(newImage, "Spritesheet", newImgWidth, newImgHeight, RGBA_IMAGE, 100, NORMAL_MODE) newImage.add_layer(newLayer, 1) # Clear any selections on the original image to esure we copy each layer in its entirety pdb.gimp_selection_none(image) # Layers are in the reverse order we want them so start at the end of the list and work backwards layerIndex = (numLayers - 1) # Loop over our spritesheet grid filling each one row at a time for y in xrange(0, numRows): for x in xrange(0, numCols): # Copy the layer's contents and paste it into a "floating" layer in the new image pdb.gimp_edit_copy(layers[layerIndex]) floatingLayer = pdb.gimp_edit_paste(newLayer, TRUE) # This floating layer will default to the center of the new image so we first shift to the top left # corner (0, 0) and and then shift to correct grid position based on current row and column index xOffset = (-newImgWidth/2) + (image.width/2) + (x * image.width) yOffset = (-newImgHeight/2) + (image.height/2) + (y * image.height) # GIMP will only copy non-transparent pixels, so if our image contains transparency # the new floating layer may be smaller than we want which will cause animation issues. # To resolve this we adjust our position by the difference in layer size to ensure everything aligns xOffset += (image.width - floatingLayer.width) / 2 yOffset += (image.height - floatingLayer.height) / 2 # Move the floating layer into the correct position pdb.gimp_layer_translate(floatingLayer, xOffset, yOffset) # Move to the next layer, unless we're all done in which case exit! layerIndex = (layerIndex - 1) if layerIndex < 0: break; # Merge the last floating layer into our final 'Spritesheet' layer pdb.gimp_image_merge_visible_layers(newImage, 0) # Create and show a new image window for our spritesheet gimp.Display(newImage) gimp.displays_flush() # Register the plugin with Gimp so it appears in the filters menu register( "python_fu_create_spritesheet", "Creates a spritesheet (in a new image) from the layers of the current image.", "Creates a spritesheet (in a new image) from the layers of the current image.", "Karn Bianco", "Karn Bianco", "2018", "Create Spritesheet", "*", [ (PF_IMAGE, 'image', 'Input image:', None), (PF_BOOL, "singleRow", "Output to a single row?", FALSE) ], [], create_spritesheet, menu="/Filters/Animation/") main()