mirror of
https://github.com/mon/ifstools.git
synced 2024-11-27 18:40:48 +01:00
GenericFile.load now uses kwargs, add --uv arg
This commit is contained in:
parent
9004fef5d7
commit
c3b01d03f9
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user