1 unstable release

0.4.0 Nov 16, 2023

#4 in #psd

Download history 37/week @ 2023-11-16 17/week @ 2023-11-23 17/week @ 2023-11-30 19/week @ 2023-12-07 12/week @ 2023-12-14 10/week @ 2023-12-21 6/week @ 2023-12-28 8/week @ 2024-01-04 17/week @ 2024-01-11 10/week @ 2024-01-18 17/week @ 2024-01-25 14/week @ 2024-02-01 15/week @ 2024-02-08 35/week @ 2024-02-15

82 downloads per month
Used in zune-image

MIT OR Apache-2.0 OR Zlib

1.5K SLoC


A simple photoshop reader.

This crate doesn't handle any fancy photoshop features, including layering, blending,metadata extraction and such, it simply copies some bytes it believes are the base layer hence it may not suit your needs


  1. First include it into your Cargo.toml
cargo add zune-psd

or include it directory in your Cargo.toml


Then use either one of the decode_ variants to get pixel data decode_raw will always return Vec<u8> while decode distinguishes return type via image depth (either 8-bit or 16-bit)


The decoder is fairly fast, we don't do any fancy processing so there is no need to compare it with other crates (I'm not sure any supports full parsing), hence there are no benchmarks.


The crate is fuzz tested in CI to ensure untrusted input does not cause a panic


A simple PSD decoder

This crate features a simple Photoshop PSD reader

What it means by simple

Photoshop is a complicated format, probably one of the most complicated format, this library doesn't claim to parse a lot of the images photoshop and it's derivatives will generate.

It does not check layers, doesn't like CMYKa images, only reads Grayscale, RGB and RGBA images ignoring Dutone, Multichannel and a slew of other .PSD features I've never heard of. It's as simple as it gets.

Sometimes that's all you need..

obligatory photoshop dunking


  • Reading a psd file
use zune_psd::errors::PSDDecodeErrors;
use zune_core::result::DecodingResult;
use zune_psd::PSDDecoder;

fn main()->Result<(),PSDDecodeErrors>{
    let mut decoder = PSDDecoder::new(&[]);
    let px = decoder.decode()?;

    // we need to handle u8 and u16 since the decoder supports those depths
    match px {
        DecodingResult::U8(_) => {}
        DecodingResult::U16(_) => {}