Skip to content

Instantly share code, notes, and snippets.

@TravisEvashkevich
Last active April 22, 2023 03:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TravisEvashkevich/390e100fddf1f9cd572b367446ccf547 to your computer and use it in GitHub Desktop.
Save TravisEvashkevich/390e100fddf1f9cd572b367446ccf547 to your computer and use it in GitHub Desktop.
Pytoshop and Pillow PSD Creation
#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
@TravisEvashkevich
Copy link
Author

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.

@Ruden2007
Copy link

Thank you so much, I finally found how to write several layers to a psd file.

Sorry for my English, i'm Ukrainian.

@TravisEvashkevich
Copy link
Author

TravisEvashkevich commented Aug 15, 2022

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 :)

@Spiri0
Copy link

Spiri0 commented Apr 22, 2023

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