
#!/usr/bin/env python3

################################################
# Extract contents from Open Office Sheets columns and convert it to text in image arrays. Can rescale the input image with command line arguments.


# Created by A.Gordillo-Guerrero (anto@unex.es), September , 2023.
# University of Extremadura. Smart Open Lab.
# Released into the public domain.

################################################

text = 'This program read data from a Libre Office, open document, sheet and convert it to centered text, with a given font, in a matrix from a base image file.'

print(text)

# To use libre office and excel sheets
import pyexcel

# To modify and create images with texts
from PIL import Image, ImageFont, ImageDraw

#To read arguments from command line
import argparse


################################################
# Reading arguments from the command line
################################################

# Initiate the parser with a description
parser = argparse.ArgumentParser(description=text)

parser.add_argument("--outWidth", "-ow", help="Width in mm of the output image")
parser.add_argument("--outHeight", "-oh", help="Height in mm of the output image")
parser.add_argument("--inWidth", "-iw", help="Width in mm for the scaled input image")
parser.add_argument("--inHeight", "-ih", help="Height in mm of the scaled input image")
parser.add_argument("--imagefile", "-i", help="Input image file name")
parser.add_argument("--fontfile", "-f", help="Truetype font file name")

parser.parse_args()

args = parser.parse_args()

if args.outWidth:
    print("Width in mm of the output image: %s mm" % args.outWidth)
if args.outHeight:
    print("Height in mm of the output image: %s mm" % args.outHeight)
if args.inWidth:
    print("Width in mm of rescaled base image: %s mm" % args.inWidth)
if args.inHeight:
    print("Height in mm of the rescaled base image: %s mm" % args.inHeight)
if args.imagefile:
    print("Input image file name: %s" % args.imagefile)
if args.fontfile:
    print("Truetype font file name: %s\n" % args.fontfile)

    
################################################
# Obtaining data from sheet's first column
################################################

from pyexcel._compact import OrderedDict

# Reading the table as an ordered dictionary
my_dict = pyexcel.get_dict(file_name="tabla_nombres_1.ods", name_columns_by_row=0)

# Some test...
# Printing in command line the reades lines
# for i in range (1, len(my_dict["Nombre"])):
#    print(my_dict["Nombre"][i])
  
#print only the first column (names)
#my_dict["Nombre"][0]



################################################
# Defining new canvas size
################################################

#conversion from mm to pixels (1 mm = 3.7795275591 pixel )
canvasPixwidth  = int(3.7795*int(args.outWidth))
canvasPixheight = int(3.7795*int(args.outHeight))
canvas=Image.new('RGBA', (canvasPixwidth, canvasPixheight), 'white')
#canvas.show()

#loading base image file
imBase = Image.open(args.imagefile)
#print(imOriginal.format, imOriginal.size, imOriginal.mode)
#imBase.show()

#putting image base in white background
imBaseWhiteBack = Image.new("RGBA", imBase.size, "WHITE") # Create a white rgba background
imBaseWhiteBack.paste(imBase, (0, 0), imBase)              # Paste the image on the background. 
imBaseWhiteBack.convert('RGB')
#imBaseWhiteBack.show()

# Rescaling base image according to input parameters
baseRescaledWidth = int(3.7795*int(args.inWidth))
baseRescaledHeight = int(3.7795*int(args.inHeight))
imBaseResized = imBaseWhiteBack.resize((baseRescaledWidth ,baseRescaledHeight))

##print(imBase.format, imBase.size, imBase.mode)
#baseWidth, baseHeight = imBase.size
##print(imBase.format, imBase.size, imBase.mode)

# To add 2D graphics in an image call draw Method
drawBase = ImageDraw.Draw(imBase)


    
#########################################################    
# Making a 2D array of images. Filling the matrix by rows
#########################################################    

#Defining array of images

#Defining small offset in pixels between images to ease laser cuts
offset=4 #pixels

