~widelands-dev/widelands/bug-1656671

5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
1
#!/usr/bin/env python
5060 by Timo Wingender
Add a new script to crop animations
2
# -*- coding: utf-8 -*-
3
4
# Copyright (C) 2010 by the Widelands Development Team
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
#
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
12
# This script takes one or more conf files on the command line.
13
# It reads [idle] and [working] sections from these files and
5060 by Timo Wingender
Add a new script to crop animations
14
# take the pics= and playercolor= lines from these sections.
15
#
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
16
#
17
#
5060 by Timo Wingender
Add a new script to crop animations
18
#
19
20
import os
21
import re
22
import sys
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
23
5060 by Timo Wingender
Add a new script to crop animations
24
from PIL import Image
25
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
26
"""
27
This script takes a list of conf files as arguments and crops
28
the correponding animations to their proper size
29
30
usage:
31
    find -type f -name conf -exec crop_animation.py {} \;
32
"""
33
8201 by GunChleoc
Fetched translations and updated catalogues.
34
5060 by Timo Wingender
Add a new script to crop animations
35
def crop_images(basepath, section):
8201 by GunChleoc
Fetched translations and updated catalogues.
36
    """crop_images does the work of actually cropping the animation pictures
37
    from a conf section.
38
39
    The first parameter basepath is the directory in which the conf file
40
    was.  The second parameter section is a dictionary with contains the
41
    important contents of the section from the conf file
42
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
43
    """
44
    # two empty lists. The first for the animation pictures
8201 by GunChleoc
Fetched translations and updated catalogues.
45
    list = []
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
46
    # the second one for the player color masks
8201 by GunChleoc
Fetched translations and updated catalogues.
47
    list_pc = []
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
48
8201 by GunChleoc
Fetched translations and updated catalogues.
49
    basepath = basepath + '/'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
50
51
    if 'pics' in section:
8201 by GunChleoc
Fetched translations and updated catalogues.
52
        filepattern = section['pics']
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
53
    else:
8201 by GunChleoc
Fetched translations and updated catalogues.
54
        filepattern = section['dirpics']
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
55
8201 by GunChleoc
Fetched translations and updated catalogues.
56
    # TODO(sirver): playercolor is never used in the conf files anymore.
57
    # remove this.
58
    use_playercolor = False
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
59
    if 'playercolor' in section and \
8201 by GunChleoc
Fetched translations and updated catalogues.
60
       section['playercolor'].upper().strip() == 'TRUE':
61
        use_playercolor = True
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
62
63
    # replace the placeholders ?? and !! by a .
8201 by GunChleoc
Fetched translations and updated catalogues.
64
    filepattern = filepattern.replace(r".", r"\.")
65
    filepattern = filepattern.replace(r"??", r"[0-9][0-9]")
66
    filepattern = filepattern.replace(r"!!", r"(e|w|sw|se|nw|ne)")
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
67
    # The end of the pattern is the end of the filename
8201 by GunChleoc
Fetched translations and updated catalogues.
68
    filepattern += '$'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
69
70
    # create a pattern for the playercolor masks
8201 by GunChleoc
Fetched translations and updated catalogues.
71
    filepattern_pc = filepattern.rpartition('\.')
72
    filepattern_pc = filepattern_pc[0] + '_pc\\.' + filepattern_pc[2]
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
73
5071 by Timo Wingender
fix another bug in crop animation script: correct the file pattern and make it more robust
74
    # print filepattern
75
    # print filepattern_pc
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
76
77
    for filename in os.listdir(basepath):
78
        if re.match(filepattern, filename):
79
            list.append(filename)
80
        if use_playercolor and re.match(filepattern_pc, filename):
81
            list_pc.append(filename)
82
83
    # Now we have two list which contains the animation pictures and the
84
    # playercolor mask
85
8201 by GunChleoc
Fetched translations and updated catalogues.
86
    # print list
87
    # print list_pc
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
88
8201 by GunChleoc
Fetched translations and updated catalogues.
89
    if len(list) < 1:
90
        return 'error'  # we found no pictures
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
91
92
    # Now open the first picture, get the size and validate the size
8201 by GunChleoc
Fetched translations and updated catalogues.
93
    im = Image.open(basepath + list[0])
94
    size = im.size
95
    if size[0] < 1 or size[1] < 1:
96
        print '*** ERROR ***: image has size 0'
97
        return 'error'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
98
    # Set a first boundingbox to crop away the maximum from the picture
