Skip to content

Commit 71e2dae

Browse files
committed
Implemented zstandard compression
1 parent 9bbbfcb commit 71e2dae

File tree

4 files changed

+27
-19
lines changed

4 files changed

+27
-19
lines changed

Main.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
# -*- coding: utf-8 -*-
2-
31
import os
42
import sys
53
import lzma
64
import lzham
75
import hashlib
86
import argparse
7+
import zstandard
98

109
from PIL import Image
1110
from Writer import BinaryWriter
1211

1312

1413
class Packer(BinaryWriter):
1514

16-
def __init__(self, use_lzma, use_lzham, splitting, header, outputName):
15+
def __init__(self, use_lzma, use_lzham, use_zstd, splitting, header, outputName):
1716
self.settings = {
1817
'use_lzma': use_lzma,
1918
'use_lzham': use_lzham,
19+
'use_zstd': use_zstd,
2020
'splitting': splitting,
2121
'header': header,
2222
'outputname': outputName
@@ -81,14 +81,14 @@ def pack(self):
8181

8282
self.write(5)
8383

84-
if self.settings['use_lzma'] or self.settings['use_lzham']:
84+
if True in (self.settings['use_lzma'], self.settings['use_lzham'], self.settings['use_zstd']):
8585
self.compress_data()
8686

8787
if self.settings['outputname']:
8888
outputName = self.settings['outputname']
8989

9090
else:
91-
outputName = '_'.join(list(filter(None, (''.join(''.join(self.image_list[0]['Path'].split('.png')).split('_')).split('tex'))))) + '_tex.sc'
91+
outputName = os.path.splitext(self.image_list[0]['Path'])[0].rstrip('_') + '.sc'
9292

9393
with open(outputName, 'wb') as f:
9494
f.write(self.buffer)
@@ -124,12 +124,9 @@ def split_image(self, image):
124124
print('[*] Splitting done !')
125125

126126
def write_pixel(self, pixelFormat, colors):
127-
red = colors[0]
128-
green = colors[1]
129-
blue = colors[2]
130-
alpha = colors[3]
127+
red, green, blue, alpha = colors
131128

132-
if pixelFormat == 0 or pixelFormat == 1:
129+
if pixelFormat in (0, 1):
133130
# RGBA8888
134131
self.write_uint8(red)
135132
self.write_uint8(green)
@@ -189,22 +186,32 @@ def compress_data(self):
189186
compressed = lzma.compress(self.buffer, format=lzma.FORMAT_ALONE, filters=filters)
190187
compressed = compressed[0:5] + len(self.buffer).to_bytes(4, 'little') + compressed[13:]
191188

192-
else:
189+
elif self.settings['use_lzham']:
193190
print('[*] Compressing texture with lzham')
194191

195192
dict_size = 18
196193

197194
compressed = lzham.compress(self.buffer, {'dict_size_log2': dict_size})
198195
compressed = 'SCLZ'.encode('utf-8') + dict_size.to_bytes(1, 'big') + len(self.buffer).to_bytes(4, 'little') + compressed
199196

197+
else:
198+
print('[*] Compressing texture with zstandard')
199+
compressed = zstandard.compress(self.buffer, level=zstandard.MAX_COMPRESSION_LEVEL)
200+
200201
fileMD5 = hashlib.md5(self.buffer).digest()
201202

202203
# Flush the previous buffer
203204
self.buffer = b''
204205

205206
if self.settings['header']:
206207
self.write('SC'.encode('utf-8'))
207-
self.write_uint32(1, 'big')
208+
209+
if self.settings['use_zstd']:
210+
self.write_uint32(3, 'big')
211+
212+
else:
213+
self.write_uint32(1, 'big')
214+
208215
self.write_uint32(len(fileMD5), 'big')
209216
self.write(fileMD5)
210217

@@ -220,6 +227,7 @@ def compress_data(self):
220227
parser.add_argument('files', help='.png file(s) to pack', nargs='+')
221228
parser.add_argument('-lzma', '--lzma', help='enable LZMA compression', action='store_true')
222229
parser.add_argument('-lzham', '--lzham', help='enable LZHAM compression', action='store_true')
230+
parser.add_argument('-zstd', '--zstd', help='enable Zstandard compression', action='store_true')
223231
parser.add_argument('-header', '--header', help='add SC header to the beginning of the compressed _tex.sc', action='store_true')
224232
parser.add_argument('-o', '--outputname', help='define an output name for the _tex.sc file (if not specified the output filename is set to <first_packed_filename> + _tex.sc')
225233
parser.add_argument('-p', '--pixelformat', help='pixelformat(s) to be used to pack .png to _tex.sc', nargs='+', type=int)
@@ -229,8 +237,8 @@ def compress_data(self):
229237

230238
if args.pixelformat:
231239
if len(args.files) == len(args.pixelformat):
232-
if not (args.lzma and args.lzham):
233-
scPacker = Packer(args.lzma, args.lzham, args.splitting, args.header, args.outputname)
240+
if (args.lzham, args.lzma, args.zstd).count(True) == 1:
241+
scPacker = Packer(args.lzma, args.lzham, args.zstd, args.splitting, args.header, args.outputname)
234242

235243
for file, pixelFormat in zip(args.files, args.pixelformat):
236244
if file.endswith('.png'):
@@ -248,7 +256,7 @@ def compress_data(self):
248256
scPacker.pack()
249257

250258
else:
251-
print('[*] You cannot set both lzma and lzham compression !')
259+
print('[*] You cannot set many compression at a time !')
252260

253261
else:
254262
print('[*] Files count and pixelformats count don\'t match !')

Writer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
from io import BytesIO
42

53

readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ in this case ui\_tex.png will be packed using pixelformat 0 and ui\_tex\_.png us
3030

3131
* `-lzma`: if this argument is specified tex.sc file will be compressed using lzma
3232
* `-lzham`: if this argument is specified tex.sc file will be compressed using lzham
33+
* `-zstd`: if this argument is specified tex.sc file will be compressed using zstandard
3334
* `-header`: add Supercell header at the beginning of the compressed tex.sc file
3435
* `-o`: optionnal output filename for the tex.sc file, if this argument isn't specified tex.sc file will be saved as <first\_packed\_filename\> + _tex.sc
3536
* `-s`: enable 32x32 block texture splitting, 32x32 block splitting is used in most of the original Supercell _tex.sc files
@@ -51,5 +52,5 @@ Basically to re-pack these .png we'll use the following command:
5152
5253
### Dependencies
5354
To install **scPacker** dependencies run the following command
54-
55+
5556
> python -m pip install -r requirements.txt

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pylzham
2-
Pillow
2+
Pillow
3+
zstandard

0 commit comments

Comments
 (0)