Last active
April 22, 2023 03:16
-
-
Save TravisEvashkevich/390e100fddf1f9cd572b367446ccf547 to your computer and use it in GitHub Desktop.
Pytoshop and Pillow PSD Creation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#imports | |
from PIL import Image | |
import numpy | |
import pytoshop | |
from pytoshop.user import nested_layers | |
from pytoshop import enums | |
from pytoshop.image_data import ImageData | |
#Convert Pillow image to pyto layer (not fool proof by anymeans) | |
def pillow_image_to_pyto_image(name, image, x, y, visible, opacity, group_id, blend_mode, metadata, layer_color, color_mode, width = 0, height = 0): | |
'''ease of use method for converting an image loaded via PIL to be made layer ready for Pytoshop''' | |
#resize the image if needed | |
if ((width != 0 and width != image.width) or (height != 0 and height != image.height )): | |
print("resizing: {0}".format(name)) | |
image = image.resize((width, height), Image.LANCZOS) | |
arr = numpy.array(image) | |
if(image.mode == "L"): | |
#we just copy the same channel 3 times as it's black and white. Else we get one single colour which isn't right | |
channels = [arr[:,:], arr[:,:], arr[:,:]] | |
elif(image.mode =="RGB"): | |
channels = [arr[:,:,0], arr[:,:,1], arr[:,:,2]] | |
elif image.mode == "RGBA": | |
channels = [arr[:,:,0], arr[:,:,1], arr[:,:,2], arr[:,:,3]] | |
newLayer = nested_layers.Image(name=name, visible=visible, opacity=opacity, group_id=group_id, blend_mode=blend_mode, top=y, left=x, channels=channels, metadata=metadata, layer_color=layer_color, color_mode=color_mode) | |
return newLayer | |
#albedo_group for making psd grouping later | |
albedo_group = None | |
#overall layers list for later psd saving | |
layers = [] | |
pillowImage = Image.open("pathToImage") | |
#make a new layer | |
newLayer = pillow_image_to_pyto_image(imageName, pillowImage, xPos, yPos, True, 255, 0, enums.BlendMode.normal, None, 0, None, width = (optional but if filled in will resize image), height = (optional but if filled in will resize image)) | |
if not albedo_group: | |
#make albedo group if it doesn't exist already | |
albedo_group = nested_layers.Group(name="albedo", visible=True, opacity=255, group_id=0, | |
blend_mode=enums.BlendMode.normal, | |
layers=None, closed=True, metadata=None, | |
layer_color=0) | |
#add the group to the layers list. We also have the albedo_group so we can add layers easier later | |
layers.append(mro_group) | |
#if you wanted to add the layer to be under the albedo_group in the psd | |
#albedo_group.append(newLayer) | |
#else | |
#layers.append(newLayer) | |
#you can save layers returned from this into just a regular list and then at the end (after doing whatever) | |
output = nested_layers.nested_layers_to_psd(layers, color_mode=3) | |
#save out Image. | |
with open("psd/path/name", 'wb') as fd: | |
output.write(fd) | |
#Helper function for resizing images with Alpha | |
#for some reason pillow butchers channels when it has alpha, this resizes channels individually instead and keeps the data correct. | |
def PNG_ResizeKeepTransparency(sourceImg, new_width=0, new_height=0, resample=Image.LANCZOS): | |
# open PNG image path and name | |
img = sourceImg.convert("RGBA") # convert to RGBA channels | |
width, height = img.size # get initial size | |
# split image by channels (bands) and resize by channels | |
img.load() | |
bands = img.split() | |
bands = [b.resize((new_width, new_height), resample) for b in bands] | |
# merge the channels after individual resize | |
img = Image.merge('RGBA', bands) | |
return img |
Thank you so much, I finally found how to write several layers to a psd file.
Sorry for my English, i'm Ukrainian.
Thank you so much, I finally found how to write several layers to a psd file.
Sorry for my English, i'm Ukrainian.
No worries, glad it helps :)
I'm looking for a way to convert psb images to png images. That's when I became aware of pytoshop. I haven't found an example where this is done. Does anyone here know one?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ran a test where this was fed 98 textures and created a 4k atlas with all the textures placed correctly (think it was ~30 some models with, albedo, norm and an extra texture) in less than 4 seconds. PLUS saving out the 4k images as well.