mirror of
https://github.com/mon/ifstools.git
synced 2024-11-24 01:50:10 +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 kbinxml import KBinXML
|
||||||
|
from tqdm import tqdm
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
from . import MD5Folder, ImageFile, GenericFile
|
from . import MD5Folder, ImageFile, GenericFile
|
||||||
|
from .ImageDecoders import cachable_formats
|
||||||
|
|
||||||
class TextureList(GenericFile):
|
class TextureList(GenericFile):
|
||||||
def _load_from_filesystem(self):
|
def _load_from_filesystem(self):
|
||||||
raw = GenericFile._load_from_filesystem(self)
|
raw = GenericFile._load_from_filesystem(self)
|
||||||
k = KBinXML(raw)
|
k = KBinXML(raw)
|
||||||
# force the only type we can compress
|
# fallback to a type we can encode
|
||||||
for tex in k.xml_doc.iterchildren():
|
for tex in k.xml_doc.iterchildren():
|
||||||
|
if tex.attrib['format'] not in cachable_formats:
|
||||||
tex.attrib['format'] = 'argb8888rev'
|
tex.attrib['format'] = 'argb8888rev'
|
||||||
|
|
||||||
return k.to_binary()
|
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):
|
class TexFolder(MD5Folder):
|
||||||
def __init__(self, ifs_data, obj, parent = None, path = '', name = '', supers = None):
|
def __init__(self, ifs_data, obj, parent = None, path = '', name = '', supers = None):
|
||||||
MD5Folder.__init__(self, ifs_data, obj, parent, path, name, supers, 'image', '.png')
|
MD5Folder.__init__(self, ifs_data, obj, parent, path, name, supers, 'image', '.png')
|
||||||
|
|
||||||
def tree_complete(self):
|
def tree_complete(self):
|
||||||
MD5Folder.tree_complete(self)
|
MD5Folder.tree_complete(self)
|
||||||
|
|
||||||
if '_cache' in self.folders:
|
if '_cache' in self.folders:
|
||||||
self.folders.pop('_cache')
|
self.folders.pop('_cache')
|
||||||
|
|
||||||
if not self.info_kbin:
|
if not self.info_kbin:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -32,12 +82,17 @@ class TexFolder(MD5Folder):
|
|||||||
for tex in self.info_kbin.xml_doc.iterchildren():
|
for tex in self.info_kbin.xml_doc.iterchildren():
|
||||||
folder = tex.attrib['name']
|
folder = tex.attrib['name']
|
||||||
fmt = tex.attrib['format']
|
fmt = tex.attrib['format']
|
||||||
|
canvas_contents = []
|
||||||
|
canvas_size = None
|
||||||
for indiv in tex.iterchildren():
|
for indiv in tex.iterchildren():
|
||||||
if indiv.tag == 'size':
|
if indiv.tag == 'size':
|
||||||
continue
|
canvas_size = self._split_ints(indiv.text)
|
||||||
elif indiv.tag == 'image':
|
elif indiv.tag == 'image':
|
||||||
name = indiv.attrib['name'] + '.png'
|
name = indiv.attrib['name'] + '.png'
|
||||||
if name in self.files:
|
if name in self.files:
|
||||||
ImageFile.upgrade_generic(self.files[name], indiv, fmt, self.compress)
|
ImageFile.upgrade_generic(self.files[name], indiv, fmt, self.compress)
|
||||||
|
canvas_contents.append(self.files[name])
|
||||||
else:
|
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 .GenericFolder import GenericFolder
|
||||||
from .MD5Folder import MD5Folder
|
from .MD5Folder import MD5Folder
|
||||||
from .AfpFolder import AfpFolder
|
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 import KBinXML
|
||||||
from kbinxml.bytebuffer import ByteBuffer
|
from kbinxml.bytebuffer import ByteBuffer
|
||||||
|
|
||||||
from .handlers import GenericFolder, MD5Folder, ImageFile
|
from .handlers import GenericFolder, MD5Folder, ImageFile, ImageCanvas
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
SIGNATURE = 0x6CAD8F89
|
SIGNATURE = 0x6CAD8F89
|
||||||
@ -143,7 +143,14 @@ class IFS:
|
|||||||
|
|
||||||
# build the tree
|
# build the tree
|
||||||
for folder in self.tree.all_folders:
|
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
|
continue
|
||||||
f_path = join(path, folder.full_path)
|
f_path = join(path, folder.full_path)
|
||||||
utils.mkdir_silent(f_path)
|
utils.mkdir_silent(f_path)
|
||||||
@ -151,7 +158,7 @@ class IFS:
|
|||||||
|
|
||||||
# extract the files
|
# extract the files
|
||||||
for f in tqdm(self.tree.all_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
|
continue
|
||||||
f.extract(path, **kwargs)
|
f.extract(path, **kwargs)
|
||||||
if progress:
|
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('-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('-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('--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('-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',
|
parser.add_argument('-s', '--silent', action='store_false', dest='progress',
|
||||||
help='don\'t display files as they are processed')
|
help='don\'t display files as they are processed')
|
||||||
|
Loading…
Reference in New Issue
Block a user