def test_mismatched_color_mode(): from pytoshop.user.nested_layers import Group, Image img1 = np.empty((100, 80), dtype=np.uint8) im = Image(channels={0: img1}, top=0, left=0, bottom=100, right=80, color_mode=enums.ColorMode.rgb) with pytest.raises(ValueError): im.get_channel(enums.ColorChannel.gray) im.get_channel(enums.ColorChannel.red) with pytest.raises(KeyError): im.get_channel(enums.ColorChannel.blue) layers = [ Group( layers=[ im ]) ] with pytest.raises(ValueError): nested_layers.nested_layers_to_psd( layers, enums.ColorMode.grayscale)
def test_no_images(): from pytoshop.user.nested_layers import Group layers = [ Group( layers=[] ) ] with pytest.raises(ValueError): nested_layers.nested_layers_to_psd( layers, enums.ColorMode.grayscale)
def test_from_scratch(vector_mask): from pytoshop.user.nested_layers import Group, Image img1 = np.empty((100, 80), dtype=np.uint8) img2 = np.empty((100, 80), dtype=np.uint8) img3 = np.empty((100, 80), dtype=np.uint8) img4 = np.empty((2, 100, 80), dtype=np.uint8) layers = [ Group( layers=[ Image(channels={0: img1}, top=0, left=0, bottom=100, right=80), Image(channels=img2, top=15, left=15), Image(channels=img4, top=42, left=43), Image(channels=[img1, img1], top=-5, left=49) ]), Image(channels={0: img3}) ] psd = nested_layers.nested_layers_to_psd( layers, enums.ColorMode.grayscale, vector_mask=vector_mask) buff = io.BytesIO() psd.write(buff) buff.seek(0) pytoshop.read(buff)
def test_mismatched_width(): from pytoshop.user.nested_layers import Group, Image img1 = np.empty((100, 80), dtype=np.uint8) layers = [ Group( layers=[ Image(channels={0: img1}, top=0, left=0, bottom=100, right=81), ]) ] with pytest.raises(ValueError): nested_layers.nested_layers_to_psd( layers, enums.ColorMode.grayscale)
def create_psd(self, psd_file: Union[Path, str]) -> str: """ Create PSD file at provided path containing all layers previously added to this instance. :param psd_file: Path to the Psd file to create :return: Path of the created file or error message. """ if not self.layer_ls: return 'Can not create PSD file without layer content.' psd_file = Path(psd_file) nested_layers.pprint_layers(self.layer_ls) psd_stacked = nested_layers.nested_layers_to_psd( layers=self.layer_ls, color_mode=ColorMode.rgb, version=pytoshop.enums.Version.psd, compression=pytoshop.enums.Compression.rle, size=self.size) try: # TODO: Alternative location when write only location with open(psd_file, 'wb') as file: psd_stacked.write(file) except Exception as e: LOGGER.error('Error writing Photoshop file: %s', e) return psd_file.as_posix()
def test_nested_layers_no_adjust(): filename = os.path.join(DATA_PATH, 'group.psd') with open(filename, 'rb') as fd: psd = pytoshop.PsdFile.read(fd) layers = nested_layers.psd_to_nested_layers(psd) psd2 = nested_layers.nested_layers_to_psd( layers, enums.ColorMode.rgb, size=(psd.width, psd.height)) fd = io.BytesIO() psd2.write(fd)
def test_nested_layers(): filename = os.path.join(DATA_PATH, 'group.psd') with open(filename, 'rb') as fd: psd = pytoshop.PsdFile.read(fd) layers = nested_layers.psd_to_nested_layers(psd) nested_layers.pprint_layers(layers) psd2 = nested_layers.nested_layers_to_psd(layers, enums.ColorMode.rgb) fd = io.BytesIO() psd2.write(fd)
def test_proxy(compression): from pytoshop.user.nested_layers import Group, Image class ImageProxy(object): @property def shape(self): return (1000, 1000) @property def dtype(self): return np.uint8().dtype def __array__(self): return np.arange(1000000, dtype=np.uint8).reshape((1000, 1000)) image_layers = [] for i in range(256): image_layers.append( Image( channels={0: ImageProxy()}, top=i, left=i ) ) layers = [ Group( layers=image_layers ) ] psd = nested_layers.nested_layers_to_psd( layers, enums.ColorMode.grayscale, compression=compression ) buff = io.BytesIO() psd.write(buff) buff.seek(0) psd = pytoshop.read(buff) layers = nested_layers.psd_to_nested_layers(psd) # Extract all the data so it's tested and included in the timings for image in layers[0].layers: [x.image for x in image.channels.values()]
bg_path = './background' bc_path = './bottom_color' result_path = './result' if not os.path.isdir(bg_path): os.makedirs(bg_path) if not os.path.isdir(bc_path): os.makedirs(bc_path) if not os.path.isdir(result_path): os.makedirs(result_path) for file in os.listdir(bg_path): bg_group = None with open(os.path.join(bg_path, file), 'rb') as fd: bg_psd = pytoshop.read(fd) bg_nested = nested_layers.psd_to_nested_layers(bg_psd) for l in bg_nested: if l._name == 'bg': bg_group = l with open(os.path.join(bc_path, file), 'rb') as fd: bc_psd = pytoshop.read(fd) bc_nested = nested_layers.psd_to_nested_layers(bc_psd) if bg_group != None: bc_nested.insert(len(bc_nested) - 1, bg_group) with open(os.path.join(result_path, file), 'wb') as fd: bc_psd = nested_layers.nested_layers_to_psd( bc_nested, bc_psd._color_mode) bc_psd.write(fd)
def save_stack(img, labels, dest, fmt=['rgb', 'tif', 'psd']): # rotate images back to vertical (top will always be on the right) # (easier to deal with on tablet) img = np.rot90(img, 1, (1, 0)).copy(order="C") labels = np.rot90(labels, 1, (1, 0)).copy(order="C") # NB: pytoshop requires C-contiguous arrays # get image size nrow, ncol = img.shape # RGB image where the mask is red if 'rgb' in fmt: masked = np.zeros((nrow, ncol, 3), dtype="uint8") masked[:, :, 0] = (img * 254 + 1) * (labels != 0) # R masked[:, :, 1] = (img * 254 + 1) * (labels == 0) # G masked[:, :, 2] = masked[:, :, 1] # B # NB: shift of 1 from the background to be able to easily re-extract the mask # save to file masked_img = Image.fromarray(masked) masked_img.save(dest + ".png") # multilayer, coloured TIFF file if 'tif' in fmt: # create background as RGB back = np.zeros((nrow, ncol, 3), dtype="uint8") back[:, :, 0] = img * 255 back[:, :, 1] = back[:, :, 0] back[:, :, 2] = back[:, :, 0] back_img = Image.fromarray(back) # create mask as RGBA mask = np.zeros((nrow, ncol, 4), dtype="uint8") mask[:, :, 0] = (labels != 0) * 255 mask[:, :, 3] = mask[:, :, 0] mask_img = Image.fromarray(mask) # save as multipage TIFF back_img.save(dest + ".tif", format="tiff", append_images=[mask_img], save_all=True, compression='tiff_lzw') # multilayer Photoshop file if 'psd' in fmt: blank = np.zeros((nrow, ncol), dtype="uint8") # create background as RGB back = (img * 255).astype(np.uint8) back_dict = { 0: back, # R 1: back, # G 2: back # B } # create mask as RGBA mask = ((labels != 0) * 255).astype(np.uint8) mask_dict = { 0: mask, # R 1: blank, # G 2: blank, # B -1: mask # A } # combine background and semi transparent mask back_layer = nested_layers.Image(name="back", channels=back_dict, opacity=255, color_mode=pse.ColorMode['rgb']) mask_layer = nested_layers.Image(name="mask", channels=mask_dict, opacity=150, color_mode=pse.ColorMode['rgb']) psd = nested_layers.nested_layers_to_psd([mask_layer, back_layer], color_mode=pse.ColorMode['rgb'], depth=pse.ColorDepth['depth8'], compression=pse.Compression['rle']) # write inside a subdirectory to make post-processing in external software easier os.makedirs(dest, exist_ok=True) psd.write(open(os.path.join(dest, "frame.psd"), "wb")) # TODO use with pass
color_space_correction=color_space_correction, group_color=group_color) else: groups[new_name] = image.get_grouped_nested_layers( name=name, group_name=new_name, color_space_correction=color_space_correction, group_color=group_color) print('conversion ' + file_name + ' done.\n') for group_name in groups: layers.append(groups[group_name]) # ColorMode(3) means RGB color_mode = pytoshop.enums.ColorMode(3) psd = nested_layers.nested_layers_to_psd(layers, color_mode) print('PSD data generated...\n') with open(psd_path, 'wb') as fd: psd.write(fd) print('PSD written.\n') # Used to export as bunch of png instead of one psd ''' file_name_output = image_path_input.parts[-1][:-4] + '.png' image_path_output = image_path_input.parent / file_name_output image = exr_util.Exr(image_path_input) image.save_as_png(image_path_output) '''
import numpy as np from pytoshop.enums import ColorChannel, ColorMode from pytoshop.user import nested_layers # Color channel types RGBA CHANNEL_TYPES = [ ColorChannel.red, ColorChannel.green, ColorChannel.blue, ColorChannel.transparency ] # Create Image Layer layer = nested_layers.Image(name='.Test_Layer:', color_mode=ColorMode.rgb) # Fill Layer with random image data img_np = np.array(np.random.rand(256, 256, 3) * 255, dtype=np.uint8) num_channels = range(0, img_np.shape[2]) for channel_type, channel_idx in zip(CHANNEL_TYPES, num_channels): layer.set_channel(channel_type, img_np[..., channel_idx]) layer_grp = nested_layers.Group(name='layer_group', layers=[layer]) # Create PsdFile from layer list psd_obj = nested_layers.nested_layers_to_psd(layers=[layer_grp], color_mode=ColorMode.rgb) psd_file = Path(__file__).parent / 'test_psd.psd' with open(psd_file, 'wb') as file: psd_obj.write(file)