mirror of
https://github.com/mon/ifstools.git
synced 2024-11-27 18:40:48 +01:00
Canvas dumping, rename nocache to no-cache
This commit is contained in:
parent
ee8ae3374c
commit
8c5ed5a3b9
@ -1,25 +1,75 @@
|
||||
from io import BytesIO
|
||||
|
||||
from kbinxml import KBinXML
|
||||
from tqdm import tqdm
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from . import MD5Folder, ImageFile, GenericFile
|
||||
from .ImageDecoders import cachable_formats
|
||||
|
||||
class TextureList(GenericFile):
|
||||
def _load_from_filesystem(self):
|
||||
raw = GenericFile._load_from_filesystem(self)
|
||||
k = KBinXML(raw)
|
||||
# force the only type we can compress
|
||||
# fallback to a type we can encode
|
||||
for tex in k.xml_doc.iterchildren():
|
||||
tex.attrib['format'] = 'argb8888rev'
|
||||
if tex.attrib['format'] not in cachable_formats:
|
||||
tex.attrib['format'] = 'argb8888rev'
|
||||
|
||||
return k.to_binary()
|
||||
|
||||
class ImageCanvas(GenericFile):
|
||||
def __init__(self, name, size, images, parent):
|
||||
self.name = '_canvas_{}.png'.format(name)
|
||||
self._packed_name = self.name
|
||||
self.time = parent.time
|
||||
self.path = parent.path
|
||||
|
||||
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
|
||||
if dump_canvas:
|
||||
GenericFile.extract(self, base, **kwargs)
|
||||
|
||||
def load(self, convert_kbin = False):
|
||||
''' 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)
|
||||
if self.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]
|
||||
im.paste(sprite_im, (size[0], size[2]))
|
||||
if self.bbox:
|
||||
draw.rectangle((size[0], size[2], size[1], size[3]), outline='red')
|
||||
|
||||
del draw
|
||||
b = BytesIO()
|
||||
im.save(b, format = 'PNG')
|
||||
return b.getvalue()
|
||||
|
||||
# since it's basically metadata, we ignore similarly to _cache
|
||||
def repack(self, manifest, data_blob, tqdm_progress, **kwargs):
|
||||
return
|
||||
|
||||
class TexFolder(MD5Folder):
|
||||
def __init__(self, ifs_data, obj, parent = None, path = '', name = '', supers = None):
|
||||
MD5Folder.__init__(self, ifs_data, obj, parent, path, name, supers, 'image', '.png')
|
||||
|
||||
def tree_complete(self):
|
||||
MD5Folder.tree_complete(self)
|
||||
|
||||
if '_cache' in self.folders:
|
||||
self.folders.pop('_cache')
|
||||
|
||||
if not self.info_kbin:
|
||||
return
|
||||
|
||||
@ -32,12 +82,17 @@ class TexFolder(MD5Folder):
|
||||
for tex in self.info_kbin.xml_doc.iterchildren():
|
||||
folder = tex.attrib['name']
|
||||
fmt = tex.attrib['format']
|
||||
canvas_contents = []
|
||||
canvas_size = None
|
||||
for indiv in tex.iterchildren():
|
||||
if indiv.tag == 'size':
|
||||
continue
|
||||
canvas_size = self._split_ints(indiv.text)
|
||||
elif indiv.tag == 'image':
|
||||
name = indiv.attrib['name'] + '.png'
|
||||
if name in self.files:
|
||||
ImageFile.upgrade_generic(self.files[name], indiv, fmt, self.compress)
|
||||
canvas_contents.append(self.files[name])
|
||||
else:
|
||||
print('Unknown texturelist.xml element {}'.format(indiv.tag))
|
||||
tqdm.write('Unknown texturelist.xml element {}'.format(indiv.tag))
|
||||
canvas = ImageCanvas(folder, canvas_size, canvas_contents, self)
|
||||
self.files[canvas.name] = canvas
|
||||
|
@ -6,4 +6,4 @@ from .ImageFile import ImageFile
|
||||
from .GenericFolder import GenericFolder
|
||||
from .MD5Folder import MD5Folder
|
||||
from .AfpFolder import AfpFolder
|
||||
from .TexFolder import TexFolder
|
||||
from .TexFolder import TexFolder, ImageCanvas
|
||||
|
@ -11,7 +11,7 @@ from tqdm import tqdm
|
||||
from kbinxml import KBinXML
|
||||
from kbinxml.bytebuffer import ByteBuffer
|
||||
|
||||
from .handlers import GenericFolder, MD5Folder, ImageFile
|
||||
from .handlers import GenericFolder, MD5Folder, ImageFile, ImageCanvas
|
||||
from . import utils
|
||||
|
||||
SIGNATURE = 0x6CAD8F89
|
||||
@ -143,7 +143,14 @@ class IFS:
|
||||
|
||||
# build the tree
|
||||
for folder in self.tree.all_folders:
|
||||
if tex_only and folder.name != 'tex':
|
||||
if tex_only and folder.name == 'tex':
|
||||
self.tree = folder
|
||||
# make it root to discourage repacking
|
||||
folder.name = ''
|
||||
for f in folder.all_files:
|
||||
f.path = ''
|
||||
break
|
||||
elif tex_only:
|
||||
continue
|
||||
f_path = join(path, folder.full_path)
|
||||
utils.mkdir_silent(f_path)
|
||||
@ -151,7 +158,7 @@ class IFS:
|
||||
|
||||
# extract the files
|
||||
for f in tqdm(self.tree.all_files):
|
||||
if tex_only and not isinstance(f, ImageFile):
|
||||
if tex_only and not isinstance(f, ImageFile) and not isinstance(f, ImageCanvas):
|
||||
continue
|
||||
f.extract(path, **kwargs)
|
||||
if progress:
|
||||
|
@ -41,7 +41,9 @@ def main():
|
||||
parser.add_argument('-y', action='store_true', help='don\'t prompt for file/folder overwrite', dest='overwrite')
|
||||
parser.add_argument('-o', default='.', help='output directory', dest='out_dir')
|
||||
parser.add_argument('--tex-only', action='store_true', help='only extract textures', dest='tex_only')
|
||||
parser.add_argument('--nocache', action='store_false', help='ignore texture cache, recompress all', dest='use_cache')
|
||||
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('--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',
|
||||
help='don\'t display files as they are processed')
|
||||
|
Loading…
Reference in New Issue
Block a user