Honorable Member Mali 41874 Posted August 11, 2021 Honorable Member Share Posted August 11, 2021 (edited) M2 Download Center This is the hidden content, please Sign In or Sign Up ( Internal ) This is the hidden content, please Sign In or Sign Up I did this 4 months ago out of necessity. Maybe it will be useful for someone. SubSlicer's author: sanii187 https://metin2.download/picture/w98yJ1o9Bc0QNq3Ow220aNxu68G6SX2Z/.gif password: black Edited February 9, 2023 by Mali 114 1 1 2 45 5 51 Link to comment Share on other sites More sharing options...
Forum Moderator Gurgarath 2514 Posted August 11, 2021 Forum Moderator Share Posted August 11, 2021 This is the kind of thing that will inevitably cause me to spend time upgrading the client to full .tga instead of .sub when I will have something important to do instead. Thanks for this release, it will come in handy for sure! 1 Gurgarath coming soon Link to comment Share on other sites More sharing options...
Premium WeedHex 635 Posted August 11, 2021 Premium Share Posted August 11, 2021 Ohh it's really worth! Thanks 2 Link to comment Share on other sites More sharing options...
Honorable Member .plechito' 7721 Posted August 11, 2021 Honorable Member Share Posted August 11, 2021 (edited) 2 hours ago, WeedHex said: Ohh it's really worth! Thanks You're like Edited August 25, 2022 by Metin2 Dev Core X - External 2 Internal 3 Link to comment Share on other sites More sharing options...
Honorable Member Mali 41874 Posted February 9, 2023 Author Honorable Member Share Posted February 9, 2023 (edited) #Update: I've combined sanii187's SubSlicer tool with my tool SubSlicer normally can't load dds files, uses png. Now If the dds file is wanted to be loaded with SubSlicer, it is firstly converted to png via my tool then loaded. Now SubSlicer can export sub files via my tool.(Files and tools must be in same dir) Preview Edited February 9, 2023 by Mali 9 4 Link to comment Share on other sites More sharing options...
Active+ Member Abel(Tiger) 1196 Posted February 10, 2023 Active+ Member Share Posted February 10, 2023 If you want to bulk crop here is a little python script I did some time ago: Spoiler import os import scandir # pip install scandir from PIL import Image # pip install Pillow dirSource = "catchking" # the folder with the .sub imageName = "king_001.dds" # the dds image # Recursive scantree def scantree(path): for entry in scandir.scandir(path): if entry.is_dir(follow_symlinks = False): for entry in scantree(entry.path): yield entry else: yield entry def cropImage(img, cropArea, newFilename): croppedImage = img.crop(cropArea) croppedImage.save(newFilename) def GetCropSourceFile(fileName): sourceName = "" with open(fileName, "rb") as f: for line in f: if line.startswith("image"): sourceName = str(line[6:]) return sourceName.strip().replace('"', "") def GetCropAreFromFile(fileName): left, top, right, bottom = 0, 0, 0, 0 with open(fileName, "rb") as f: for line in f: if line.startswith("left"): left = int(line[5:]) if line.startswith("top"): top = int(line[4:]) if line.startswith("right"): right = int(line[6:]) if line.startswith("bottom"): bottom = int(line[7:]) return (left, top, right, bottom) def main(): img = Image.open(imageName) for entry in scantree(dirSource): subName = entry.path root, ext = os.path.splitext(subName) if ext == ".sub": sourceName = GetCropSourceFile(subName) if sourceName != imageName: print "Can't crop sub %s because source name is not ok. (%s)" % (subName, sourceName) continue cropArea = GetCropAreFromFile(subName) print "Cropping %s - Area %s..." % (subName, str(cropArea)) cropImage(img, cropArea, root + ".png") os.remove(subName) if __name__ == "__main__": main() 1 2 Link to comment Share on other sites More sharing options...
Premium filipw1 1931 Posted February 10, 2023 Premium Share Posted February 10, 2023 (edited) I did a program that creates sub files from given png files in directory. I find it really usefull as using dds files gain you better performence. One I'll try to make a GUI for this to visualize results, but for me it's fine at current state as it gets the job done. You need to convert output png canva to dds manually. Spoiler from pyglet import image import os import math ## https://metin2.dev/topic/21221-grid-class-python/ class Grid: def __init__(self, width, height): self.grid = [False] * (width * height) self.width = width self.height = height def __str__(self): output = "Grid {}x{} Information\n".format(self.width, self.height) for x in range(self.height): output += "%3d" % (x + 1) output += "\n" for row in range(self.height): output += "%3d" % (x +1) for col in range(self.width): output += "%3d" % (row * self.width + col) output += " 1" if self.grid[row * self.width + col] else " 0" output += "\n" return output def find_blank(self, width, height): if width > self.width or height > self.height: return -1, -1, -1 for row in range(self.height): for col in range(self.width): index = row * self.width + col if self.is_empty(index, width, height): return index, row, col return -1, -1, -1 def put(self, pos, width, height): if not self.is_empty(pos, width, height): return False for row in range(height): start = pos + (row * self.width) self.grid[start] = True col = 1 while col < width: self.grid[start + col] = True col += 1 return True def clear(self, pos, width, height): if pos < 0 or pos >= (self.width * self.height): return for row in range(height): start = pos + (row * self.width) self.grid[start] = True col = 1 while col < width: self.grid[start + col] = False col += 1 def is_empty(self, pos, width, height): if pos < 0: return False row = pos // self.width if (row + height) > self.height: return False if (pos + width) > ((row * self.width) + self.width): return False for row in range(height): start = pos + (row * self.width) if self.grid[start]: return False col = 1 while col < width: if self.grid[start + col]: return False col += 1 return True def get_size(self): return self.width * self.height def reset(self): self.grid = [False] * (self.width * self.height) version = "" while not (version.isdigit() and int(version) in (1, 2)): version = input("Select sub version (1 - load dds file from \"d:\\ymir work\\ui\\\" or 2 - load dds file from dir as sub files): ") version = float(version) ddsname = "" while not ddsname: ddsname = input("Enter dds file name (public_offlineshop for example): ") images = {} files = [f for f in os.listdir('.') if os.path.isfile(f)] for f in files: ext = f.split(".")[-1] if ext != "png": continue if f == f"{ddsname}.png": print(f"Skip {f}") continue print(f"Load file {f}") img = image.load(f) print("File loaded!") images[f] = img def sortImg(img): width, height = img[1].width, img[1].height return width images = sorted(images.items(), key=sortImg, reverse=True) max_width, max_height = images[0][1].width, images[0][1].height images = {key: value for key, value in images} for key, img in images.items(): width, height = img.width, img.height print(f"File name: {key}, image size: {width}x{height}") ## https://stackoverflow.com/questions/14267555/find-the-smallest-power-of-2-greater-than-or-equal-to-n-in-python def next_power_of_2(x): return 1 if x == 0 else 2**math.ceil(math.log2(x)) canva_width, canva_height = next_power_of_2(max_width), next_power_of_2(max_height) print(f"Likely size of canva: {canva_width}x{canva_height}") done = 0 canva = None while done < len(images): canva = image.Texture.create(width=canva_width, height=canva_height) grid = Grid(canva_width, canva_height) for key, img in images.items(): img_width, img_height = img.width, img.height pos, x, y = grid.find_blank(img_width, img_height) if x >= 0 and y >= 0: grid.put(pos, img_width, img_height) done += 1 try: canva.blit_into(img, y, x, 0) left = y top = canva_height - x - img_height right = left + img_width bottom = top + img_height print(f"Image size: {img_width}x{img_height}") print(f"Found position for image {key} on left {x}, right {x + img_width}, top {y}, bottom {y + img_height}") file_name = key.split(".")[0] with open(f"{file_name}.sub", "w") as f: f.write(f"title subImage\n") f.write(f"version {version:.1f}\n") f.write(f"image \"{ddsname}.dds\"\n") f.write(f"left {left}\ntop {top}\nright {right}\nbottom {bottom}\n") f.close() except: done = 0 if math.log2(canva_height) + 1 >= math.log2(canva_width): canva_width *= 2 else: canva_height *= 2 print(f"Run out of blank space. Increase canva size to {canva_width}x{canva_height}") break canva.save(f"{ddsname}.png") Edited February 10, 2023 by filipw1 1 1 Link to comment Share on other sites More sharing options...
Recommended Posts