Skip to content

Instantly share code, notes, and snippets.

@LiEnby
Created September 10, 2022 04:11
Show Gist options
  • Save LiEnby/78387f90e649f9b6e7d8cdd96456aa52 to your computer and use it in GitHub Desktop.
Save LiEnby/78387f90e649f9b6e7d8cdd96456aa52 to your computer and use it in GitHub Desktop.
Mass CXML Decompile / Recompile
from PIL import Image, ImageEnhance, ImageDraw
from lxml import etree
import os
import shutil
import struct
IS_INDICATOR = False
def create_stripe(img: Image.Image, bbox: tuple[int,int,int,int], height: int, color: tuple[int,int,int], index: int):
" creates a stripe on the image "
d = ImageDraw.Draw(img)
xy1 = (bbox[0], bbox[1]+height*index)
xy2 = (bbox[2], bbox[1]+height*(index+1))
d.rectangle((xy1, xy2), color)
def transify_image(in_img: Image.Image) -> Image.Image:
"makes the image into a trans flag"
c = in_img.copy()
bbox = c.getbbox()
if not bbox:
return c
stripe_height = (bbox[3] - bbox[1]) / 4 # 5 for trans flag
# trans flag
#create_stripe(c, bbox, stripe_height, (91, 206, 250), 0)
#create_stripe(c, bbox, stripe_height, (245, 169, 184), 1)
#create_stripe(c, bbox, stripe_height, (255, 255, 255), 2)
#create_stripe(c, bbox, stripe_height, (245, 169, 184), 3)
#create_stripe(c, bbox, stripe_height, (91, 206, 250), 4)
# nb flag
create_stripe(c, bbox, stripe_height, (252, 244, 52 ), 0)
create_stripe(c, bbox, stripe_height, (255, 255, 255), 1)
create_stripe(c, bbox, stripe_height, (156, 89, 209), 2)
create_stripe(c, bbox, stripe_height, (44, 44, 44 ), 3)
c.putalpha(in_img.split()[-1])
return c
def darken(image):
print("Transd: "+image)
im = Image.open(image).convert("RGBA")
im = transify_image(im)
im.save(image, "PNG")
def pngquant(image):
os.system("pngquant.exe \""+image+"\" -o \""+image+"\" -f --speed 1")
def getfmt(gimfile):
global IS_INDICATOR
if IS_INDICATOR: # TODO: Work out why not doing this crashes the entire OS
return "-psvindex8"
gf = open(gimfile, "rb")
gf.seek(0x44, 0)
gtype = struct.unpack('h', gf.read(2))[0]
gf.close()
print("Gtype: "+str(gtype))
if gtype == 0x3:
return "-psvrgba8888"
else:
return "-psvindex8"
def gimify(image, fmt):
pngquant(image)
os.system("GimConv\\GimConv.exe \""+image+"\" "+fmt)
def compress(gim):
os.system("CXMLDecompiler -i \""+gim+"\" -o \""+gim.replace(".gim", ".z").replace(".png", ".z")+"\" --compress")
def changeOrigSize(xmlObj, origsize, neworigsize, oname):
itms = xmlObj.xpath("//*[@origsize='"+str(origsize)+"' and @id='"+oname.lower()+"']")
for itm in itms:
itm.set("origsize", str(neworigsize))
print("Updating origsize for "+oname)
skip = True
for root, dirs, files in os.walk("vs0"):
for file in files:
if file.endswith(".png"):
originalPath = root+"\\"+file
newPath = originalPath.replace("vs0", "theme")
path = os.path.dirname(newPath)
if not os.path.exists(path):
os.makedirs(path)
shutil.copy(originalPath, newPath)
darken(newPath)
pngquant(newPath)
totalImages = 0
if file.endswith(".rco"):
if file == "indicator_plugin.rco":
IS_INDICATOR = True
else:
IS_INDICATOR = False
compressFile = True
originalPath = root+"\\"+file
print(originalPath)
shutil.copy(originalPath, file)
xmlOut = file.replace(".rco", ".xml")
os.system("CXMLDecompiler.exe -i \""+ file +"\" -o \""+ xmlOut +"\" -d -nr -p")
files_dir = os.path.basename(file.replace(".rco", "")) + "_files"
if os.path.exists('textures'):
shutil.rmtree('textures')
if os.path.exists(files_dir+'\\converted\\GIMtoPNG'):
shutil.copytree(files_dir+'\\converted\\GIMtoPNG', 'textures')
if not os.path.exists('textures'):
os.makedirs('textures')
if not os.path.exists(files_dir+"\\decompressed"):
os.makedirs(files_dir+"\\decompressed")
if not os.path.exists(files_dir+"\\original"):
os.makedirs(files_dir+"\\original")
lst = os.listdir("textures")
lst2 = os.listdir(files_dir+"\\decompressed\\")
lst3 = os.listdir(files_dir+"\\original\\")
#pluginXml = open(xmlOut, "rb").read()
#//*[@origsize='30096' and @id='29b91f26']
pluginXml = etree.parse(open(xmlOut, "rb"))
for ll in lst2:
if ll.endswith(".png"):
deocmpressedFile = files_dir+"\\decompressed\\"+ll
shutil.copy(deocmpressedFile, 'textures')
origsize = os.path.getsize(deocmpressedFile)
oname = os.path.splitext(os.path.basename(ll))[0]
print(oname)
darken('textures\\'+ll)
compress('textures\\'+ll)
origsize2 = os.path.getsize('textures\\'+ll)
changeOrigSize(pluginXml, origsize, origsize2, oname)
zName = ll.replace(".png", ".z")
shutil.copy('textures\\'+zName, files_dir+"\\original\\"+zName)
totalImages+=1
for lll in lst3:
if lll.endswith(".png"):
origsize = os.path.getsize(files_dir+"\\original\\"+lll)
oname = os.path.splitext(os.path.basename(lll))[0]
print(oname)
darken(files_dir+"\\original\\"+lll)
origsize2 = os.path.getsize(files_dir+"\\original\\"+lll)
changeOrigSize(pluginXml, origsize, origsize2, oname)
totalImages += 1
for l in lst:
imagename = "textures/"+l
oname = os.path.splitext(os.path.basename(l))[0]
print(oname)
darken(imagename)
decompressedFile = files_dir+'\\decompressed\\'+l.replace(".png",".gim")
origsize = 0
gformat = ""
if os.path.exists(decompressedFile):
origsize = os.path.getsize(decompressedFile)
gformat = getfmt(decompressedFile)
else:
decompressedFile = files_dir+'\\original\\'+l.replace(".png",".gim")
gformat = getfmt(decompressedFile)
origsize = os.path.getsize(decompressedFile)
compressFile = False
pngquant(imagename)
print(gformat)
gimify(imagename, gformat)
gimname = imagename.replace(".png",".gim")
origsize2 = os.path.getsize(gimname)
changeOrigSize(pluginXml, origsize, origsize2, oname)
zName = ""
zName0 = ""
if compressFile:
compress(gimname)
zName = gimname.replace(".gim", ".z")
zNameO = l.replace(".png", ".z")
else:
zName = gimname
zNameO = l.replace(".png", ".gim")
shutil.copy(zName, files_dir+'\\original\\'+zNameO)
print("Copying "+zName+" to "+files_dir+'\\original\\'+zNameO)
totalImages += 1
open(xmlOut, "wb").write(etree.tostring(pluginXml, pretty_print=True))
os.system("CXMLDecompiler.exe -i \""+xmlOut+"\" -o \""+file+"\" -c")
newPath = originalPath.replace("vs0", "theme")
path = os.path.dirname(newPath)
if not os.path.exists(path):
os.makedirs(path)
if totalImages > 0:
shutil.copy(file, newPath)
os.remove(file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment