Skip to content

Commit

Permalink
Add skin tone modifiing scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
C1710 committed Apr 4, 2018
1 parent 9745b6d commit 6e9f9e3
Show file tree
Hide file tree
Showing 18 changed files with 879 additions and 0 deletions.
17 changes: 17 additions & 0 deletions skintone/blob/base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "base",
"extension": "",
"tolerance": 5,
"colors":
{
"skin": "#FEE133",
"stroke": "#eb8f00",
"dark": "#242424",
"tongue": "#e04c74",
"tongue_dark": "#ab3d2e",
"blue": "#40c0e7",
"blue_stroke": "#47a9b0",
"water": "#5f7aff",
"water_stroke": "#4864ed"
}
}
16 changes: 16 additions & 0 deletions skintone/blob/blob.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "blob",
"extension": "blob",
"colors":
{
"skin": "#fcc21b",
"stroke": "#fcc21b",
"dark": "#2f2f2f",
"tongue": "#d7598b",
"tongue_dark": "#d7598b",
"blue": "#4fafd8",
"blue_stroke": "#4fafd8",
"water": "#ffffff",
"water_stroke": "#ffffff"
}
}
65 changes: 65 additions & 0 deletions skintone/blobify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import generate_skincolor
import remove_gradient
import emoji
import argparse
import os


def main():
"""
Die main-Funktion, welche die Skin-Modifier verarbeitet
:return: Nix
"""
# Alle Kommandozeilenargumente hinzufügen
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required = True)
group.add_argument('--input_file', '-i', help='Input file', metavar='ifile')
group.add_argument('--input_dir', '-d', help='Input directory', metavar='idir', default = '.')
parser.add_argument('--mod_dir', '-m', help='Modifier directory', metavar='mdir', default = './blob')
parser.add_argument('--base_name', '-b', help='Name of the base skin color', metavar='bname', default='base')
# Zu dict verarbeiten
args = vars(parser.parse_args())
# SKin-Modifier erstellen
modifiers = generate_skincolor.generate_modifiers(args['mod_dir'])
# Wurde ein Verzeichnis gewählt?
if args['input_dir']:
process_folder(args['input_dir'], modifiers, args['base_name'])
else:
process_file(modifiers, modifiers, args['base_name'])


def process_folder(path: str, modifiers, base) -> None:
"""
Entfernt die Verläufe für alle Dateien eines Ordners
:param path: Der Pfad zur Datei
:param modifiers: Die Modifikatoren
:param base: Der Basistyp
:return: Nix (ändert die Datei)
"""
files = os.listdir(path)
errors = []
for file in files:
# Nur SVG wird derzeit unterstützt
if os.path.splitext(file)[-1].lower() in {'.svg'}:
err = process_file(os.path.join(path, file), modifiers, base, True)
if err:
errors.append(err)
print('Es sind {} Fehler aufgetreten bei folgenden Dateien:\n {}'.format(len(errors), '\n '.join(errors)))


def process_file(path, modifiers, base, folder = False):
try:
# Entferne Verläufe
remove_gradient.process_file(path)
# Erstelle ein Emoji-Objekt
emoji_ = emoji.Emoji(modifiers, path, base)
# Und wende die Modifier an
emoji_.batch_modify()
except Exception as e:
print('Es ist ein Fehler aufgetreten beim Bearbeiten von: {}'.format(path))
print(e)
return path


if __name__ == '__main__':
main()
116 changes: 116 additions & 0 deletions skintone/emoji.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from modifier import *
import re


class Emoji:

# There are some cases where an FE0F character has to be applied.
# This is the case for gender symbols which should be represented as emojis and not as characters
fe0f_chars = {'♀', '♂'}

def __init__(self, modifiers: dict, path: str, base: str, end: bool = False):
"""
Create a new Emoji
:param modifiers: All skin modifiers available to this emoji
:param path: The path of the base SVG file
:param base: Name of the base type
:param end: True/False explicitly sets the FE0F character. fe0f_chars is used if None
"""
# Assignments
self.modifiers = modifiers
self.path = path
self.directory = os.path.dirname(path)
self.base = modifiers[base]
self.name = os.path.splitext(os.path.basename(path))[0]
self.fextension = os.path.splitext(os.path.basename(path))[1]
self.content = self.load()
if end is not None:
# Explicit
self.end = end
else:
# Implicit
self.end = False
# Does it contain an "FE0F indicator"?
for char in Emoji.fe0f_chars:
if(char in path):
self.end = True
break