#How many images can I put in a row with an offset?
nImByRow=int(canvasPixwidth/(baseRescaledWidth+offset))
print("We can put %s images per row, rounding down" % nImByRow)

#How many images can I put in a column with an offset?
nImByCol=int(canvasPixheight/(baseRescaledHeight+offset))
print("We can put %s images per column, rounding down" % nImByCol)

print("Making a total of %s possible elements in total,\n" % int(nImByCol*nImByRow))
print("Our data sheet has %s elements. \n" % len(my_dict["Nombre"]))
# Do we have enough room for the elements in the table?

if (len(my_dict["Nombre"])>int(nImByCol*nImByRow)):
    print("We do not have enough room for all the table elements. Exiting...\n")
    exit()
else:
    print("We have %s remaining positions in our canvas.\n" % int( int(nImByCol*nImByRow)- len(my_dict["Nombre"]) ) )

    
for i in range (len(my_dict["Nombre"])):
    #row identification
    irow= i % nImByRow
#    print ("We are in row %s" % irow)
    #column identification
    icol= i // nImByRow
#    print ("We are in column %s" % icol)
    # putting one base image in the correct location
    canvas.paste( imBaseResized, ( int( ( baseRescaledWidth + offset )*irow ) , int( ( baseRescaledHeight +offset) *icol ) ) ) 
    #putting its corresponding text
    draw = ImageDraw.Draw(canvas)
    # Putting person name
    # obtaining this text size
    TTfont = ImageFont.truetype(args.fontfile, 24)
    textWidth, textHeight = draw.textsize(my_dict["Nombre"][i], font=TTfont)
    offset_height=15
    thisTextCenterX=int((baseRescaledWidth  + offset)*irow+(baseRescaledWidth-textWidth)/2)
    thisTextCenterY=int((baseRescaledHeight + offset)*icol+(baseRescaledHeight-textHeight)/2)+offset_height
    draw.text((thisTextCenterX, thisTextCenterY), my_dict["Nombre"][i], font=TTfont,fill=(0,0,0,255) ) #fill in black
    
    # Putting institution name
    TTfont = ImageFont.truetype(args.fontfile, 32)
    textWidth, textHeight = draw.textsize(my_dict["Institucion"][i], font=TTfont)
    offset_height=50
    thisTextCenterX=int((baseRescaledWidth  + offset)*irow+(baseRescaledWidth-textWidth)/2)
    thisTextCenterY=int((baseRescaledHeight + offset)*icol+(baseRescaledHeight-textHeight)/2)+offset_height
    draw.text((thisTextCenterX, thisTextCenterY), my_dict["Institucion"][i], font=TTfont,fill=(0,0,0,255) ) #fill in black
    
#Some test...
#canvas.text((100, 100), "Mi carro me lo robaron", font=TTfont)
#Im.text((15,15*j), my_dict["Nombre"][j], (0,0,0), font=mf)
#canvas.paste(imBaseWhiteBack, (int(0), int(0)))#canvas.paste(imBaseWhiteBack, (300, 300))


# saving to .png to retain transparent background
canvas.save('image_array_ouput.png')

# saving to .jpg
canvas=canvas.convert('RGB')
# saving the label created label array
canvas.save('image_array_ouput.jpg')

print("Array done, showing result after file save. Exiting...")

canvas.show()

# Add Text to an image
#for j in range (1, len(my_dict["Nombre"])):

    # Putting text in black colour
#    Im.text((15,15*j), my_dict["Nombre"][j], (0,0,0), font=mf)

    #Im.text((15,15*j), my_dict["Nombre"][i], (255,255,0), font=mf)

    #    print(my_dict["Nombre"][i])


# Display edited image on which we have added the text
#imBase.show()

# Save the image on which we have added the text
#imBase.save("mm.png")



#conversion from mm to pixels (1 mm = 3.7795275591 pixel )

##################################
#define new image for A4 size

