1
0
mirror of https://github.com/mon/ifstools.git synced 2024-11-30 19:54:27 +01:00

GenericFile.load now uses kwargs, add --uv arg

This commit is contained in:
Will Toohey 2018-05-21 22:07:45 +10:00
parent 9004fef5d7
commit c3b01d03f9
5 changed files with 41 additions and 21 deletions

View File

@ -21,7 +21,7 @@ Then run `ifstools` from anywhere in a command prompt.
## Usage
```
usage: ifstools [-h] [-e] [-y] [-o OUT_DIR] [--tex-only] [-c]
[--bounds] [--no-cache] [-m] [-s] [-r]
[--bounds] [--uv] [--no-cache] [-m] [-s] [-r]
file_to_unpack.ifs|folder_to_repack_ifs
[file_to_unpack.ifs|folder_to_repack_ifs ...]
@ -43,6 +43,8 @@ optional arguments:
-c, --canvas dump the image canvas as defined by the
texturelist.xml in _canvas.png
--bounds draw image bounds on the exported canvas in red
--uv crop images to uvrect (usually 1px smaller than
imgrect). Forces --tex-only
--no-cache ignore texture cache, recompress all
-m, --extract-manifest
extract the IFS manifest for inspection

View File

@ -16,24 +16,24 @@ class GenericFile(Node):
self.start = self.size = None
def extract(self, base, **kwargs):
data = self.load()
data = self.load(**kwargs)
path = os.path.join(base, self.full_path)
utils.save_with_timestamp(path, data, self.time)
def load(self, convert_kbin = True):
def load(self, **kwargs):
if self.from_ifs:
return self._load_from_ifs(convert_kbin)
return self._load_from_ifs(**kwargs)
else:
return self._load_from_filesystem()
return self._load_from_filesystem(**kwargs)
def _load_from_ifs(self, convert_kbin = True):
def _load_from_ifs(self, convert_kbin = True, **kwargs):
data = self.ifs_data.get(self.start, self.size)
if convert_kbin and self.name.endswith('.xml') and KBinXML.is_binary_xml(data):
data = KBinXML(data).to_text().encode('utf8')
return data
def _load_from_filesystem(self):
def _load_from_filesystem(self, **kwargs):
with open(self.disk_path, 'rb') as f:
ret = f.read()
self.size = len(ret)

View File

@ -25,21 +25,26 @@ class ImageFile(GenericFile):
self.format = fmt
self.compress = compress
self.uvrect = self._split_ints(image_elem.find('uvrect').text)
self.imgrect = self._split_ints(image_elem.find('imgrect').text)
# all values are multiplied by 2, odd values have never been seen
self.uvrect = [x//2 for x in self._split_ints(image_elem.find('uvrect').text)]
self.imgrect = [x//2 for x in self._split_ints(image_elem.find('imgrect').text)]
self.img_size = (
(self.imgrect[1]-self.imgrect[0])//2,
(self.imgrect[3]-self.imgrect[2])//2
self.imgrect[1]-self.imgrect[0],
self.imgrect[3]-self.imgrect[2]
)
self.uv_size = (
self.uvrect[1]-self.uvrect[0],
self.uvrect[3]-self.uvrect[2]
)
def extract(self, base, use_cache = True, **kwargs):
GenericFile.extract(self, base, **kwargs)
if use_cache and self.compress and self.from_ifs and self.format in cachable_formats:
self.write_cache(GenericFile._load_from_ifs(self), base)
self.write_cache(GenericFile._load_from_ifs(self, **kwargs), base)
def _load_from_ifs(self, convert_kbin = False):
data = GenericFile._load_from_ifs(self, False)
def _load_from_ifs(self, crop_to_uvrect = False, **kwargs):
data = GenericFile._load_from_ifs(self, **kwargs)
if self.compress == 'avslz':
uncompressed_size = unpack('>I', data[:4])[0]
@ -60,6 +65,17 @@ class ImageFile(GenericFile):
else:
raise NotImplementedError('Unknown format {}'.format(self.format))
if crop_to_uvrect:
start_x = self.uvrect[0] - self.imgrect[0]
start_y = self.uvrect[2] - self.imgrect[2]
dims = (
start_x,
start_y,
start_x + self.uv_size[0],
start_y + self.uv_size[1],
)
im = im.crop(dims)
b = BytesIO()
im.save(b, format = 'PNG')
return b.getvalue()

View File

@ -27,29 +27,27 @@ class ImageCanvas(GenericFile):
self.images = images
self.img_size = size
self.bbox = False
def extract(self, base, dump_canvas = False, draw_bbox = False, **kwargs):
self.bbox = draw_bbox
def extract(self, base, dump_canvas = False, **kwargs):
if dump_canvas:
GenericFile.extract(self, base, **kwargs)
def load(self, convert_kbin = False):
def load(self, draw_bbox = False, **kwargs):
''' Makes the canvas.
This could be far speedier if it copied raw pixels, but that would
take far too much time to write vs using Image inbuilts '''
im = Image.new('RGBA', self.img_size)
draw = None
if self.bbox:
if draw_bbox:
draw = ImageDraw.Draw(im)
for sprite in self.images:
data = sprite.load()
sprite_im = Image.open(BytesIO(data))
size = [x//2 for x in sprite.imgrect]
size = sprite.imgrect
im.paste(sprite_im, (size[0], size[2]))
if self.bbox:
if draw_bbox:
draw.rectangle((size[0], size[2], size[1], size[3]), outline='red')
del draw

View File

@ -43,6 +43,7 @@ def main():
parser.add_argument('--tex-only', action='store_true', help='only extract textures', dest='tex_only')
parser.add_argument('-c', '--canvas', action='store_true', help='dump the image canvas as defined by the texturelist.xml in _canvas.png', dest='dump_canvas')
parser.add_argument('--bounds', action='store_true', help='draw image bounds on the exported canvas in red', dest='draw_bbox')
parser.add_argument('--uv', action='store_true', help='crop images to uvrect (usually 1px smaller than imgrect). Forces --tex-only', dest='crop_to_uvrect')
parser.add_argument('--no-cache', action='store_false', help='ignore texture cache, recompress all', dest='use_cache')
parser.add_argument('-m', '--extract-manifest', action='store_true', help='extract the IFS manifest for inspection', dest='extract_manifest')
parser.add_argument('-s', '--silent', action='store_false', dest='progress',
@ -52,6 +53,9 @@ def main():
args = parser.parse_args()
if args.crop_to_uvrect:
args.tex_only = True
if args.extract_folders:
dirs = [f for f in args.files if os.path.isdir(f)]
# prune