Add the RecursiveAI.OneImage.Psd package, register PsdFormat in the load options, load the PSD and save it as .png. You get the whole document as Photoshop composited it. To work with the layers, PsdFile.Load returns the layer tree. The program below converts layer_effects.psd, an 800×640 test file from the MIT-licensed psd-tools project.
dotnet new console -o PsdToPng && cd PsdToPng dotnet add package RecursiveAI.OneImage.Psd --version 1.10.4 repo=https://raw.githubusercontent.com/psd-tools/psd-tools/main curl -L -o layer_effects.psd $repo/tests/psd_files/layer_effects.psd
OneImage needs the .NET 10 SDK. Put this in Program.cs and run dotnet run:
using OneImage; using OneImage.Psd; // PSD is an add-on format: register it for the load. var options = new LoadOptions { Configuration = new ImageConfiguration().Add(PsdFormat.Instance), }; Image design = Image.Load("layer_effects.psd", options); design.Save("layer_effects.png"); // JPEG has no transparency: put it on white. Thumbnail makes a web preview. design.Flatten(new Rgba32(255, 255, 255, 255)).Save("layer_effects.jpg"); Image.Thumbnail(design, 400).Save("preview.webp"); foreach (string file in new[] { "layer_effects.png", "layer_effects.jpg", "preview.webp" }) { ImageInfo info = Image.Identify(file); Console.WriteLine($"{file}: {info.Width}x{info.Height}"); }
layer_effects.png: 800x640 layer_effects.jpg: 800x640 preview.webp: 400x320
When the PSD carries a merged copy of the document, that is what Load returns, so the PNG matches what Photoshop showed. A file without one is drawn from its layers. PSB (large document) files load the same way, and CMYK and Lab documents are converted to RGB.
List and export the layers
using OneImage.Layers; using OneImage.Psd; using PsdFile psd = PsdFile.Load("layer_effects.psd"); Directory.CreateDirectory("layers"); int index = 0; foreach (Layer layer in psd.Document.Root.Children) // groups have Children too { index++; string size = $"{layer.Bounds.Width}x{layer.Bounds.Height}"; Console.WriteLine($"{layer.Kind} \"{layer.Name}\" {size}"); if (layer is PixelLayer pixels) { // The layer's own pixels, at the layer's size. pixels.Pixels.Snapshot().Save($"layers/{index:00}.png"); } }
Pixel "Background" 800x640 Pixel "Bevel" 190x47 Pixel "Emboss" 270x47 Pixel "Outer Glow" 399x48 Pixel "Inner Glow" 384x48 Pixel "Inner Shadow" 484x48 Pixel "Color Fill" 481x60 Pixel "Drop Shadow" 465x59 Pixel "Gradient Overlay" 600x60 Pixel "Pattern Overlay" 555x60 Pixel "Stroke" 232x48 Pixel "Satin" 180x48
An exported layer holds its own pixels, without the effects drawn when the document is composited, and Bounds gives its position. To change the document, set a layer’s Visible, Opacity or blend mode, then psd.Document.Render() for a PNG or psd.Save("out.psd") for a Photoshop file.
Limits
- Text and smart objects keep their stored pixels. They aren’t re-laid out or re-rendered when you edit; they are written back unchanged.
- Renders follow Photoshop closely, not exactly. Layer effects, blend modes and adjustment layers are drawn by OneImage; the PSD docs list what is modelled and how it compares.
- Untrusted files are bounded: at most 20,000 layers, 64 levels of groups and 64 MiB per data block by default, checked before allocating.
For PDF and SVG, see Convert a PDF to an image and Convert SVG to PNG.