# resolution = 72 dpi
#imA4=Image.new('RGBA', (595, 842), 'white')

# resolution = 300 dpi
#A4pixwidth=2480
#A4pixlength=3508
#imA4=Image.new('RGBA', (A4pixwidth, A4pixlength), 'white')

#loading image file
#imOriginal = Image.open(args.file)
#print(imOriginal.format, imOriginal.size, imOriginal.mode)

#converting text to integer numbers
#cols_int=int(args.cols)
#rows_int=int(args.rows)


#defining new image size
#imResized = imOriginal.resize((int(A4pixwidth / cols_int), int(A4pixlength / rows_int)))
#imResized = imOriginal.resize((200, 200))

#making array of images
#for i in range (int(cols_int)):
#  for j in range (int(rows_int)):
#    imA4.paste(imResized, (int(A4pixwidth / cols_int *i), int(A4pixlength / rows_int * j)))

##imA4.paste(imResized, (0, 0))

# saving to .png to retain transparent background
#imA4.save('labelarray_ouput.png')

# saving to .jpg
#imA4=imA4.convert('RGB')
# saving the label created label array
#imA4.save('labelarray_ouput.jpg')

#print("Array done, showing result after file save. Exiting...")
#imOriginal.show()

#imA4.show()




#my_dict.get("Nombre")
#my_dict.items()

#import pyexcel as pe

#from pyexcel.ext import ods

#sheet = pe.get_book(file_name="tabla_nombres_1.ods")

#sheet

#print(json.dumps(sheet.to_array()))

#sheet = pyexcel.get_sheet(file_name="tabla_nombres_1.ods", name_columns_by_row=0)

#sheet.to_dict()

#data = get_data("tabla_nombres_1.ods")
#import json

#json_data = json.dumps(data)

#print(json.dumps(data)[10])

#data_list = json.load(data)
#print(type(data_list))
#print(data_list)


                #print(json.dumps(data))


###################################################
#### Reading arguments via command line ###########
###################################################

#import argparse
# Initiate the parser with a description
#parser = argparse.ArgumentParser(description=text)

#parser.add_argument("--rows", "-r", help="Number of rows")
#parser.add_argument("--cols", "-c", help="Number of columns")
#parser.add_argument("--file", "-f", help="Input image file name")

#parser.parse_args()


# Read arguments from the command line
#args = parser.parse_args()

#if args.rows:
#    print("Number of rows to do: %s" % args.rows)
#if args.cols:
#    print("Number of cols to do: %s" % args.cols)
#if args.file:
#    print("Input file name: %s" % args.file)



##################################
#define new image for A4 size

# resolution = 72 dpi
#imA4=Image.new('RGBA', (595, 842), 'white')

# resolution = 300 dpi
#A4pixwidth=2480
#A4pixlength=3508
#imA4=Image.new('RGBA', (A4pixwidth, A4pixlength), 'white')

#loading image file
#imOriginal = Image.open(args.file)
#print(imOriginal.format, imOriginal.size, imOriginal.mode)

#converting text to integer numbers
#cols_int=int(args.cols)
#rows_int=int(args.rows)


#defining new image size
#imResized = imOriginal.resize((int(A4pixwidth / cols_int), int(A4pixlength / rows_int)))
#imResized = imOriginal.resize((200, 200))

#making array of images
#for i in range (int(cols_int)):
#  for j in range (int(rows_int)):
#    imA4.paste(imResized, (int(A4pixwidth / cols_int *i), int(A4pixlength / rows_int * j)))

##imA4.paste(imResized, (0, 0))

# saving to .png to retain transparent background
#imA4.save('labelarray_ouput.png')

# saving to .jpg
#imA4=imA4.convert('RGB')
# saving the label created label array
#imA4.save('labelarray_ouput.jpg')

#print("Array done, showing result after file save. Exiting...")
#imOriginal.show()

#imA4.show()
