def _get_media_cache(export_request: MediaExportRequest, sourcedir: Path, palettes: dict[int, ColorTable], compression_level: int) -> None: """ Convert a media file and return the used settings. This performs a dry run, i.e. the graphics media is not saved on the filesystem. :param export_request: Export request for a graphics file. :param sourcedir: Directory where all media assets are mounted. Source subfolder and source filename should be stored in the export request. :param exportdir: Directory the resulting file(s) will be exported to. Target subfolder and target filename should be stored in the export request. :param palettes: Palettes used by the game. :param compression_level: PNG compression level for the resulting image file. :type export_request: MediaExportRequest :type sourcedir: Path :type exportdir: Path :type palettes: dict :type compression_level: int """ source_file = sourcedir[export_request.get_type().value, export_request.source_filename] try: media_file = source_file.open("rb") except FileNotFoundError: if source_file.suffix.lower() == ".smx": # Rename extension to SMP and try again other_filename = export_request.source_filename[:-1] + "p" source_file = sourcedir[export_request.get_type().value, other_filename] media_file = source_file.open("rb") if source_file.suffix.lower() == ".slp": from ...value_object.read.media.slp import SLP image = SLP(media_file.read()) elif source_file.suffix.lower() == ".smp": from ...value_object.read.media.smp import SMP image = SMP(media_file.read()) elif source_file.suffix.lower() == ".smx": from ...value_object.read.media.smx import SMX image = SMX(media_file.read()) from .texture_merge import merge_frames texture = Texture(image, palettes) merge_frames(texture) MediaExporter.save_png(texture, None, None, compression_level=compression_level, cache=None, dry_run=True) return texture.get_cache_params()
def _export_terrain(export_request, sourcedir, exportdir, palettes, game_version, compression_level): """ Convert and export a terrain graphics file. :param export_request: Export request for a terrain graphics file. :param sourcedir: Directory where all media assets are mounted. Source subfolder and source filename should be stored in the export request. :param exportdir: Directory the resulting file(s) will be exported to. Target subfolder and target filename should be stored in the export request. :param game_version: Game edition and expansion info. :param palettes: Palettes used by the game. :param compression_level: PNG compression level for the resulting image file. :type export_request: MediaExportRequest :type sourcedir: Directory :type exportdir: Directory :type palettes: dict :type game_version: tuple :type compression_level: int """ source_file = sourcedir[ export_request.get_type().value, export_request.source_filename ] media_file = source_file.open("rb") if source_file.suffix.lower() == ".slp": from ...value_object.read.media.slp import SLP image = SLP(media_file.read()) elif source_file.suffix.lower() == ".dds": # TODO: Implement pass if game_version[0].game_id in ("AOC", "SWGB"): from .terrain_merge import merge_terrain texture = Texture(image, palettes) merge_terrain(texture) else: from .texture_merge import merge_frames texture = Texture(image, palettes) merge_frames(texture) MediaExporter.save_png( texture, exportdir[export_request.targetdir], export_request.target_filename, compression_level, )
def get_textures(self) -> list[Texture]: """ generate a list of textures. one atlas per blending mode is generated, each atlas contains all blending masks merged on one texture """ from ....entity_object.export.texture import Texture return [Texture(b_mode) for b_mode in self.blending_modes]
def save_png(texture: Texture, targetdir: Path, filename: str, compression_level: int = 1, cache: dict = None, dry_run: bool = False) -> None: """ Store the image data into the target directory path, with given filename="dir/out.png". :param texture: Texture with an image atlas. :param targetdir: Directory where the image file is created. :param filename: Name of the resulting image file. :param compression_level: PNG compression level used for the resulting image file. :param dry_run: If True, create the PNG but don't save it as a file. :type texture: Texture :type targetdir: Directory :type filename: str :type compression_level: int :type dry_run: bool """ from ...service.export.png import png_create compression_levels = { 0: png_create.CompressionMethod.COMPR_NONE, 1: png_create.CompressionMethod.COMPR_DEFAULT, 2: png_create.CompressionMethod.COMPR_OPTI, 3: png_create.CompressionMethod.COMPR_GREEDY, 4: png_create.CompressionMethod.COMPR_AGGRESSIVE, } if not dry_run: _, ext = os.path.splitext(filename) # only allow png if ext != ".png": raise ValueError("Filename invalid, a texture must be saved" "as 'filename.png', not '%s'" % (filename)) compression_method = compression_levels.get( compression_level, png_create.CompressionMethod.COMPR_DEFAULT) png_data, compr_params = png_create.save(texture.image_data.data, compression_method, cache) if not dry_run: with targetdir[filename].open("wb") as imagefile: imagefile.write(png_data) if compr_params: texture.best_compr = (compression_level, *compr_params)
def _export_terrain(export_request: MediaExportRequest, sourcedir: Path, exportdir: Path, palettes: dict[int, ColorTable], game_version: GameVersion, compression_level: int) -> None: """ Convert and export a terrain graphics file. :param export_request: Export request for a terrain graphics file. :param sourcedir: Directory where all media assets are mounted. Source subfolder and source filename should be stored in the export request. :param exportdir: Directory the resulting file(s) will be exported to. Target subfolder and target filename should be stored in the export request. :param game_version: Game edition and expansion info. :param palettes: Palettes used by the game. :param compression_level: PNG compression level for the resulting image file. :type export_request: MediaExportRequest :type sourcedir: Directory :type exportdir: Directory :type palettes: dict :type game_version: GameVersion :type compression_level: int """ source_file = sourcedir[export_request.get_type().value, export_request.source_filename] if source_file.suffix.lower() == ".slp": from ...value_object.read.media.slp import SLP media_file = source_file.open("rb") image = SLP(media_file.read()) elif source_file.suffix.lower() == ".dds": # TODO: Implement pass elif source_file.suffix.lower() == ".png": from shutil import copyfileobj src_path = source_file.open('rb') dst_path = exportdir[export_request.targetdir, export_request.target_filename].open('wb') copyfileobj(src_path, dst_path) return else: raise Exception( f"Source file {source_file.name} has an unrecognized extension: " f"{source_file.suffix.lower()}") if game_version.edition.game_id in ("AOC", "SWGB"): from .terrain_merge import merge_terrain texture = Texture(image, palettes) merge_terrain(texture) else: from .texture_merge import merge_frames texture = Texture(image, palettes) merge_frames(texture) MediaExporter.save_png( texture, exportdir[export_request.targetdir], export_request.target_filename, compression_level, ) if get_loglevel() <= logging.DEBUG: MediaExporter.log_fileinfo( source_file, exportdir[export_request.targetdir, export_request.target_filename])
def _export_graphics(export_request: MediaExportRequest, sourcedir: Path, exportdir: Path, palettes: dict[int, ColorTable], compression_level: int, cache_info: dict = None) -> None: """ Convert and export a graphics file. :param export_request: Export request for a graphics file. :param sourcedir: Directory where all media assets are mounted. Source subfolder and source filename should be stored in the export request. :param exportdir: Directory the resulting file(s) will be exported to. Target subfolder and target filename should be stored in the export request. :param palettes: Palettes used by the game. :param compression_level: PNG compression level for the resulting image file. :param cache_info: Media cache information with compression parameters from a previous run. :type export_request: MediaExportRequest :type sourcedir: Path :type exportdir: Path :type palettes: dict :type compression_level: int :type cache_info: tuple """ source_file = sourcedir[export_request.get_type().value, export_request.source_filename] try: media_file = source_file.open("rb") except FileNotFoundError: if source_file.suffix.lower() == ".smx": # Rename extension to SMP and try again other_filename = export_request.source_filename[:-1] + "p" source_file = sourcedir[export_request.get_type().value, other_filename] export_request.set_source_filename(other_filename) media_file = source_file.open("rb") if source_file.suffix.lower() == ".slp": from ...value_object.read.media.slp import SLP image = SLP(media_file.read()) elif source_file.suffix.lower() == ".smp": from ...value_object.read.media.smp import SMP image = SMP(media_file.read()) elif source_file.suffix.lower() == ".smx": from ...value_object.read.media.smx import SMX image = SMX(media_file.read()) packer_cache = None compr_cache = None if cache_info: cache_params = cache_info.get(export_request.source_filename, None) if cache_params: packer_cache = cache_params["packer_settings"] compression_level = cache_params["compr_settings"][0] compr_cache = cache_params["compr_settings"][1:] from .texture_merge import merge_frames texture = Texture(image, palettes) merge_frames(texture, cache=packer_cache) MediaExporter.save_png(texture, exportdir[export_request.targetdir], export_request.target_filename, compression_level=compression_level, cache=compr_cache) metadata = {export_request.target_filename: texture.get_metadata()} export_request.set_changed() export_request.notify_observers(metadata) export_request.clear_changed() if get_loglevel() <= logging.DEBUG: MediaExporter.log_fileinfo( source_file, exportdir[export_request.targetdir, export_request.target_filename])