def batch_modify(self):
"""
new_modified_file for all Modifiers
:return: None
"""
for name, modifier in self.modifiers.items():
# You don't need to convert from base to base
if modifier != self.base:
self.new_modified_file(modifier)
print('{} auf Emoji {} angewendet.'.format(name, self.name))

def new_modified_file(self, modifier: Modifier):
"""
Creates a new skin tone variant file
:param modifier: The Modifier
:return: None
"""
# Update the SVG file
new_content = self.generate_modified(modifier)
# Save file
self.save(new_content, modifier.extension)

def load(self) -> str:
"""Gets the (text) content of the base SVG file of this Emoji.
:return: the SVG file's content"""
try:
with open(self.path) as file:
return file.read()
except FileNotFoundError:
print('File "{}" not found!'.format(self.path))

def generate_modified(self, modifier: Modifier):
"""
Creates a new skin tone variant of this Emoji
:param modifier: The Modifier which has to be applied
:return: The altered SVG file's content
"""
# We're going to work on a copy of the content
content = self.content
# All colors are indexed by their name. We'll replace one by one
for old, new in modifier.replace(self.base).items():
# Create the regular expression which will be used
old_regex = re.compile(old, re.IGNORECASE)
# ...Apply it
content = old_regex.sub(new, content)
return content

def save(self, content: str, extension: str) -> None:
"""
Save the new skin tone variant
:param content: The new content which has been created
:param extension: Any new characters which have to be added (usually 200d + the skin tone modifier)
:return: None (writes the file)
"""
# Well, this should be obvious...
with open(self.generate_path(extension), 'w') as file:
file.write(content)

def generate_path(self, extension: str) -> str:
"""
Creates the file path of the newly created variant
:param extension: All characters which have to be added to this emoji.
:return: A str containing the path/to/emoji_variant.svg
"""
# Which directory? (It will be saved in the same one as the base emoji)
directory = self.directory
# Which is the base name of the file? (e.g. emoji_u1f973)
basename = self.name
# The file extension (.svg)
fileextension = self.fextension
base_seq = basename.split('_')
base_seq.insert(2, extension)
# Add FE0F?
if self.end:
base_seq.append('fe0f')
basename = '_'.join(base_seq)
# Stitch it together and return the whole file path
return os.path.join(directory, basename) + fileextension
74 changes: 74 additions & 0 deletions skintone/generate_skincolor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-

import os
import sys
import argparse
from modifier import *
from emoji import *


def main():
"""
The main function doing all the work
:return: Nothing
"""
# We'll need all those command line arguments
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required = True)
group.add_argument('--input_file', '-i', help='Input file.svg', metavar='ifile')
group.add_argument('--input_dir', '-d', help='Directory containing all base files.svg', metavar='idir', default = '.')
parser.add_argument('--mod_dir', '-m', help='Directory containing all modifier.json', metavar='mdir', default = './skins')
parser.add_argument('--base_name', '-b', help='Name of the base skin color (without file extensions)', metavar='bname', default='base')
parser.add_argument('--add_end', '-e', help='Do you want to add an fe0f ZWJ-sequence?', default='auto', choices=['y','n','auto'], required=False)
# Make a dict out of it
args = vars(parser.parse_args())
end = False if args['add_end'].lower() == 'n' else (True if args['add_end'].lower() == 'y' else None)
# Create skin-Modifiers
modifiers = generate_modifiers(args['mod_dir'])
# Did the user chose a dir or a file?
if args['input_dir']:
multi_process(args['input_dir'], modifiers, args['base_name'], end)
else:
# Create this one Emoji object
emoji = Emoji(modifiers, args['input_file'], args['base_name'], end)
# Apply modifiers
emoji.batch_modify()


