Saturday, July 12, 2014

49. Using an Atlas

An atlas can be used, by putting atlas, pathname, and then the name without extension, where an image filename is required.




This is the first half of program to create Atlas, and the most important. The glob module is used which calls other modules. In the glob.glob, we write the filenames it should search for. These correspond to 26 letters of size 64 by 64 in Set 1. Besides the letters, the space character is inserted. The way to create space, is to open the included vector graphic in Inkspace or similar program and deleting the contents and exporting as 64 by 64 png. Then, the letters atlas is created using the create() function.


# create_atlas.py

from __future__ import print_function
import atlas
import sys, glob

filenames = glob.glob('*Set_1*64x64.png')+['sp.png']

ret = atlas.create('letters', filenames, 512)

if not ret:
    print('Error while creating atlas!')
    sys.exit(1)

fn, meta = ret
print('Atlas created at', fn)
print('%d image%s created' % (len(meta),
        's' if len(meta) > 1 else ''))



The last 2 files are the files created by create_atlas. The input images are not shown since they are not needed anymore.




These are the imports. A module split_lines is needed to split a large string into many lines. An implementation is included on blogspot. The string standard library is included, so we can use the constants, like the 26 letters, rather than typing each. The other imports are similar to the previous Example.


# split_lines.py

from __future__ import print_function

def split_lines(S,I,J):
    'Split String S into 2J lines with each line 2I characters or less'
    Line=['']*2*J
    Strs=S.split(' ')
    stop = 0
    for i in range(2*J):
        start = stop
        try: Sp = len(Strs[start])
        except IndexError: break
        while (Sp<=2*I):
            stop = stop + 1
            try: Sp = Sp + 1 + len(Strs[stop])
            except IndexError: break
        Line[i] = ' '.join(Strs[start:stop])
    return Line
        

if __name__ == '__main__':
    I = 5
    J = 3
    S='1 2 3, 4 5 6. 7 8, 9: 10. 11 12 13 14 15 16g 17h 18i 19j'
    Line = split_lines(S,I,J)
    for i in range(len(Line)):
        print('Line[{}] = {}'.format(i,Line[i]))
        print('len = {}\n'.format(len(Line[i])))
    
    



This is the string to output. Note, this is only one string, even though it is on many lines. Next, the constants, I and J, are defined. The number of maximum characters in a line is 2I. The maximum number of lines is 2J. It is possible the string will not fit into 2J lines, and thus, we will only see a partial string in the output. The split_lines module is used to create LINES which is a list of length 2J.




Next, we form the 27 image strings. These correspond to the 26 letters, and a space character. In the template, we start with atlas://, then the relative path, then the name without an extension. The coordinates, ORIG_X, and ORIG_Y, refer to the lower-left of the region where text will be displayed.




The Letter class has a StringProperty which will be used to hold the image string. Next, in the root there is only 1 function, write_string. It uses an integer variable to iterate over the 2J lines. Next for each line, we iterate over all the individual characters in the particular line.




For each character in a line, we create a Letter instance. Then its StringProperty is set to a letter or space. Notice, if we have a comma or period it will be treated as a space. Then, the x and y positions of the Letter are set, as some offset from the ORIG_X and_ORIG Y coordinates. Finally the Letter instance is added to root widget.




In the app, we schedule the write_string function to take place in half a second.


# ex49.py

from split_lines import split_lines
import string
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.app import App
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.clock import Clock

STRING = ('Four score and seven years ago '
          'our fathers brought forth on this continent, '
          'a new nation, conceived in Liberty, and '
          'dedicated to the proposition that all men '
          'are created equal.')
I,J = 10,6
LINES = split_lines(STRING,I,J)
LETTERS={}
LETT_TEMPLATE = ('atlas://Letter_Blocks_01/'
                'letters/Letter_Blocks_01_Set_1_{}_64x64')
for char in string.ascii_uppercase:
    exec("LETTERS['{}'] = LETT_TEMPLATE.format('{}')".format(char,char))

LETTERS['SP'] = 'atlas://Letter_Blocks_01/letters/sp'

ORIG_X = Window.width/2-I*32
ORIG_Y = Window.height/2-J*32

class Letter(Image):
    fname = StringProperty()

class Ex49(Widget):
    def write_string(self,dt):
        for line in range(2*J):
            for i,lett in enumerate(list(LINES[line])):
                letter = Letter()
                if lett.isalpha():
                    letter.fname = LETTERS[lett.upper()]
                else: letter.fname = LETTERS['SP']
                letter.x = ORIG_X+32*i
                letter.y = ORIG_Y+32*(2*J-1-line)
                self.add_widget(letter)
       
class Ex49App(App):
    def build(self):
        ex49=Ex49()
        Clock.schedule_once(ex49.write_string,.5)
        return ex49

if __name__=='__main__':
    Ex49App().run()



In the kv file, each letter source is set to image StringProperty. Also the size is set to 32 by 32. Since the image is 64 by 64, it is scaled by 50%.




Finally, we set a gray background color.


# ex49.kv

<Letter>:
    source: root.fname
    size: 32, 32
        
<Ex49>:
    canvas:
        Color:
            rgb: .75,.75,.75
        Rectangle:
            size: self.size
            pos: self.pos
    
        



In this result, we can see the string has been written, over many lines. Also it can be seen, that the commas, and periods, are missing, and replaced with spaces. If we had the images of the two symbols, we can easily write more conditions.




3 comments:

  1. Python:

    Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.

    https://www.emexotechnologies.com/online-courses/python-training-in-electronic-city/

    ReplyDelete
  2. Good Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.

    Python Training in electronic city

    ReplyDelete
  3. Thanks a lot for sharing this with all of us you actually know what you are talking about! Bookmarked. Please also visit my site =). We could have a link exchange arrangement between us! apple service provider berlin


    ReplyDelete