8201 by GunChleoc
Fetched translations and updated catalogues.
99
    crop = [size[0], size[1], 0, 0]
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
100
101
    # Now go through all picture of the animation and get the boundingbox
102
    for file in list:
8201 by GunChleoc
Fetched translations and updated catalogues.
103
        # print basepath+file
104
        im = Image.open(basepath + file)
105
        # im.show()
106
        bb = im.getbbox()
107
        # print "Bounding box for " + file + ": ",
108
        # print bb
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
109
110
        # Here the boundingbox is adjusted. It's only set it to crop away less
111
        # of the picture
8201 by GunChleoc
Fetched translations and updated catalogues.
112
        if bb[0] < crop[0]:
113
            crop[0] = bb[0]
114
        if bb[1] < crop[1]:
115
            crop[1] = bb[1]
116
        if bb[2] > crop[2]:
117
            crop[2] = bb[2]
118
        if bb[3] > crop[3]:
119
            crop[3] = bb[3]
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
120
        # Assure that the size of all images of the animation is the same
8201 by GunChleoc
Fetched translations and updated catalogues.
121
        if im.size != size:
122
            print '*** Error *** Frame size changed', basepath, ' ', file
123
            return 'error'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
124
125
    # Now we have a common boundingbox of all images of the animation
126
8201 by GunChleoc
Fetched translations and updated catalogues.
127
    # print crop,
128
    # print " ",
129
    # print size,
130
    if crop[0] > 0 or crop[1] > 0 or crop[2] < size[0] or crop[3] < size[1]:
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
131
        # We have somethin to crop
8201 by GunChleoc
Fetched translations and updated catalogues.
132
        rect = (crop[0], crop[1], crop[2], crop[3])
133
        print 'crop images', filepattern, filepattern_pc
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
134
135
        # If playercolor was true in the config file add the playercolor masks
136
        # tho the list
137
        if use_playercolor:
138
            list += list_pc
139
8201 by GunChleoc
Fetched translations and updated catalogues.
140
        # print list
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
141
142
        # Now go through all images (include playercolor mask if set) and crop
143
        # them
144
        for file in list:
8201 by GunChleoc
Fetched translations and updated catalogues.
145
            im = Image.open(basepath + file)
146
            # print "crop", basepath+file, " ",im.size, rect
147
            im = im.crop(rect)
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
148
            # Images in paletted mode have to be handled differently. If they
149
            # are saved without the option the transparency is lost
8201 by GunChleoc
Fetched translations and updated catalogues.
150
            if(im.mode == 'P'):
151
                im.save(basepath + file, quality=100, transparency=0)
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
152
            else:
8201 by GunChleoc
Fetched translations and updated catalogues.
153
                im.save(basepath + file, quality=100)
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
154
            # If this function cropped something it returns a tupple containing
155
            # the crop rect
156
        return rect
157
    else:
8201 by GunChleoc
Fetched translations and updated catalogues.
158
        # print "nothing to do for", filepattern, filepattern_pc
159
        return 'unchanged'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
160
161
5060 by Timo Wingender
Add a new script to crop animations
162
def read_conffile(filename):
8201 by GunChleoc
Fetched translations and updated catalogues.
163
    """read_conf reads a configfile and searches for sections which contain
164
    pic= or dirpic=.
165
166
    Such section are added to a list. For every of these sections the
167
    function crop_images() is called. of crop_images did not return
168
    "error" or "unchanged" the hotspot in the conf file is adjusted by
169
    the top and left values of the crop rectangle.  The parameter to
170
    this function is the conf file
171
172
    """
173
    print 'read ' + filename
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
174
175
    # We read the complete file to a list of lines
176
    f = open(filename)
177
    lines = f.readlines()
178
    f.close()
179
8201 by GunChleoc
Fetched translations and updated catalogues.
180
    basepath = os.path.split(filename)
181
    basepath = basepath[0]
182
    # print basepath
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
183
184
    # section_begin track where the current section began
8201 by GunChleoc
Fetched translations and updated catalogues.
185
    section_begin = 0
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
186
    # insection a list of matching section is saved
8201 by GunChleoc
Fetched translations and updated catalogues.
187
    sections = []
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
188
    # i counts the lines
8201 by GunChleoc
Fetched translations and updated catalogues.
189
    i = 0
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
190
    # section is a dictionary where the contents of the current section are
191
    # stored
