scripts for comics trip - jacques_duflos - 05-11-2023
Hi there,
I do comics trip as a hobby. Here are some of my works. I use gimp for text, editing, sometimes coloring or texturing. I will show in this thread the scripts I did to ease some tasks. Comments and advice are welcome
This first script is made to prepare a scanned drawing. automatize de-saturating, changing contrast and light, and separate the ink from the background, so I can add a color layer in between and paint.
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GIMP plugin to separe the ink form the paper of a b&w scan
# (c) Jacques Duflos 2023
#
# History:
#
# v0.0: 2023-xx-xx: First published version
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import sys, os
from gimpfu import *
import gimpcolor
#print "**********preparer un scan***************"
debug= False
def trace(s):
if debug:
print "****"
print s
print "****"
def preparerUnScan(image):
image.undo_group_start()
trace("1")
# récupérer l'image et le calque selectionné
layer = pdb.gimp_image_get_active_layer(image)
layer_name = pdb.gimp_item_get_name(layer)
trace("2 "+ layer_name)
#désaturer, pousser le contraste très haut et augmenter un peu la luminosité.
# voir pour en faire des paramètres éventuellement.
pdb.gimp_drawable_desaturate(layer, 0)
trace("3")
pdb.gimp_drawable_brightness_contrast(layer, -0.2, 0.8)
#enregistrer les variables de contexte avant de les modifier
opacity_old = pdb.gimp_context_get_opacity()
foreground_old = pdb.gimp_context_get_foreground()
paint_mode_old = pdb.gimp_context_get_paint_mode()
#print foreground_old
pdb.gimp_context_set_opacity(100)
pdb.gimp_context_set_foreground(gimpcolor.RGB(1.0, 1.0, 1.0, 1.0))
pdb.gimp_context_set_paint_mode(LAYER_MODE_COLOR_ERASE)
#effacer l'arrière plan blanc
pdb.gimp_layer_add_alpha(layer)
pdb.gimp_drawable_edit_fill(layer, FILL_FOREGROUND)
trace("fond effacé")
#créer le fond blanc
fond = pdb.gimp_layer_new(image, pdb.gimp_image_width(image), pdb.gimp_image_height(image), RGB_IMAGE , "fond", 100, LAYER_MODE_NORMAL)
num_layers, layer_ids = pdb.gimp_image_get_layers(image)
pdb.gimp_image_add_layer(image, fond, num_layers)
pdb.gimp_context_set_paint_mode(LAYER_MODE_NORMAL )
pdb.gimp_drawable_edit_fill(fond, FILL_FOREGROUND)
#rétablir les variables
pdb.gimp_context_set_opacity(opacity_old)
pdb.gimp_context_set_foreground(foreground_old)
pdb.gimp_context_set_paint_mode(paint_mode_old)
trace("contexte rétabli")
image.undo_group_end()
### Registrations
whoiam='\n'+os.path.abspath(sys.argv[0])
register(
'preparer-un-scan',
'Prépare un scan %s' % whoiam,
'prépare un scan',
'Jacques Duflos','Jacques Duflos','2023',
'Prépare un scan...',
'*',
[
(PF_IMAGE, 'image', 'Image', None)
],
[],
preparerUnScan,
menu='<Image>/Layer'
)
main()
This second script is made to move all the text layers in a layer group named texts.
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GIMP plugin to move every text layer in a text layer group
# (c) Jacques Duflos 2023
#
# History:
#
# v0.0: 2023-xx-xx: First published version
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import sys, os
from gimpfu import *
import gimpcolor
print "**********calques texte dans groupe***************"
debug= True
def trace(s):
if debug:
print "**** "
print s
print "**** "
def calquesTextesDansGroupe(image):
image.undo_group_start()
trace("1")
groupe_textes = pdb.gimp_layer_group_new(image)
pdb.gimp_item_set_name(groupe_textes, "textes")
pdb.gimp_image_insert_layer(image, groupe_textes, None, 0)
calques=[]
for numero_calque in range(pdb.gimp_image_get_layers(image)[0]):
calques.append(image.layers[numero_calque])
trace(calques)
for calque in calques :
if pdb.gimp_item_is_text_layer(calque):
pdb.gimp_image_reorder_item(image, calque, groupe_textes, 0)
image.undo_group_end()
### Registrations
whoiam='\n'+os.path.abspath(sys.argv[0])
register(
'textes-dans-groupe',
'Mettre les calques textes dans un groupe %s' % whoiam,
'Mettre les calques textes dans un groupe',
'Jacques Duflos','Jacques Duflos','2023',
'Mettre les calques textes dans un groupe...',
'*',
[
(PF_IMAGE, 'image', 'Image', None)
],
[],
calquesTextesDansGroupe,
menu='<Image>/Layer'
)
main()
Im presently working on a script that makes a text bubble around a text layer.
enjoy !
RE: scripts for comics trip - Ofnuts - 05-11-2023
In the first script, instead of saving/restoring individual context settings, you should just bracket your code with gimp.context_push()/gimp.context_pop() (usually goes hand in hand with the undo_group calls).
RE: scripts for comics trip - jacques_duflos - 06-10-2023
This next script exports as png all .xcf files of the same folder as the current image in a /rendu/ folder. I use it to export all the pages of the comics Im working on. I made it with chatgpt, it's the first time I use it to program, and I'm impressed.
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GIMP plugin to export all .xcf files of the folder in a /rendu/ folder
# (c) Jacques Duflos 2023
#
# History:
#
# v0.0: 2023-xx-xx: First published version
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import random
import sys, os
from gimpfu import *
import gimpcolor
debug = False
def trace(s):
if debug:
print "**** "
print s
print "**** "
trace("export group test")
def export_groupe(image):
# Chemin complet vers le fichier actif
chemin_fichier = image.filename
# Obtenir le chemin du dossier contenant le fichier
dossier = os.path.dirname(chemin_fichier)
# Chemin du dossier de rendu
dossier_rendu = os.path.join(dossier, 'Rendu')
try:
os.makedirs(dossier_rendu)
except OSError:
pass
# Obtenir la liste des fichiers dans le même dossier
fichiers_dossier = os.listdir(dossier)
# Filtrer les fichiers avec l'extension ".xcf"
fichiers_xcf = [fichier for fichier in fichiers_dossier if fichier.endswith(".xcf")]
# Exporter les fichiers .xcf vers le dossier de rendu
for fichier in fichiers_xcf:
chemin_complet = os.path.join(dossier, fichier)
nom_fichier, _ = os.path.splitext(fichier)
# Charger le fichier .xcf dans GIMP
image_xcf = pdb.gimp_xcf_load(0, chemin_complet, chemin_complet)
# Exporter le fichier dans le dossier de rendu
chemin_rendu = os.path.join(dossier_rendu, nom_fichier + ".png")
new_image = pdb.gimp_image_duplicate(image_xcf)
layer = pdb.gimp_image_merge_visible_layers(new_image, CLIP_TO_IMAGE)
pdb.gimp_file_save(new_image, layer, chemin_rendu, '?')
pdb.gimp_image_delete(new_image)
pdb.gimp_image_delete(image_xcf)
### Registrations
whoiam='\n'+os.path.abspath(sys.argv[0])
register(
'export-groupe',
'exporter tous les .xcf du dossier %s' % whoiam,
'exporter tous les .xcf du dossier',
'Jacques Duflos','Jacques Duflos','2023',
'exporter tous les .xcf du dossier...',
'*',
[
(PF_IMAGE, 'image', 'Image', None),
],
[],
export_groupe,
menu='<Image>/Layer'
)
main()
RE: scripts for comics trip - Ofnuts - 06-10-2023
(06-10-2023, 12:38 AM)jacques_duflos Wrote: I made it with chatgpt, it's the first time I use it to program, and I'm impressed.
Me, somewhat less so... looks like the intern's code
- glob.glob() does the filtering and returns the list of files with full paths: for instance glob.glob('Screenshots/*.png') returns ['Screenshots/OldStyle.png', 'Screenshots/MapObjectPlaneAxis.png'] and this would avoid some file name tinkering
- duplicating the image is somewhat wasteful, saving the result of a layer-new-from-visible is sufficient: pdb.gimp_file_save(image, pdb.gimp_layer_new_from_visible(image, image, "## saved"), '/tmp/foo.png','/tmp/foo.png')
- catching an exception to bury it with a pass is heinous. Good luck if you can't create the directory.
RE: scripts for comics trip - jacques_duflos - 06-10-2023
(06-10-2023, 07:23 AM)Ofnuts Wrote: (06-10-2023, 12:38 AM)jacques_duflos Wrote: I made it with chatgpt, it's the first time I use it to program, and I'm impressed.
Me, somewhat less so... looks like the intern's code
glade to hear that IAs are not ready to replace us all just yet . I'm particularly impressed by the generation of a functional code that actually does what I asked in a human non-precise way.
About your observations :
- glob.glob : I didn't know about this module. Is it "just" to gain one code line ? I can replace the two lines
Code:
fichiers_dossier = os.listdir(dossier)
fichiers_xcf = [fichier for fichier in fichiers_dossier if fichier.endswith(".xcf")]
- by the one line
Code:
fichiers_xcf = glob.glob(os.path.join(dossier, '*.xcf'))
- duplicating the image : chatgpt originally just omitted the layer argument of the save function. I googled the problem and found a thread on stack overflow that claimed that the duplicate technique was the easiest and not-so-resource-consuming solution. But I'll take your advice, thanks.
- skipping the directory creation : it was to avoid the error generation if the directory already exist. Chatgpt first proposed this line :
os.makedirs(dossier_rendu, exist_ok=True)but it didn't work, because of the python version used by gimp I think (?). would the code
Code:
if not os.path.exists(dossier_rendu):os.makedirs(dossier_rendu)
be more correct in your opinion ?
now my code looks like that
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GIMP plugin to export all .xcf files of the folder in a /rendu/ folder
# (c) Jacques Duflos 2023
#
# History:
#
# v0.0: 2023-xx-xx: First published version
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import random
import sys, os
from glob import glob
from gimpfu import *
import gimpcolor
debug = False
def trace(s):
if debug:
print "**** "
print s
print "**** "
trace("export group test")
def export_groupe(image):
# Chemin complet vers le fichier actif
chemin_fichier = image.filename
# Obtenir le chemin du dossier contenant le fichier
dossier = os.path.dirname(chemin_fichier)
# Chemin du dossier de rendu
dossier_rendu = os.path.join(dossier, 'Rendu')
# Check if the render directory already exists
if not os.path.exists(dossier_rendu):os.makedirs(dossier_rendu)
# Obtenir la liste des fichiers xcf dans le même dossier
fichiers_xcf = glob(os.path.join(dossier, '*.xcf'))
trace(fichiers_xcf)
# Exporter les fichiers .xcf vers le dossier de rendu
for fichier in fichiers_xcf:
nom_fichier = os.path.basename(fichier)
trace(nom_fichier)
nom_fichier, _ = os.path.splitext(nom_fichier)
trace(nom_fichier)
# Charger le fichier .xcf dans GIMP
image_xcf = pdb.gimp_xcf_load(0, fichier, fichier)
# Exporter le fichier dans le dossier de rendu
trace(dossier_rendu)
trace(nom_fichier)
chemin_rendu = os.path.join(dossier_rendu, nom_fichier + ".png")
#trace(chemin_rendu)
pdb.gimp_file_save(image_xcf, pdb.gimp_layer_new_from_visible(image_xcf, image_xcf, "## saved"), chemin_rendu,chemin_rendu)
pdb.gimp_image_delete(image_xcf)
### Registrations
whoiam='\n'+os.path.abspath(sys.argv[0])
register(
'export-groupe',
'exporter tous les .xcf du dossier %s' % whoiam,
'exporter tous les .xcf du dossier',
'Jacques Duflos','Jacques Duflos','2023',
'exporter tous les .xcf du dossier...',
'*',
[
(PF_IMAGE, 'image', 'Image', None),
],
[],
export_groupe,
menu='<Image>/Layer'
)
main()
RE: scripts for comics trip - Ofnuts - 06-10-2023
- glob.glob: a bit more than this. What it returns is a list of files with paths. So you also avoir the reconstruction of the path+file later on.
- directory: if not os.path.isdir(directory): mkdir(directory) so you avoid the error if the directory exists, and get a real error otherwise (access rights, name is used by a file, etc...). You don't need makedirS since the parent already exist.
|