1
0
Fork 0
mirror of https://gitlab.com/oloturia/fumcaso.git synced 2025-01-08 22:47:17 +01:00
fumcaso/randstrip.py

316 lines
12 KiB
Python
Raw Normal View History

#!/usr/bin/python3.6
2019-09-09 17:32:07 +02:00
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import csv
import random
import os
import json
fileDir = os.path.dirname(os.path.abspath(__file__))
2019-09-09 17:32:07 +02:00
def replaceText(text,config):
"""This function replace $WILDCARD with a word found in subs.csv
subs.csv definition is 1st colum $WILDCARD, subsequent columns, possible values (chosen at random), delimiter is ;"""
with open(config["csvLocation"]+"/"+config["csvSubs"]) as subs:
csvReader = csv.reader(subs,delimiter=";")
for row in csvReader:
if text.find(row[0]) != -1:
text = text.replace(row[0],row[random.randint(1,len(row)-1)],1)
return text
2021-03-11 01:42:44 +01:00
print("Parsing error \""+text+"\" not found")
quit()
def fetchText(indText,config):
"""This function fetch the text for the image with two characters
rtext.csv definition is: 1st column the name of the file (i.e. B001.png), 2nd number of actors (at the moment
they are limited to two; then a couple of columns or each actor with x and y coord of the strings; after the coords the outcomes,
one column for each actor
Delimiter is ; and line feeds @, if there aren't any options, it returns 0 (no text)
It returns two arrays, coords is a tuple (x,y) and result is the outcome"""
with open(config["csvLocation"]+"/"+config["csvSpeech"]) as rtext:
csvReader = csv.reader(rtext,delimiter=';')
for row in csvReader:
if row[0]==indText:
noActors = int(row[1])
if noActors == 0:
return 0
else:
firstElement = 2+(noActors*2)
lastElement = len(row)-(noActors-1)
randQuote = random.randrange(firstElement,lastElement,noActors)
coords = []
result = []
for x in range(0,noActors):
coords.append((row[2+x*2],row[3+x*2]))
result.append(row[randQuote+x])
return coords,result
def fetchVign(config):
"""This functions fetch an image, randomly, chosen from a markov tree defined in ram.csv
ram.csv definition is: 1st column the name of the image (without extension), subsequent columns, possible outcomes chosen randomly
It returns an array with the file names"""
2019-09-09 17:32:07 +02:00
starts = []
startdest = []
nvign = 0
currVign = "000"
story = []
with open(config["csvLocation"]+"/"+config["csvTree"]) as ram:
2019-09-09 17:32:07 +02:00
csvReader = csv.reader(ram)
for row in csvReader:
starts.append(row[0])
startdest.append(row)
while nvign <100:
2019-09-09 17:32:07 +02:00
story.append(startdest[starts.index(currVign)][random.randint(1,len(startdest[starts.index(currVign)])-1)])
currVign = story[nvign]
if currVign == "END":
return story
story[nvign]+=".png"
2019-09-09 17:32:07 +02:00
nvign +=1
print("tree with no END")
quit()
2019-09-09 17:32:07 +02:00
def addThing(indVign,config):
"""This function adds a small image (object) to a larger image
obj.csv definition is: name of the image (i.e. A001.png), x-coord, y-coord, subsequent columns possible outcomes
It returns a tuple (object file name, x, y)"""
objects = list()
with open(config["csvLocation"]+"/"+config["csvObj"]) as obj:
2019-09-17 16:33:43 +02:00
csvReader = csv.reader(obj)
for row in csvReader:
if row[0] == indVign:
objects.append( (row[random.randint(3,len(row)-1)],row[1],row[2] ))
return objects
2023-02-24 02:11:30 +01:00
def fetchAltText(config,csvFile,indVign):
"""Function to fetch the correct alt text for the image"""
if os.path.exists(config["csvLocation"]+"/"+config["csvAltText"]):
with open(csvFile) as alt_text_csv:
csvReader = csv.reader(alt_text_csv,delimiter=";")
for row in csvReader:
if row[0] == indVign:
return row[1]
else:
return ""
2021-03-13 18:57:12 +01:00
def writeStrip(story,config):
"""This function creates the strip returning an image object that could be saved or viewed. It takes an array with filenames as parameter
2020-11-24 02:30:42 +01:00
The first image is always 000, then appends to strip the files, then decorates it fetching text and adding objects. If the object is an R, then
2023-02-24 02:11:30 +01:00
repeats the last object. It also generates alt text if setted correctly in the config file."""
strip = []
2023-02-24 02:11:30 +01:00
alt_text = ""
for indVign in story:
try:
vign = Image.open(config["imagesLocation"]+"/"+indVign).convert('RGBA')
addtext = ImageDraw.Draw(vign)
2021-03-13 18:57:12 +01:00
fnt = ImageFont.truetype(config["font"],config["fontSize"])
2023-02-24 02:11:30 +01:00
text_vign_ind = fetchText(indVign,config)
ind_text_vign = 1
alt_text += fetchAltText(config,config["csvLocation"]+"/"+config["csvAltText"],indVign)+"\n"
if text_vign_ind!=0:
try:
2023-02-24 02:11:30 +01:00
for x in range(len(text_vign_ind[0])):
text_vign = text_vign_ind[1][x]
try:
while text_vign.find('$') != -1:
text_vign = replaceText(text_vign,config)
2021-03-11 01:42:44 +01:00
except AttributeError as err:
print("Problem parsing:")
2023-02-24 02:11:30 +01:00
print(text_vign_ind)
2021-03-11 01:42:44 +01:00
print(err)
quit()
2023-02-24 02:11:30 +01:00
while '$'+str(ind_text_vign) in alt_text:
alt_text = alt_text.replace('$'+str(ind_text_vign),text_vign.replace('@'," "))
ind_text_vign += 1
text_vign = text_vign.replace('@','\n')
2023-02-24 02:11:30 +01:00
addtext.multiline_text((int(text_vign_ind[0][x][0]),int(text_vign_ind[0][x][1])),text_vign,fill="#000000",font=fnt,align="center")
text_vign = ""
except TypeError:
print("Problem finding text for:")
print(indVign)
quit()
obj_list = addThing(indVign,config)
if obj_list!=0:
for obj in obj_list:
if obj[0] == 'R':
objImg = Image.open(config["imagesLocation"]+"/"+prevObj[0])
else:
prevObj = obj
objImg = Image.open(config["imagesLocation"]+"/"+obj[0])
try:
vign.paste(objImg,(int(obj[1]),int(obj[2])),objImg)
except ValueError:
vign.paste(objImg,(int(obj[1]),int(obj[2])))
2023-02-24 02:11:30 +01:00
if "$0" in alt_text:
alt_text = alt_text.replace("$0",fetchAltText(config,config["csvLocation"]+"/"+config["csvAltText"],obj_list[0][0])+" ")
strip.append(vign)
except FileNotFoundError:
pass
image = Image.new('RGBA',(config["xSize"],config["ySize"]))
xshift = yshift = 0
pprow = config["panelsPerRow"]
for vign in strip:
image.paste(vign,(xshift,yshift))
pprow -= 1
if pprow > 0:
xshift += config["panelLength"]
else:
xshift = 0
yshift += config["panelHeight"]
pprow = config["panelsPerRow"]
2021-05-11 15:04:08 +02:00
ImageDraw.Draw(image).rectangle([0,0,config["xSize"]-1,config["ySize"]-1], fill=None, outline="black", width=1)
2023-02-24 02:11:30 +01:00
return image,alt_text
2019-09-09 17:32:07 +02:00
2023-02-24 02:11:30 +01:00
def createStrip(config,specialPlatform="",altTextRequested=False):
"""Create strip and save it, if altTextRequested is True then returns also the alt text
createStrip(str path/filename)"""
2019-09-19 01:59:13 +02:00
try:
story = fetchVign(config)
2023-02-24 02:11:30 +01:00
finalStrip,altText = writeStrip(story,config)
if specialPlatform == "android":
2019-12-23 17:50:59 +01:00
return finalStrip
else:
finalStrip.save(config["saveLocation"]+config["filename"])
2023-02-24 02:11:30 +01:00
if altTextRequested:
return 0,altText
else:
return 0
2019-09-19 01:59:13 +02:00
except Exception as err:
return err
def readConfig(profile=False,platform=False):
"""Read configuration file"""
try:
with open(fileDir+"/config.json") as f:
config = json.load(f)
except IOError:
print("config.json not found")
return False
if not(profile):
profile = config["defaultProfile"]
else:
profile = profile[0]
try:
checkProfile = config[profile]
except KeyError:
print("Profile "+profile+" not found")
profile = config["defaultProfile"]
saveLocation = checkLocal(config[profile]["saveLocation"])
imagesLocation = checkLocal(config[profile]["imagesLocation"])
csvLocation = checkLocal(config[profile]["csvLocation"])
csvTree = config[profile]["csvTree"]
csvSpeech = config[profile]["csvSpeech"]
csvSubs = config[profile]["csvSubs"]
csvObj = config[profile]["csvObj"]
2023-02-24 02:11:30 +01:00
csvAltText = config[profile]["csvAltText"]
font = checkLocal(config[profile]["font"])
2021-03-13 18:57:12 +01:00
fontSize = int((config[profile]["fontSize"]))
xSize = config[profile]["xSize"]
ySize = config[profile]["ySize"]
panelLength = config[profile]["panelLength"]
panelHeight = config[profile]["panelHeight"]
pprow = config[profile]["panelsPerRow"]
if platform:
token = checkLocal(config[profile][platform]["token"])
filename = checkLocal(config[profile][platform]["filename"])
try:
text = config[profile][platform]["text"]
except KeyError:
2020-12-29 02:19:51 +01:00
text = False
return {"saveLocation":saveLocation,"imagesLocation":imagesLocation,"csvLocation":csvLocation,"fontSize":fontSize,"font":font,"token":token,"filename":filename,"xSize":xSize,"ySize":ySize,"panelLength":panelLength,"panelHeight":panelHeight,"csvTree":csvTree,"csvSpeech":csvSpeech,"csvSubs":csvSubs,"csvObj":csvObj,"csvAltText":csvAltText,"text":text,"panelsPerRow":pprow}
filename = config[profile]["filename"]
return {"saveLocation":saveLocation,"imagesLocation":imagesLocation,"csvLocation":csvLocation,"fontSize":fontSize,"font":font,"filename":filename,"xSize":xSize,"ySize":ySize,"panelLength":panelLength,"panelHeight":panelHeight,"csvTree":csvTree,"csvSpeech":csvSpeech,"csvSubs":csvSubs,"csvObj":csvObj,"csvAltText":csvAltText,"panelsPerRow":pprow}
def checkLocal(directory):
"""Checks if it's a relative or absolute path"""
if directory[0] == ".":
return fileDir + directory[1:]
else:
return directory
2019-09-09 17:32:07 +02:00
if __name__ == "__main__":
2020-02-28 17:34:49 +01:00
import argparse
2020-02-28 17:34:49 +01:00
parser = argparse.ArgumentParser()
parser.add_argument('-s','--story',metavar='story',default='',nargs=4,help='story = image file name')
2021-05-10 14:21:23 +02:00
parser.add_argument('-a','--a4',default=False,action='store_true',help='print on an A4 in PDF, needs -o output, disables -x xsize')
parser.add_argument('-m','--multiple',metavar='multiple',default=[1],nargs=1,type=int,help='multiple output (int >0), if no output -o specified, it just tests the stories')
parser.add_argument('-x','--xsize',metavar='xsize',default=0,type=int,nargs=1,help='output image width')
parser.add_argument('-y','--ysize',metavar='ysize',default=0,type=int,nargs=1,help='output image height')
parser.add_argument('-p','--profile',metavar='profile',default="",type=str,nargs=1,help='select a profile registered in config.json, if it doesn\'t exist it will use the default one')
parser.add_argument('-o','--output',metavar='output',const=True,default=False,nargs="?",help='output file, if name not specified, default path will be used')
parser.add_argument('-r','--pprows',metavar='panelsPerRow',default=4,type=int,nargs=1,help='number of panels per row, default is 4')
2020-02-28 17:34:49 +01:00
args = parser.parse_args()
if args.multiple[0] <= 0: #Wrong multiple choice
2020-12-01 00:17:55 +01:00
quit()
config = readConfig(profile=args.profile)
2021-05-10 14:21:23 +02:00
if args.output == True: #Output on but no filename specified
fileName = config["saveLocation"]+config["filename"]
elif type(args.output) == str: #Output specified
fileName = args.output
2021-05-10 14:21:23 +02:00
pdfs = list() #Prepare a list for the PDF
for ist in range(0,args.multiple[0]):
if (args.story == ''): #No story specified
story = fetchVign(config)
2020-12-01 00:17:55 +01:00
else:
story = [] #Story specified
2020-12-01 00:17:55 +01:00
for x in args.story:
story.append(x)
2023-02-24 02:11:30 +01:00
finalStrip,alt_text = writeStrip(story,config)
2021-05-10 14:21:23 +02:00
if args.a4: #Prints a PDF
finalStrip = finalStrip.resize((2249,516))
pdfs.append(finalStrip)
else:
if args.xsize != 0: #Resize specified
finalStrip = finalStrip.resize((args.xsize[0],int(args.xsize[0]/2400*500)))
2021-05-10 14:21:23 +02:00
if args.multiple[0] == 1: #No multiple selected
if args.output == False:
finalStrip.show()
2023-02-24 02:11:30 +01:00
print(alt_text)
2021-05-10 14:21:23 +02:00
else:
finalStrip.save(fileName)
else: #Multiple selected
if args.output == False:
2023-02-24 02:11:30 +01:00
print(story,alt_text)
2021-05-10 14:21:23 +02:00
else:
2021-05-10 14:55:56 +02:00
finalStrip.save(fileName + str(ist).zfill(3) + ".png")
2021-05-10 14:21:23 +02:00
if args.a4:
ypos = 100
nopage = 0
if args.output == False:
print("Output not specified")
quit()
2021-05-10 14:21:23 +02:00
pagePdf = list()
2021-05-11 15:00:32 +02:00
for pag in range(0,int((args.multiple[0]-1)/6+1)):
2021-05-11 15:04:08 +02:00
image = Image.new('RGB',(2479,3508),(255,255,255))
fnt = ImageFont.truetype(config["font"],config["fontSize"])
ImageDraw.Draw(image).text((2479 - 500, 3508 - 200),"https://github.com/oloturia/fumcaso",fill="black",font=fnt)
pagePdf.append(image)
2021-05-10 14:21:23 +02:00
for ist,strip_num in enumerate(range(0,args.multiple[0])):
pagePdf[nopage].paste(pdfs[strip_num],box=(110,ypos))
2021-05-11 15:03:02 +02:00
ypos += 516 + 20
2021-05-10 14:21:23 +02:00
if ypos > 3508-569:
ypos = 100
nopage += 1
if fileName[len(fileName)-4:] != ".pdf":
fileName += ".pdf"
2021-05-11 15:23:53 +02:00
pagePdf[0].save(fileName, resolution=300, save_all=True, append_images=pagePdf[1:])