Skip to content

Instantly share code, notes, and snippets.

@Tonius
Last active April 24, 2020 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tonius/6515a54d41f6b3a5b671c5df928e6cbf to your computer and use it in GitHub Desktop.
Save Tonius/6515a54d41f6b3a5b671c5df928e6cbf to your computer and use it in GitHub Desktop.
GIMP plugin that slices a Minecraft animated texture into layers; used for converting them to GIFs
#!/usr/bin/env python
import json
from gimpfu import *
def copy_frame(img, layer, sprite_size, index):
pdb.gimp_image_select_rectangle(img, CHANNEL_OP_REPLACE, 0, index * sprite_size,
sprite_size, sprite_size)
pdb.gimp_edit_copy(layer)
def paste_frame(img, layer, sprite_size):
pdb.gimp_image_select_rectangle(img, CHANNEL_OP_REPLACE, 0, 0,
sprite_size, sprite_size)
floating_selection = pdb.gimp_edit_paste(layer, FALSE)
pdb.gimp_floating_sel_anchor(floating_selection)
def slice_minecraft_animation(img, layer, frametime=1, frames='', interpolate=False):
gimp.progress_init('Slicing layer...')
pdb.gimp_image_undo_group_start(img)
try:
sprite_size = layer.width
if interpolate:
frame_ms = 50
frames_between = frametime - 1
else:
frame_ms = int(frametime / 20.0 * 1000.0)
frames_between = 0
if len(frames) > 0:
indices = json.loads(frames)
else:
indices = range(int(layer.height / sprite_size))
total_frames = len(indices) + (len(indices) * frames_between)
frame_counter = 0
for i, frame_index in enumerate(indices):
copy_frame(img, layer, sprite_size, frame_index)
layer_name = 'Frame {} ({}ms) (replace)'.format(frame_counter, frame_ms)
frame_layer = gimp.Layer(img, layer_name, sprite_size, sprite_size,
RGBA_IMAGE, 100, NORMAL_MODE)
img.add_layer(frame_layer, 0)
paste_frame(img, frame_layer, sprite_size)
gimp.progress_update(float(frame_counter + 1) / float(total_frames))
frame_counter += 1
for between_index in range(0, frames_between):
opacity = (between_index + 1.0) / (frames_between + 1.0) * 100.0
layer_name = 'Frame {} (interpolated) ({}ms) (replace)'\
.format(frame_counter, frame_ms)
between_layer = gimp.Layer(img, layer_name, sprite_size,
sprite_size, RGBA_IMAGE, 100,
NORMAL_MODE)
between_layer_overlay = gimp.Layer(img, 'Temp', sprite_size,
sprite_size, RGBA_IMAGE,
opacity, NORMAL_MODE)
img.add_layer(between_layer, 0)
img.add_layer(between_layer_overlay, 0)
copy_frame(img, layer, sprite_size, frame_index)
paste_frame(img, between_layer, sprite_size)
try:
next_frame_index = indices[i + 1]
except IndexError:
next_frame_index = indices[0]
copy_frame(img, layer, sprite_size, next_frame_index)
paste_frame(img, between_layer_overlay, sprite_size)
pdb.gimp_image_merge_down(img, between_layer_overlay,
CLIP_TO_BOTTOM_LAYER)
frame_counter += 1
gimp.progress_update(float(frame_counter + 1) / float(total_frames))
img.remove_layer(layer)
img.resize(sprite_size, sprite_size, 0, 0)
except Exception as err:
gimp.message('Unexpected error: {}'.format(str(err)))
pdb.gimp_image_undo_group_end(img)
pdb.gimp_progress_end()
register(
'python_fu_slice_minecraft_animation',
'Slice Minecraft animation',
'Slices a Minecraft animated sprite into layers.',
'Ton Broekhuizen',
'',
'2017',
'<Image>/Filters/Minecraft/Slice animation',
'RGB*',
[
(PF_INT, 'frametime', 'Frame time (from .mcmeta)', 1),
(PF_STRING, 'frames', 'Frames array (from .mcmeta)', ''),
(PF_BOOL, 'interpolate', 'Interpolate', False)
],
[],
slice_minecraft_animation
)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment