Last active
May 1, 2024 08:07
Emote generator for GIMP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to Use This
This script adds a submenu to the Image menu, which provides two options:
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
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).