8201 by GunChleoc
Fetched translations and updated catalogues.
192
    section = {}
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
193
194
    # First go through all lines and identify relevant sections
195
    for line in lines:
8201 by GunChleoc
Fetched translations and updated catalogues.
196
        line = line.split('#')
197
        line = line[0].strip(' \r\n\t')
198
        if re.match(r"\[[a-zA-Z0-9]*\]", line):
199
            # print "*** section begin"
200
            if 'pics' in section or 'dirpics' in section:
201
                sections.append((section_begin, i - 1, section))
202
            section_begin = i
203
            section = {'name': 'test'}
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
204
        if re.match(r"(pics=|dirpics=|hotspot=|playercolor=)", line):
8201 by GunChleoc
Fetched translations and updated catalogues.
205
            keyval = line.split('=')
206
            section[keyval[0]] = keyval[1]
207
        i += 1
208
    if 'pics' in section or 'dirpics' in section:
209
        pic_section = False
210
        sections.append((section_begin, i - 1, section))
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
211
212
    # Now use the information gatherd above to crop the images
213
    for section in sections:
8201 by GunChleoc
Fetched translations and updated catalogues.
214
        # print section
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
215
        # Crop the animation ...
216
        ret = crop_images(basepath, section[2])
217
218
        # See if we cropped images
8201 by GunChleoc
Fetched translations and updated catalogues.
219
        if ret != 'error' and ret != 'unchanged':
220
            if (ret[0] > 0 or ret[1] > 0) and 'hotspot' in section[2]:
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
221
                # Somethin was cropped from top or left, so adjust the hotspot
8201 by GunChleoc
Fetched translations and updated catalogues.
222
                print 'change hotspot', ret
223
                oldhs = section[2]['hotspot'].split(' ')
224
                newhs = (int(oldhs[0]) - ret[0], int(oldhs[1]) - ret[1])
225
                # print oldhs, newhs
5066 by Timo Wingender
small fix to crop animation script: now adjust all hotspots for an animation
226
                # search all section which use this animation
227
                for sec in sections:
8201 by GunChleoc
Fetched translations and updated catalogues.
228
                    if 'pics' in section[2]:
229
                        fname = section[2]['pics']
5066 by Timo Wingender
small fix to crop animation script: now adjust all hotspots for an animation
230
                    else:
8201 by GunChleoc
Fetched translations and updated catalogues.
231
                        fname = section[2]['dirpics']
232
                    if ('pics' in sec[2] and sec[2]['pics'] == fname) or \
233
                       ('dirpics' in sec[2] and sec[2]['dirpics'] == fname):
6509.1.11 by Holger Rapp
Removed playercolor key. Use playercolor when there are _pc.png files for this animation automatically.
234
                        # Simply go through the lines of the section and
235
                        # search for hotspot= if found replace the line. It
5066 by Timo Wingender
small fix to crop animation script: now adjust all hotspots for an animation
236
                        # will be written to the conf file a the end
8201 by GunChleoc
Fetched translations and updated catalogues.
237
                        for i in range(sec[0], sec[1] + 1):
238
                            # print i,
239
                            # print lines[i],
5066 by Timo Wingender
small fix to crop animation script: now adjust all hotspots for an animation
240
                            if re.match(r"hotspot=", lines[i]):
8201 by GunChleoc
Fetched translations and updated catalogues.
241
                                lines[i] = 'hotspot=%u %u\n' % (
242
                                    newhs[0], newhs[1])
243
                                # print i, lines[i],
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
244
245
    # Now we write back the conf file from our list of lines
8201 by GunChleoc
Fetched translations and updated catalogues.
246
    f = open(filename, 'w')
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
247
    f.writelines(lines)
248
    f.close()
249
250
251
def main():
8201 by GunChleoc
Fetched translations and updated catalogues.
252
    """This is the main function.
253
254
    It calls read_conffile() for every file given to this program
255
256
    """
257
    if len(sys.argv) <= 1:
258
        print 'Usage: ' + sys.argv[0] + ' conf-files'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
259
        sys.exit()
260
261
    for file in sys.argv[1:]:
262
        if os.path.isfile(file):
263
            read_conffile(file)
264
        else:
8201 by GunChleoc
Fetched translations and updated catalogues.
265
            print '*** WARNING ***: ' + file + ' is not a file'
5061 by Holger Rapp
Cleaned the new crop animation script up a bit. Made it more conform to PEP8
266
267
if __name__ == '__main__':
268
    main()