This repository has been archived by the owner on Apr 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
nvsg_converter
executable file
·110 lines (99 loc) · 4.07 KB
/
nvsg_converter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/python3
import argparse
import sys
import zlib
from PIL import Image
from open_ext import open_ext
HZC1_MAGIC = b'hzc1'
NVSG_MAGIC = b'NVSG'
def swap_channels(img):
channels = list(img.split())
channels[0], channels[2] = channels[2], channels[0]
return Image.merge(img.mode, channels)
def convert_to_png(input_file, output_file):
if input_file.read(len(HZC1_MAGIC)) != HZC1_MAGIC:
raise RuntimeError('Not a NVSG file')
uncompressed_size = input_file.read_u32_le()
nvsg_header_size = input_file.read_u32_le()
if input_file.read(len(NVSG_MAGIC)) != NVSG_MAGIC:
raise RuntimeError('Not a NVSG file')
unk = []
unk.append(input_file.read_u16_le()) #always 256?
format = input_file.read_u16_le()
width = input_file.read_u16_le()
height = input_file.read_u16_le()
x = input_file.read_u16_le() #not sure if coordinates, but seems close
y = input_file.read_u16_le()
unk.append(input_file.read_u16_le())
unk.append(input_file.read_u16_le())
image_count = input_file.read_u32_le()
unk.append(input_file.read_u32_le())
unk.append(input_file.read_u32_le())
data = input_file.read_until_end()
data = zlib.decompress(data)
if format == 0:
img = swap_channels(Image.fromstring('RGB', (width, height), data))
elif format == 1:
img = swap_channels(Image.fromstring('RGBA', (width, height), data))
elif format == 2:
height *= image_count
img = swap_channels(Image.fromstring('RGBA', (width, height), data))
print('Make sure to pass --image_count %d when converting back!' % (image_count))
elif format == 3:
img = Image.fromstring('L', (width, height), data)
elif format == 4:
raise NotImplementedError('1 bit images are not implemented')
else:
raise NotImplementedError('Unknown image format')
img.save(output_file, 'png')
print('Make sure to pass -x %d -y %d converting back!' % (x, y))
def convert_from_png(input_file, output_file, image_count, x, y):
img = Image.open(input_file)
img.load()
width, height = img.size
if image_count != 1:
if img.mode != 'RGBA':
raise RuntimeError('Image strides must be saved with alpha channel.')
format = 2
height = int(height / image_count)
img = swap_channels(img)
elif img.mode == 'RGBA':
format = 1
img = swap_channels(img)
elif img.mode == 'RGB':
format = 0
img = swap_channels(img)
data = img.tostring()
output_file.write(HZC1_MAGIC)
output_file.write_u32_le(len(data))
output_file.write_u32_le(0x20)
output_file.write(NVSG_MAGIC)
output_file.write_u16_le(256)
output_file.write_u16_le(format)
output_file.write_u16_le(width)
output_file.write_u16_le(height)
output_file.write_u16_le(x)
output_file.write_u16_le(y)
output_file.write_u16_le(0)
output_file.write_u16_le(0)
output_file.write_u32_le(image_count)
output_file.write_u32_le(0)
output_file.write_u32_le(0)
output_file.write(zlib.compress(data))
def main():
parser = argparse.ArgumentParser(description='Converts NVSG to PNG and vice versa')
parser.add_argument('--image_count', type=int, default=1, help='used in encoding character avatars')
parser.add_argument('-x', nargs='?', type=int, default=0, help='used in encoding')
parser.add_argument('-y', nargs='?', type=int, default=0, help='used in encoding')
parser.add_argument('infile', nargs='?', type=open_ext.ArgParser('rb'), default=sys.stdin)
parser.add_argument('outfile', nargs='?', type=open_ext.ArgParser('wb'), default=sys.stdout)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--decode', action='store_true', help='converts NVSG to PNG')
group.add_argument('--encode', action='store_false', help='converts PNG to NVSG')
result = parser.parse_args()
if result.decode:
convert_to_png(result.infile, result.outfile)
else:
convert_from_png(result.infile, result.outfile, result.image_count, result.x, result.y)
if __name__ == '__main__':
main()