HDRLoader.deCrunch()   F
last analyzed

Complexity

Conditions 12

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 12
dl 0
loc 44
rs 2.7855
c 4
b 1
f 0

How to fix   Complexity   

Complexity

Complex classes like HDRLoader.deCrunch() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import math
2
import struct
3
import re
4
import six as sm
5
from operator import itemgetter
6
7
def convertComponent(expo, val):
8
    v = val / 256.0
9
    d = math.pow(2, expo)
10
    return v * d
11
12
def getValueFromStream(FILE):
13
    return ord(FILE.read(1))
14
15
class HDR(object):
16
    def __init__(self):
17
        self.width = 0
18
        self.height = 0
19
        self.cols = []
20
21
class HDRLoader(object):
22
    def __init__(self):
23
        self.R = 0
24
        self.G = 1
25
        self.B = 2
26
        self.E = 3
27
28
        # Mininum scanline length for encoding
29
        self.MINELEN = 8
30
        # Maximum scanline length for encoding
31
        self.MAXELEN = 0x7fff
32
33
        self.RGBE = [-1, -1, -1, -1]
34
35
        # Store the scanline stuff here
36
        self.scanline = None
37
38
    def workOnRGBE(self, hdrFILE, length):
39
        scanIndex = 0
40
        while length > 0:
41
            expo = self.scanline[scanIndex][self.E] - 128
42
            hdrFILE.cols.append(convertComponent(expo, self.scanline[scanIndex][self.R]))
43
            hdrFILE.cols.append(convertComponent(expo, self.scanline[scanIndex][self.G]))
44
            hdrFILE.cols.append(convertComponent(expo, self.scanline[scanIndex][self.B]))
45
            scanIndex = scanIndex + 1
46
            length = length - 1
47
48
49
    def deCrunch(self, scanIndex1, length, FILE):
50
51
        scanIndex = scanIndex1
52
53
        if length < self.MINELEN or length > self.MAXELEN:
54
            return self.oldDeCrunch(scanIndex, length, FILE)
55
56
        i = getValueFromStream(FILE)
57
        if i is not 2:
58
            # stuff about file parsing c style
59
            FILE.seek(-1 ,1)
60
            return self.oldDeCrunch(scanIndex, length, FILE)
61
62
        self.scanline[scanIndex][self.G] = getValueFromStream(FILE)
63
        self.scanline[scanIndex][self.B] = getValueFromStream(FILE)
64
65
        i = getValueFromStream(FILE)
66
67
        if self.scanline[scanIndex][self.G] is not 2 or self.scanline[scanIndex][self.B] & 128:
68
            self.scanline[scanIndex][self.R] = 2
69
            self.scanline[scanIndex][self.E] = i
70
            # The bug could be here
71
            return self.oldDeCrunch(scanIndex, length - 1, FILE)
72
73
        # Read each component
74
        for i in range(4):
75
            for j in range(length):
76
                code = getValueFromStream(FILE)
77
78
                # Run
79
                if code > 128:
80
                    code &= 127
81
                    val = getValueFromStream(FILE)
82
                    while code:
83
                        self.scanline[j][i] = val
84
                        code -= 1
85
                # Non-Run
86
                else:
87
                    while code:
88
                        self.scanline[j][i] = getValueFromStream(FILE)
89
                        code -= 1
90
91
        if getValueFromStream(FILE) is None:
92
            return False
93
94
    def oldDeCrunch(self, scanIndex1, length, FILE):
95
        scanIndex = scanIndex1
96
        rshift = 0
97
98
        while length > 0:
99
            self.scanline[scanIndex][self.R] = getValueFromStream(FILE)
100
            self.scanline[scanIndex][self.G] = getValueFromStream(FILE)
101
            self.scanline[scanIndex][self.B] = getValueFromStream(FILE)
102
            self.scanline[scanIndex][self.E] = getValueFromStream(FILE)
103
104
            if (getValueFromStream(FILE) is None):
105
                return False
106
107
            if (self.scanline[scanIndex][self.R] is 1 and self.scanline[scanIndex][self.G] is 1 and self.scanline[scanIndex][self.B] is 1):
108
                for [] in range(self.scanline[scanIndex][self.E] << rshift, 0, -1):
109
                    self.scanline[scanIndex][0] = self.scanline[scanIndex - 1][0]
110
                    scanIndex = scanIndex + 1
111
                    length = length - 1
112
                rshift += 8
113
            else:
114
                scanIndex = scanIndex + 1
115
                length = length - 1
116
                rshift = 0
117
            return True
118
119
    def load(self, fileName, hdrf):
120
        f = open(fileName, 'rb')
121
122
        strf = ''.join(struct.unpack('10s', f.read(10)))
123
        if strf != '#?RADIANCE':
124
            f.close()
125
            return False
126
127
        f.seek(1, 1)
128
129
        cmd = []
130
        c = 0
131
        oldc = 0
132
        while True:
133
            oldc = c
134
            c = ord(f.read(1))
135
            if c is 0xa and oldc is 0xa:
136
                break
137
            cmd.append(str(sm.unichr(c)))
138
139
        reso = []
140
        while True:
141
            c = ord(f.read(1))
142
            cstr = str(sm.unichr(c))
143
            reso.append(cstr)
144
            if c is 0xa:
145
                break
146
147
        resoStr = "".join(reso)
148
        resoStrUnformat = re.match('\-Y (?P<_0>\d+) \+X (?P<_1>\d+)', resoStr)
149
        (ws, hs) = map(itemgetter(1), sorted(resoStrUnformat.groupdict().items()))
150
151
        w = int(ws)
152
        h = int(hs)
153
154
        hdrf.width = w
155
        hdrf.height = h
156
157
        self.scanline = [[-1 for i in range(4)] for i in range(w)]
158
159
        if not self.scanline:
160
            print("File closed because scanline not found.")
161
            f.close()
162
            return False
163
164
        scnidx = 0
165
        # Convert image
166
        for [] in range(h - 1, -1, -1):
167
            # If self.scanline doesn't update is because of this
168
            if (self.deCrunch(scnidx, w, f) is False):
169
                break
170
            # This should update the cols array in hdrf which is the HDR Class.
171
            # If hdrf.cols doesn't update is because of this
172
            self.workOnRGBE(hdrf, w)
173
            scnidx = scnidx + 1
174
175
        f.close()
176
177
178
# myhdrtest = HDR()
179
# myhdrtestloader = HDRLoader()
180
# filePath = files.resolve_path('data', 'images', "grace_probe.hdr")
181
# myhdrtestloader.load(filePath, myhdrtest)
182
#
183
# print("HDR File Info")
184
# print(myhdrtest.width, myhdrtest.height)
185
# print("Size of the image: ", len(myhdrtest.cols))
186
# print("Random pixel", myhdrtest.cols[0], myhdrtest.cols[1], myhdrtest.cols[2])
187
188
#for i in range(len(myhdrtest.cols) / 3):
189
#    print(myhdrtest.cols[i], myhdrtest.cols[i + 1], myhdrtest.cols[i + 2])
190