0
|
1 #!/usr/bin/python3
|
|
2
|
|
3 # SPDX-FileCopyrightText: 2023 Sebastien Jodogne, UCLouvain, Belgium
|
|
4 # SPDX-License-Identifier: GPL-3.0-or-later
|
|
5
|
|
6 # OHIF plugin for Orthanc
|
|
7 # Copyright (C) 2023 Sebastien Jodogne, UCLouvain, Belgium
|
|
8 #
|
|
9 # This program is free software: you can redistribute it and/or
|
|
10 # modify it under the terms of the GNU General Public License as
|
|
11 # published by the Free Software Foundation, either version 3 of the
|
|
12 # License, or (at your option) any later version.
|
|
13 #
|
|
14 # This program is distributed in the hope that it will be useful, but
|
|
15 # WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
17 # General Public License for more details.
|
|
18 #
|
|
19 # You should have received a copy of the GNU General Public License
|
|
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
|
22
|
|
23 import gzip
|
|
24 import hashlib
|
|
25 import io
|
|
26 import os
|
|
27 import sys
|
|
28
|
|
29 if len(sys.argv) != 3:
|
|
30 raise Exception('Usage: %s [source folder] [target C++]' % sys.argv[0])
|
|
31
|
|
32 SOURCE = sys.argv[1]
|
|
33 TARGET = sys.argv[2]
|
|
34
|
|
35 if not os.path.isdir(SOURCE):
|
|
36 raise Exception('Nonexistent source folder: %s' % SOURCE)
|
|
37
|
|
38
|
|
39 def EncodeFileAsCString(f, variable, content):
|
|
40 f.write('static const uint8_t %s[%d] = \n "' % (variable, len(content) + 1))
|
|
41
|
|
42 column = 0
|
|
43
|
|
44 for c in content:
|
|
45
|
|
46 if sys.version_info < (3, 0):
|
|
47 # Python 2.7
|
|
48 i = ord(c)
|
|
49 else:
|
|
50 # Python 3.x
|
|
51 i = c
|
|
52
|
|
53 if i < 32 or i >= 127 or i == ord('?'):
|
|
54 f.write('\\{0:03o}'.format(i))
|
|
55 elif i in [ ord('"'), ord('\\') ]:
|
|
56 f.write('\\' + chr(i))
|
|
57 else:
|
|
58 f.write(chr(i))
|
|
59
|
|
60 column += 1
|
|
61 if column >= 120:
|
|
62 f.write('"\n "')
|
|
63 column = 0
|
|
64
|
|
65 f.write('";\n\n')
|
|
66
|
|
67
|
|
68 def WriteChecksum(f, variable, content):
|
|
69 md5 = hashlib.md5(content).hexdigest()
|
|
70 g.write('static const char* %s = "%s";\n\n' % (variable, md5))
|
|
71
|
|
72
|
|
73 with open(TARGET, 'w') as g:
|
|
74 g.write('''
|
|
75 #include <stdint.h>
|
|
76 #include <Compression/GzipCompressor.h>
|
|
77 #include <OrthancException.h>
|
|
78 #include <Toolbox.h>
|
|
79
|
|
80 static void Uncompress(std::string& target, const void* data, size_t size, const std::string& md5Expected)
|
|
81 {
|
|
82 Orthanc::GzipCompressor compressor;
|
|
83 compressor.Uncompress(target, data, size);
|
|
84 std::string md5Actual;
|
|
85 Orthanc::Toolbox::ComputeMD5(md5Actual, target);
|
|
86 if (md5Actual != md5Expected)
|
|
87 {
|
|
88 throw Orthanc::OrthancException(Orthanc::ErrorCode_CorruptedFile);
|
|
89 }
|
|
90 }
|
|
91
|
|
92 ''')
|
|
93
|
|
94 index = {}
|
|
95 count = 0
|
|
96
|
|
97 for root, dirs, files in os.walk(SOURCE):
|
|
98 for f in files:
|
|
99 fullPath = os.path.join(root, f)
|
|
100 relativePath = os.path.relpath(os.path.join(root, f), SOURCE)
|
|
101 variable = 'data_%06d' % count
|
|
102
|
|
103 with open(fullPath, 'rb') as source:
|
|
104 content = source.read()
|
|
105
|
|
106 if sys.version_info < (3, 0):
|
|
107 # Python 2.7
|
|
108 fileobj = io.BytesIO()
|
|
109 gzip.GzipFile(fileobj=fileobj, mode='w').write(content)
|
|
110 compressed = fileobj.getvalue()
|
|
111 else:
|
|
112 # Python 3.x
|
|
113 compressed = gzip.compress(content)
|
|
114
|
|
115 EncodeFileAsCString(g, variable, compressed)
|
|
116 WriteChecksum(g, variable + '_md5', content)
|
|
117
|
|
118 index[relativePath] = variable
|
|
119
|
|
120 count += 1
|
|
121
|
|
122 g.write('void ReadStaticAsset(std::string& target, const std::string& path)\n')
|
|
123 g.write('{\n')
|
|
124 for (path, variable) in index.items():
|
|
125 g.write(' if (path == "%s")\n' % path)
|
|
126 g.write(' {\n')
|
|
127 g.write(' Uncompress(target, %s, sizeof(%s) - 1, %s_md5);\n' % (variable, variable, variable))
|
|
128 g.write(' return;\n')
|
|
129 g.write(' }\n\n')
|
|
130
|
|
131 g.write(' throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentItem, "Unknown OHIF resource: " + path);\n')
|
|
132 g.write('}\n')
|