Skip to content

Instantly share code, notes, and snippets.

@aquila12
Last active May 1, 2024 08:07
Emote generator for GIMP
; Emote test page generator
; aquila12 (Lissa Moriarty)
; (c) 2022
; Provided under the MIT license
;
; for Scheherazade
(define AUTHOR_MAIL "Lissa Moriarty <h9e72r38k@mozmail.com>")
(define AUTHOR_NAME "Lissa Moriarty")
(define AUTHOR_DATE "17 Mar 2019")
(define EMOTEGEN-SUBMENU "<Image>/Image/Emote Generator")
(define EMOTEGEN-TWITCH-SIZES '(18 36 72 28 56 112)) ; Badge sizes / emote sizes
(define EMOTEGEN-TWITCH-DARK '( 24 24 27)) ;#18181b
(define EMOTEGEN-TWITCH-LIGHT '(255 255 255)) ;#ffffff
(define EMOTEGEN-DISCORD-SIZES '(16 22 48 144)) ; Desktop reaction / small / large = Android small+reaction / android large
(define EMOTEGEN-DISCORD-DARK '( 54 57 63)) ;#36393f
(define EMOTEGEN-DISCORD-LIGHT '(255 255 255)) ;#ffffff
(define EMOTEGEN-SIZE-OPTIONS '("Twitch" "Discord"))
(define EMOTEGEN-MARGIN 2)
(define EMOTEGEN-SPACING 2)
; Forward definitions of exports
(define emotegen-create-page)
(define emotegen-export-emotes)
(let*
(
; Compatibility fixes for 2.8
(is-2.8 (= 0 (strcmp (substring (car (gimp-version)) 0 4) "2.8.")))
(gimp-image-insert-layer (if is-2.8 (lambda (p1 p2 p3 p4) (gimp-image-add-layer p1 p2 p4)) gimp-image-insert-layer))
(gimp-context-set-background (if is-2.8 (lambda (p1) (gimp-palette-set-background p1)) gimp-context-set-background))
(gimp-drawable-edit-fill (if is-2.8 (lambda (p1 p2) (gimp-edit-fill p1 p2)) gimp-drawable-edit-fill))
(gimp-item-transform-translate (if is-2.8 (lambda (p1 p2 p3) (gimp-layer-translate p1 p2 p3)) gimp-item-transform-translate))
(gimp-image-undo-group-start (if is-2.8 (lambda (p1) (gimp-undo-push-group-start p1)) gimp-image-undo-group-start))
(gimp-image-undo-group-end (if is-2.8 (lambda (p1) (gimp-undo-push-group-end p1)) gimp-image-undo-group-end))
(LAYER-MODE-NORMAL (if is-2.8 NORMAL LAYER-MODE-NORMAL))
(FILL-BACKGROUND (if is-2.8 BACKGROUND-FILL FILL-BACKGROUND))
)
; Create a new layer containing the flattened source image at a particular size
; Return the layer; it's already added to the specified image
(define (emotegen--create-emote src_image dst_image emote_size)
(let*
(
(layer (car (gimp-layer-new-from-visible src_image dst_image "Emote")))
)
(gimp-image-insert-layer dst_image layer 0 -1)
(gimp-layer-scale layer emote_size emote_size FALSE)
layer
)
)
; Generate an emote panel with a 2px margin
(define (emotegen--create-panel src_image dst_image emote_size x y)
(let*
(
(margin EMOTEGEN-MARGIN)
(panel_size (+ margin emote_size margin))
(fg_layer 0)
)
(set! fg_layer (emotegen--create-emote src_image dst_image emote_size))
(gimp-item-transform-translate fg_layer (+ x margin) (+ y margin))
)
)
(define (emotegen--create-set src_image dst_image bg_colour sizes x y)
(let*
(
(margin EMOTEGEN-MARGIN)
(spacing EMOTEGEN-SPACING)
(sum 0)
(bg_layer 0)
(set-width (+ (apply + (map (lambda (s) (+ margin s margin)) sizes)) (* spacing (- (length sizes) 1))) )
(set-height (+ margin (apply max sizes) margin))
)
; Create the background layer
(gimp-context-set-background bg_colour)
(set! bg_layer (car (gimp-layer-new
dst_image
set-width
set-height
RGBA-IMAGE "Colour Panel"
100
LAYER-MODE-NORMAL
)))
(gimp-image-insert-layer dst_image bg_layer 0 -1)
(gimp-drawable-edit-fill bg_layer FILL-BACKGROUND)
(gimp-item-transform-translate bg_layer 0 y)
(for-each
(lambda (size)
(emotegen--create-panel
src_image dst_image size
(+ x sum)
(+ y (/ (- (apply max sizes) size) 2))
)
(set! sum (+ sum margin size margin spacing))
)
sizes
)
)
)
(define (emotegen--create-page src_image dark_t light_t dark_d light_d)
(gimp-context-push)
(gimp-context-set-interpolation INTERPOLATION-CUBIC)
(let*
(
(margin EMOTEGEN-MARGIN)
(spacing EMOTEGEN-SPACING)
(dst_image (car (gimp-image-new 1 1 RGB)))
(y 0)
)
(gimp-image-undo-group-start dst_image)
(emotegen--create-set src_image dst_image dark_t EMOTEGEN-TWITCH-SIZES 0 y)
(set! y (+ y margin (apply max EMOTEGEN-TWITCH-SIZES) margin spacing))
(emotegen--create-set src_image dst_image light_t EMOTEGEN-TWITCH-SIZES 0 y)
(set! y (+ y margin (apply max EMOTEGEN-TWITCH-SIZES) margin spacing))
(emotegen--create-set src_image dst_image dark_d EMOTEGEN-DISCORD-SIZES 0 y)
(set! y (+ y margin (apply max EMOTEGEN-DISCORD-SIZES) margin spacing))
(emotegen--create-set src_image dst_image light_d EMOTEGEN-DISCORD-SIZES 0 y)
(gimp-image-resize-to-layers dst_image)
(gimp-image-undo-group-end dst_image)
(gimp-display-new dst_image)
(gimp-displays-flush)
)
(gimp-context-pop)
)
(define (emotegen--export-emote src_image size prefix directory)
(gimp-context-push)
(gimp-context-set-interpolation INTERPOLATION-CUBIC)
(let*
(
(filename (string-append prefix (number->string size) ".png"))
(dst_image (car (gimp-image-new size size RGB)))
(layer (emotegen--create-emote src_image dst_image size))
)
(file-png-save RUN-NONINTERACTIVE dst_image layer (string-append directory "/" filename) filename 0 9 1 1 1 1 1)
(gimp-image-delete dst_image)
)
(gimp-context-pop)
)
(define (emotegen--export-emotes src_image size_option prefix directory)
(let*
(
(size_name (list-ref EMOTEGEN-SIZE-OPTIONS size_option))
(size_list (string-append "EMOTEGEN-" (string-upcase size_name) "-SIZES"))
(sizes (eval (string->symbol size_list)))
)
(for-each
(lambda (size)
(emotegen--export-emote src_image size prefix directory)
)
sizes
)
)
)
; Hoist exported functions
(set! emotegen-create-page emotegen--create-page)
(set! emotegen-export-emotes emotegen--export-emotes)
)
(script-fu-register
"emotegen-create-page"
"Generate Emote Test Page"
"Creates sized versions of the current image against test colours in a new image"
AUTHOR_MAIL
AUTHOR_NAME
AUTHOR_DATE
"RGB RGBA GRAY GRAYA"
SF-IMAGE "Image containing the emote" 0
SF-COLOR "Dark twitch colour" EMOTEGEN-TWITCH-DARK
SF-COLOR "Light twitch colour" EMOTEGEN-TWITCH-LIGHT
SF-COLOR "Dark discord colour" EMOTEGEN-DISCORD-DARK
SF-COLOR "Light discord colour" EMOTEGEN-DISCORD-LIGHT
)
(script-fu-menu-register "emotegen-create-page" EMOTEGEN-SUBMENU)
(script-fu-register
"emotegen-export-emotes"
"Export Presized Emotes"
"Saves a set of sized versions of the current image"
AUTHOR_MAIL
AUTHOR_NAME
AUTHOR_DATE
"RGB RGBA GRAY GRAYA"
SF-IMAGE "Image containing the emote" 0
SF-OPTION "Sizes for" EMOTEGEN-SIZE-OPTIONS
SF-STRING "File prefix" "untitled-emote"
SF-DIRNAME "Export directory" ""
)
(script-fu-menu-register "emotegen-export-emotes" EMOTEGEN-SUBMENU)
@aquila12
Copy link
Author

aquila12 commented Mar 7, 2019

How to Use This

This script adds a submenu to the Image menu, which provides two options:

  • Generate Emote Test Page
  • Export Presized Emotes

Both options use the current image as input, creating a flattened copy to work with.

The emote test page consists of multiple scaled copies (as layers) above coloured tiles for dark and light backgrounds. The export option will automatically export PNGs to the chosen directory with the specified prefix.

In each case the flattened copies are made square by stretching if necessary, so you almost certainly want to start with a square canvas.

How to Install This

  • Find out where GIMP will look in Edit -> Preferences -> Folders -> Scripts; on Linux mine is at ~/.gimp-2.8/scripts/ (depending on your version).
  • Just drop the .scm (Scheme) file into gimp's scripts/ directory.
  • Go to Filters -> Script-Fu -> Refresh Scripts, and the submenu should then appear at Images -> Emote Generator

Compatibility

This has been tested on GIMP 2.8 (the version shipping with Ubuntu 18.04) and 2.10 (the latest version as of this writing). It should continue to work with later versions until the API changes again. The current version of the script automatically patches in the appropriate missing definitions for gimp 2.8 only; if you want to run another old version it'll need extra compatibility code (which was a pain to write).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment