chinedufn / psd

A Rust API for parsing and working with PSD files.
https://chinedufn.github.io/psd
Apache License 2.0
265 stars 40 forks source link

Cropping a layer based on it's content #22

Closed ok-nick closed 3 years ago

ok-nick commented 3 years ago

I'm assuming this isn't currently supported and I was looking at a few dependencies that do, but they include a lot of other stuff outside of psd's scope. I was planning on doing this externally, but would it cause further optimizations if done internally? Any pointers on how it could be done? My goal is to export a layer as a png, excluding any white space. I'm currently using the layer.rgba() method

ok-nick commented 3 years ago

Also quick question, how would you suggest exporting the return from layer.rgba() as a png?

chinedufn commented 3 years ago

Here's a quick example of creating an image::DynamicImage.

use image::{DynamicImage, GenericImage, Rgba};
use psd::Psd;

pub fn img_from_psd(psd: &Psd) -> DynamicImage {
    let pixels = psd.rgba();
    let pixel_count = pixels.len() / 4;

    let mut img = DynamicImage::new_rgba8(psd.width(), psd.height());

    for idx in 0..pixel_count {
        let x = idx as u32 % psd.width();
        let y = idx as u32 / psd.width();

        let mut pixel = [0; 4];
        let pixel_slice = &pixels[4 * idx..4 * idx + 4];
        pixel.copy_from_slice(pixel_slice);

        img.put_pixel(x, y, Rgba(pixel))
    }

    img
}

The image crate has methods for cropping as well as other image manipulation functions.

If you only need a PNG with no image manipulation you can also take a look at https://docs.rs/png/0.16.8/png/#using-the-encoder


I think you're right that something like cropping belongs outside of the psd crate.

Let me know if you need any more help with this issue, otherwise best of luck.

chinedufn commented 3 years ago

My goal is to export a layer as a png, excluding any white space.

Oh, and for the excluding any white space portion.

You can handle this with the image crate.

One brute force way:

You'll end up with the left, top, right and bottom crop coordinates. Then just call https://docs.rs/image/0.23.13/image/imageops/fn.crop.html

chinedufn commented 3 years ago

Here's a much simpler way to get an Image from a psd.

let img: image::ImageBuffer<image::Rgba<u8>, Vec<u8>> =
                image::ImageBuffer::from_vec(psd.width(), psd.height(), psd.pixels()).unwrap();
img.save("/tmp/foo.png").unwrap();