blob: 6b435aa90e1cd261722d3e445fe90ee06d19f11b [file] [log] [blame]
Elliott Hughes692941b2016-04-21 14:26:14 -07001#!/usr/bin/env python
Doug Zongker5120c9f2014-03-11 12:39:33 -07002# Copyright (C) 2014 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Tao Baob723f4f2015-12-11 15:18:51 -080016"""
Elliott Hughes692941b2016-04-21 14:26:14 -070017Script to take a set of frames (PNG files) for a recovery animation
18and turn it into a single output image which contains the input frames
19interlaced by row. Run with the names of all the input frames on the
20command line, in order, followed by the name of the output file.
Tao Baob723f4f2015-12-11 15:18:51 -080021"""
22
23from __future__ import print_function
24
25import argparse
Elliott Hughes692941b2016-04-21 14:26:14 -070026import os.path
Doug Zongker5120c9f2014-03-11 12:39:33 -070027import sys
28try:
29 import Image
30 import PngImagePlugin
31except ImportError:
Tao Baob723f4f2015-12-11 15:18:51 -080032 print("This script requires the Python Imaging Library to be installed.")
Doug Zongker5120c9f2014-03-11 12:39:33 -070033 sys.exit(1)
34
Doug Zongker5120c9f2014-03-11 12:39:33 -070035
Elliott Hughes692941b2016-04-21 14:26:14 -070036def interlace(output, inputs):
Tao Baob723f4f2015-12-11 15:18:51 -080037 frames = [Image.open(fn).convert("RGB") for fn in inputs]
38 assert len(frames) > 0, "Must have at least one input frame."
39 sizes = set()
40 for fr in frames:
41 sizes.add(fr.size)
Doug Zongker5120c9f2014-03-11 12:39:33 -070042
Tao Baob723f4f2015-12-11 15:18:51 -080043 assert len(sizes) == 1, "All input images must have the same size."
44 w, h = sizes.pop()
45 N = len(frames)
Doug Zongker5120c9f2014-03-11 12:39:33 -070046
Tao Baob723f4f2015-12-11 15:18:51 -080047 out = Image.new("RGB", (w, h*N))
48 for j in range(h):
49 for i in range(w):
50 for fn, f in enumerate(frames):
51 out.putpixel((i, j*N+fn), f.getpixel((i, j)))
Doug Zongker5120c9f2014-03-11 12:39:33 -070052
Tao Baob723f4f2015-12-11 15:18:51 -080053 # When loading this image, the graphics library expects to find a text
54 # chunk that specifies how many frames this animation represents. If
55 # you post-process the output of this script with some kind of
56 # optimizer tool (eg pngcrush or zopflipng) make sure that your
57 # optimizer preserves this text chunk.
Doug Zongker5120c9f2014-03-11 12:39:33 -070058
Tao Baob723f4f2015-12-11 15:18:51 -080059 meta = PngImagePlugin.PngInfo()
60 meta.add_text("Frames", str(N))
Tao Baob723f4f2015-12-11 15:18:51 -080061
62 out.save(output, pnginfo=meta)
63
64
Elliott Hughes692941b2016-04-21 14:26:14 -070065def deinterlace(output, input):
66 # Truncate the output filename extension if it's '.png'.
67 if os.path.splitext(output)[1].lower() == '.png':
68 output = output[:-4]
69
70 img2 = Image.open(input)
71 print(img2.mode)
72 palette = img2.getpalette()
73 img = img2.convert("RGB")
74 num_frames = int(img.info.get('Frames', 1))
75 print('Found %d frames in %s.' % (num_frames, input))
76 assert num_frames > 0, 'Invalid Frames meta.'
77
78 # palette = img.getpalette()
79 print(palette)
80
81 width, height = img.size
82 height /= num_frames
83 for k in range(num_frames):
84 out = Image.new('RGB', (width, height))
85 out.info = img.info
86 for i in range(width):
87 for j in range(height):
88 out.putpixel((i, j), img.getpixel((i, j * num_frames + k)))
89 # out.putpalette(img.getpalette(), rawmode='RGB')
90 out2 = out.convert(mode='P', palette=palette)
91 #out2 = out
92 print(out2.mode)
93 # out2.putpalette(palette)
94 filename = '%s%02d.png' % (output, k)
95 out2.save(filename)
96 print('Frame %d written to %s.' % (k, filename))
97
98
Tao Baob723f4f2015-12-11 15:18:51 -080099def main(argv):
Elliott Hughes692941b2016-04-21 14:26:14 -0700100 parser = argparse.ArgumentParser(description='Parse')
101 parser.add_argument('--deinterlace', '-d', action='store_true')
Tao Baob723f4f2015-12-11 15:18:51 -0800102 parser.add_argument('--output', '-o', required=True)
103 parser.add_argument('input', nargs='+')
104 args = parser.parse_args(argv)
105
Elliott Hughes692941b2016-04-21 14:26:14 -0700106 if args.deinterlace:
107 # args.input is a list, and we only process the first when deinterlacing.
108 deinterlace(args.output, args.input[0])
109 else:
110 interlace(args.output, args.input)
Tao Baob723f4f2015-12-11 15:18:51 -0800111
112
113if __name__ == '__main__':
114 main(sys.argv[1:])