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

Support text layers #20

Open ok-nick opened 3 years ago

ok-nick commented 3 years ago

I'm trying to access the text data (font/text) from a text layer. Is this currently possible or is it possible to support?

chinedufn commented 3 years ago

Hey there.

Text layers aren't current supported, but I'd love for them to be supported in psd.

The first step would be to check the spec to find out how text is stored.

Followed by parsing out the data from the appropriate section.


So, it currently isn't possible in psd, but it's definitely possible to support.

ok-nick commented 3 years ago

@chinedufn I've never done something like this, but it seems really interesting. I've actually hit a bit of a snag and wondering you had any suggestions.

In the file src/sections/layer_and_mask_information_section/mod.rs, at the bottom, I check if the key is TySh and read all that info by doing (psuedocode):

cursor.read_2()?; // Version
cursor.read(48)?; // Transformation
cursor.read_2()?; // Text version
cursor.read_4()?; // Descriptor version

The text version returns [0, 50], while the descriptor version returns [0, 0, 0, 16], which seems correct?

From here I get into the actual structure and as it says, I read the unicode string, which seems to be just an empty string, at least in my psd:

cursor.read_unicode_string()?; // name from classID

After this, I read the classID, this is where I implement a simple yet exact replica of the described method into the cursor:

pub fn read_ascii_string(&mut self) -> Result<String, Error> {
    let mut length = self.read_u32()?;
    if length == 0 {
        length = 4;
    }

    let mut result = String::new();
    for _ in 0..length {
        let bytes = self.read_u8()?;
        result.push(bytes as char);
    }

    Ok(result)
}
cursor.read_ascii_string()?; // classID

I've implemented a little past this point, but it seems that when I call read_ascii_string, it has a length of 21624 characters, the image below is what it ends up returning: image

Any suggestions on what I could or am doing wrong?

chinedufn commented 3 years ago

I'm excited that you're diving in here. I'm more than happy to help wherever I can.

Could you make a really simple, small PSD file with a text layer in it and then add it to the fixtures folder

Then add a text_layer.rs to the integration tests folder along with a failing test case. (Let me know if you need any help on how to do this).

From there, if you can push up your code I can pull it and take a look and see if I notice anything.

Thanks for diving into this. I'm glad that it looks like you're close to having it working.

ok-nick commented 3 years ago

@chinedufn https://github.com/ok-nick/psd cargo test --test layer_and_mask_information_section text_layer -- --exact The test is located in tests/layer_and_mast_information_section.rs at the bottom.

chinedufn commented 3 years ago

Hey. Just a heads up that this is still on my radar but I haven't gotten to it yet. Not sure how time sensitive it is for you.