main()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 1
c 4
b 0
f 0
dl 0
loc 15
rs 9.4285
1
"""
2
A command-line tool for combining multiple image files into
3
POV-Ray density file (DF3).
4
5
"""
6
7
from __future__ import print_function
8
import sys
9
import argparse
10
import struct
11
import glob
12
13
from PIL import Image
14
15
from df3tools.exceptions import Df3Exception
16
17
18
def to_big_endian(value):
19
    """ Convert integer to big-endian byte string """
20
    return struct.pack(">L", value)
21
22
23
def detect_size(prefix, silent):
24
    """
25
    Detect image size and number of layers.
26
27
    :param prefix: input files prefix
28
    :param silent: suppress output (info messages, progress etc.)
29
30
    :returns: Tuple with sizes.
31
32
    """
33
    files = sorted(glob.glob(prefix + "*"))
34
    num_layers = len(files)
35
    if num_layers == 0:
36
        raise Df3Exception("No files found with prefix '%s'" % prefix)
37
38
    width, height = Image.open(files[0]).size
39
    if not silent:
40
        print("Size: %dx%d, %d layers" % (width, height, num_layers))
41
42
    return (files, width, height, num_layers)
43
44
45
def df3combine(filename, prefix="layer", silent=True):
46
    """
47
    Combine a series of separate images into POV-Ray density file (DF3).
48
49
    :param filename: path to resulting DF3 file
50
    :param prefix: input files prefix
51
    :param silent: suppress output (info messages, progress etc.)
52
53
    """
54
    files, width, height, num_layers = detect_size(prefix, silent)
55
56
    with open(filename, "wb") as df3_file:
57
        # write header
58
        df3_file.write(to_big_endian(width)[-2:])
59
        df3_file.write(to_big_endian(height)[-2:])
60
        df3_file.write(to_big_endian(num_layers)[-2:])
61
62
        # write layers data
63
        for img_num, img_name in enumerate(files):
64
            img = Image.open(img_name)
65
            img_data = img.convert("L").tobytes("raw", "L")
66
            df3_file.write(img_data)
67
            percentage = float(img_num + 1) / num_layers * 100
68
            if not silent:
69
                sys.stdout.write("Processing data [%.2f%%]\r" % percentage)
70
                sys.stdout.flush()
71
72
        if not silent:
73
            print("\nDone.")
74
75
76
def main():
77
    """ Main script execution """
78
    parser = argparse.ArgumentParser(description="""
79
    Combine a series of separate images into POV-Ray density file (DF3)
80
    """)
81
    parser.add_argument("df3file", help="Resulting DF3 filename")
82
    parser.add_argument("-p", "--prefix", type=str,
83
                        default="layer",
84
                        help="Input files prefix")
85
    parser.add_argument("-s", "--silent", help="Suppress output",
86
                        default=False, action="store_true")
87
88
    args = parser.parse_args()
89
90
    df3combine(args.df3file, args.prefix, args.silent)
91