def generate_modifiers(path: str) -> dict:
"""
Parses all skin modifiers in their directory
:param path: Directory containing the JSON files for the modifiers
:return: A str-Modifier dict containing the modifiers, sorted by their name (name: modifier)
"""
modifiers = {}
for file in os.listdir(path):
# Ignore non-JSON files
if os.path.splitext(file)[-1].lower() == '.json':
# Create one Modifier out of this JSON file
modifier = Modifier.generate_from_json(os.path.join(path, file))
modifiers.update({modifier.name: modifier})
return modifiers


def multi_process(directory: str, modifiers: dict, base: str, end: bool = False):
"""
Processes one directory of Emoji files
:param directory: The directory containing the base SVG files
:param modifiers: All Modifiers (probably provided by generate_modifiers)
:param base: The name of the base skin color used in the base SVG files
:param end: If an FE0F sequence should be added
:return: Nothing (Files will be written)
"""
files = os.listdir(directory)
for file in files:
# Ignore non-SVG-files
if os.path.splitext(file)[-1].lower() in {'.svg'}:
# Create a new Emoji-object
emoji = Emoji(modifiers, os.path.join(directory, file), base, end)
# Apply modifiers
emoji.batch_modify()


if __name__ == '__main__':
main()
74 changes: 74 additions & 0 deletions skintone/generate_skincolor_de.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-

import os
import sys
import argparse
from modifier import *
from emoji import *


def main():
"""
Die main-Funktion, welche die Skin-Modifier verarbeitet
:return: Nix
"""
# Alle Kommandozeilenargumente hinzufügen
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required = True)
group.add_argument('--input_file', '-i', help='Input file', metavar='ifile')
group.add_argument('--input_dir', '-d', help='Input directory', metavar='idir', default = '.')
parser.add_argument('--mod_dir', '-m', help='Modifier directory', metavar='mdir', default = './skins')
parser.add_argument('--base_name', '-b', help='Name of the base skin color', metavar='bname', default='base')
parser.add_argument('--add_end', '-e', help='Do you want to add an fe0f ZWJ-sequence?', default='n', choices=['y','n','auto'], required=False)
# Zu dict verarbeiten
args = vars(parser.parse_args())
end = False if args['add_end'].lower() == 'n' else (True if args['add_end'].lower() == 'y' else None)
# Skin-Modifier erstellen
modifiers = generate_modifiers(args['mod_dir'])
# Wurde ein Verzeichnis gewählt?
if args['input_dir']:
multi_process(args['input_dir'], modifiers, args['base_name'], end)
else:
# Erstelle ein Emoji-Objekt
emoji = Emoji(modifiers, args['input_file'], args['base_name'], end)
# Und wende die Modifier an
emoji.batch_modify()


def generate_modifiers(path: str) -> dict:
"""
Holt alle Skin-Modifier aus dem Ordner
:param path: Der Ordner mit den JSON-Dateien
:return: Ein dict mit name: Modifier
"""
modifiers = {}
for file in os.listdir(path):
# Ist es überhaupt eine JSON-Datei?
if os.path.splitext(file)[-1].lower() == '.json':
# Erstelle aus der JSON-Datei und füge es ein
modifier = Modifier.generate_from_json(os.path.join(path, file))
modifiers.update({modifier.name: modifier})
return modifiers


def multi_process(directory: str, modifiers: dict, base: str, end: bool = False):
"""
Verarbeitet ein ganzes Verzeichnis mit Emojis
:param directory: Der Ordner
:param modifiers: Die Skin-Modifier
:param base: Der Name des Basis-Typen
:param end: Ob noch eine fe0f-Sequenz angefügt werden soll.
:return: Nix
"""
files = os.listdir(directory)
for file in files:
# Nur SVG wird derzeit unterstützt
if os.path.splitext(file)[-1].lower() in {'.svg'}:
# Erstelle ein Emoji-Objekt
emoji = Emoji(modifiers, os.path.join(directory, file), base, end)
# Und wende die Modifier an
emoji.batch_modify()


if __name__ == '__main__':
main()
Loading

0 comments on commit 6e9f9e3

Please sign in to comment.