async def pixelate(self, im: Image.Image): root = tk.AsyncToplevel(self._master) root.title(self._master.cur_locale.general.corruptions.pixelate) root.bar = Progressbar(root, orient="horizontal", length=400, mode="indeterminate") root.bar.pack() asyncio.get_event_loop().create_task(start(root.bar)) width, height = im.size wdigits = max(-1 * len(str(width)) + 2, 1) hdigits = max(-1 * len(str(height)) + 2, 1) await asyncio.sleep(0.01) factor = hdigits if hdigits > wdigits else wdigits width = int(round(width / 2, factor) * 2) height = int(round(height / 2, factor) * 2) await asyncio.sleep(0.01) im = im.resize((width, height)) await asyncio.sleep(0.01) divider = max(10**(-1 * factor) // 5, 1) small_width = width // divider small_height = height // divider await asyncio.sleep(0.01) new_im = im.resize((small_width, small_height)) new_im = new_im.resize((width, height)) try: await root.destroy() except Exception: pass return new_im
async def alterpixel2(self, im: Image.Image): width, height = im.size wdigits = -1 * len(str(width)) + 2 hdigits = -1 * len(str(height)) + 2 factor = hdigits if hdigits > wdigits else wdigits width = int(round(width / 2, factor) * 2) height = int(round(height / 2, factor) * 2) im = im.resize((width, height)) BLOCKLEN = int("2" + "0" * (-1 * factor)) xblock = width // BLOCKLEN yblock = height // BLOCKLEN max = xblock * yblock * 2 root = tk.AsyncToplevel(self._master) root.title(self._master.cur_locale.general.corruptions.alterpixel) root.bar = Progressbar(root, orient="horizontal", length=400, mode="determinate", maximum=max) root.bar.pack() blockmap = [] for yb in range(yblock): for xb in range(xblock): blockmap.append(( xb * BLOCKLEN, yb * BLOCKLEN, (xb + 1) * BLOCKLEN, (yb + 1) * BLOCKLEN, )) root.bar["value"] += 1 await asyncio.sleep(0.001) shuffle = list(blockmap) random.shuffle(shuffle) result = Image.new(im.mode, (width, height)) for box, sbox in zip(blockmap, shuffle): c = im.crop(sbox) result.paste(c, box) root.bar["value"] += 1 await asyncio.sleep(0.001) try: await root.destroy() except Exception: pass return result
async def save(self, file: typing.Union[str, pathlib.Path]): """Shortcut to save the PIL file""" # Get the file extension ext = str(file).split(".")[-1] buffer = BytesIO() # Save into buffer self.pil_image.save(buffer, format=ext) # Find out how many bytes the file holds, and reset file pointer max_bytes = buffer.tell() buffer.seek(0) async with aiofiles.open(file, "wb") as fp: # For every byte for i in range(max_bytes): current_byte = buffer.read(1) # Open a window root = tk.AsyncToplevel(self._master) # ... that the user cannot kill root.protocol('WM_DELETE_WINDOW', lambda *i: None) async def cb(i=i): # No late binding # Write the byte await fp.write(current_byte) # ... then kill the root await root.destroy() # ... and place a button if isinstance(self.master, tk.AsyncFrame): master = self.master.master else: master = self.master tk.AsyncButton( root, # ... on the window # ... that says the current byte text=(f"{master.cur_locale.menu.fileselect.write} " f"{current_byte.hex().upper()}"), # ... and writes it on click callback=cb, ).pack() # ... and wait until the button is pressed (so the user cannot mess up) await self._master.wait_window(root)
async def alterpixel(self, im: Image.Image): root = tk.AsyncToplevel(self._master) root.title(self._master.cur_locale.general.corruptions.alterpixel) root.bar = Progressbar(root, orient="horizontal", length=400, mode="indeterminate") root.bar.pack() asyncio.get_event_loop().create_task(start(root.bar)) data = list(im.getdata()) await asyncio.sleep(0.01) random.shuffle(data) await asyncio.sleep(0.01) new_im = Image.new(im.mode, im.size, (255, 255, 255)) new_im.putdata(data) try: await root.destroy() except Exception: pass return new_im
async def altercolour(self, im: Image.Image): data = list(im.getdata()) max = len(data) root = tk.AsyncToplevel(self._master) root.title(self._master.cur_locale.general.corruptions.altercolour) root.bar = Progressbar(root, orient="horizontal", length=400, mode="determinate", maximum=max) root.bar.pack() new_data = [] for r, g, b in data: new_data.append((g, b, r)) root.bar["value"] += 1 await asyncio.sleep(0.001) new_im = Image.new(im.mode, im.size, (255, 255, 255)) new_im.putdata(new_data) try: await root.destroy() except Exception: pass return new_im
async def new(): """Internal coroutine used to create the new file dialogue.""" dialogue = tk.AsyncToplevel(manager) dialogue.title(self.cur_locale.menu.fileselect.new) dialogue.protocol("WM_DELETE_WINDOW", nothing) filename = tk.AsyncEntry(dialogue) filename.pack() async def cb(): if filename.get() != len(filename.get()) * ".": for i in r'\/:*?"<>|': if i in filename.get(): button.config(text=self.cur_locale.menu. fileselect.button.invalid) break else: manager.file = manager.dir / filename.get() await manager.destroy() else: button.config(text=self.cur_locale.menu.fileselect. button.special) # Confirm button button = tk.AsyncButton( dialogue, text=self.cur_locale.menu.fileselect.button.default, callback=cb, ) button.pack(fill=tk.X) # Cancel button tk.AsyncButton( dialogue, text=self.cur_locale.menu.fileselect.button.cancel, callback=dialogue.destroy, ).pack(fill=tk.X) await manager.wait_window(dialogue)
async def file_select(self, *, new_file: bool = True): """File select dialogue""" manager = tk.AsyncToplevel(self) manager.title(self.cur_locale.menu.fileselect.saveas if new_file else self.cur_locale.menu.fileselect.open) manager.protocol("WM_DELETE_WINDOW", lambda: asyncio.ensure_future(manager.destroy())) dir = pathlib.Path() dirbox = tk.AsyncEntry(manager) dirbox.grid(row=0, column=0) foldermap = tk.AsyncFrame(manager) foldermap.grid(row=1, column=0) def populate_folder(folder: pathlib.Path): """Internally manages the save dialogue.""" nonlocal dir dir = manager.dir for i in [".."] + os.listdir(folder): if (dir / i).is_file(): async def cb(i=i): # i=i prevents late binding # Late binding causes an undetectable error that # causes all buttons to utilise the same callback manager.file = dir / i await manager.destroy() tk.AsyncButton( foldermap, text=f"{i} {self.cur_locale.menu.fileselect.file}", callback=cb, ).pack(fill=tk.X) elif (dir / i).is_dir(): async def cb(i=i): # i=i prevents late binding # Late binding causes an undetectable error that # causes all buttons to utilise the same callback manager.dir = dir / i change_dir(manager.dir) tk.AsyncButton( foldermap, text=f"{i} {self.cur_locale.menu.fileselect.folder}", callback=cb, ).pack(fill=tk.X) async def new(): """Internal coroutine used to create the new file dialogue.""" dialogue = tk.AsyncToplevel(manager) dialogue.title(self.cur_locale.menu.fileselect.new) dialogue.protocol("WM_DELETE_WINDOW", nothing) filename = tk.AsyncEntry(dialogue) filename.pack() async def cb(): if filename.get() != len(filename.get()) * ".": for i in r'\/:*?"<>|': if i in filename.get(): button.config(text=self.cur_locale.menu. fileselect.button.invalid) break else: manager.file = manager.dir / filename.get() await manager.destroy() else: button.config(text=self.cur_locale.menu.fileselect. button.special) # Confirm button button = tk.AsyncButton( dialogue, text=self.cur_locale.menu.fileselect.button.default, callback=cb, ) button.pack(fill=tk.X) # Cancel button tk.AsyncButton( dialogue, text=self.cur_locale.menu.fileselect.button.cancel, callback=dialogue.destroy, ).pack(fill=tk.X) await manager.wait_window(dialogue) if new_file: # New File button tk.AsyncButton(foldermap, text=self.cur_locale.menu.fileselect.new, callback=new).pack(fill=tk.X) def boxcallback(*i): """Internal function called to change the directory to what is typed in dirbox.""" change_dir(dirbox.get()) def change_dir(path: typing.Union[str, pathlib.Path]): """Internal function to load a path into the file select menu.""" nonlocal dir, foldermap dir = pathlib.Path(path) manager.dir = dir asyncio.ensure_future(foldermap.destroy()) foldermap = tk.AsyncFrame(manager) foldermap.grid(row=1, column=0) populate_folder(dir) # Cancel button tk.AsyncButton( foldermap, text=self.cur_locale.menu.fileselect.button.cancel, callback=manager.destroy, ).pack(fill=tk.X) dirbox.bind("<Return>", boxcallback) change_dir(".") await self.wait_window(manager) if hasattr(manager, "file"): return manager.file