Skip to main content

[JAI-IMAGEIO] API for reading layers in PSDImageReader (Photoshop Document format)

4 replies [Last post]
Anonymous

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Harald Kuhr

Hi,

I've been developing an ImageIO plugin to read Photoshop Document
format for some time, and would like some input on the best way to
expose layers through the API.

Pixel data and thumbnail support is quite complete, but in addition,
I'd like to expose the image data in the various Photoshop layers (the
actual reading is already implemented). What would be the best way to
expose this functionality?

a) A new API like readLayer(int index, ImageReadParam param), or
readLayer(int imageIndex, int layerIndex, ImageReadParam param). The
latter is useful in case there should be a format that supports multi-
framed layered data. This is also in line with the readThumbnail(int
imageIndex, int thumbnailIndex). Anyone know of other image formats
that has a concept of layers?

b) Use existing read(int index ImageReadParam param) method, with
indexes < 0 or > getNumImages (breaking the contract of the read
method). It's clearly a hack, but it avoids extra API.. You still need
to know how this works though, so it may not mean anything in practice.

c) None of the above. Please suggest. :-)

Another question is where to put the layer blending data (opacity,
visibility, blend mode etc)? I'd like to put it close to the image
data, perhaps available through BufferedImage.getProperty(..).
However, the properties are read-only and only exposed at creation-
time. And the ImageReader does not neccesarily create the BI. So I
guess I need to invent something similar to IIOImage to achieve that.

Another possibility is to just leave the blending data as metadata,
and leave it to third party to figure out the details.

What do you think? I'd be happy to hear your thougts!

Best regards,

--
Harald K

PS: This is a copy of a mail sendt to users@twelvemonkeys-imageio.dev.java.net
, resent to reach a wider audience.

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Bob Deen

Cool! A photoshop plugin would be quite handy.

I haven't thought deeply about this, but a few things come to mind.

Could layers simply be represented using the image index? Each layer is
a different "image" in that context. So getNumImages() would return
numLayers. This seems to make the most sense if the format doesn't
support multiple actual images in the file. The layers really are
separate images, so this actually makes sense.

You could have an option on ImageReadParam that says to read as layers
or as flattened. Presumably the default would be flat, but you could
turn on layered read if you wanted it and knew how to deal with it. It
would require opening the file a second time to switch, but that doesn't
sound horrible.

If using the image index is not viable, then you could also have a layer
number as part of ImageReadParam and treat each layer as a completely
separate entity. Not super nice but might work.

JAI has a class called RenderedImageList which can contain a set of
images. It would seem to be a natural for holding the layers, but I'm
not sure how you get to there from the IIO plugin. We did some work
along those lines several years ago but the relevant brain cells have
died off. ;-/ We were looking at jpeg2000 and having the multiple
resolutions come out of the IIO plugin and into a RIL... but I don't
remember the mechanism. Might have used the index #, I'm not sure. But
that might be somewhere to look.

I didn't follow what the problem was with the metadata. Can't you use
ImageReader.getImageMetadata (or getStreamMetadata)? Even if the
getProperty() stuff is only available at creation time, that shouldn't
be a problem since you should know what the values are at BI creation
time, right? And I'm not so sure about BI but I know RenderedImage
allows for dynamically-created properties (they may need to be immutable
per contract but can be dynamically created).

Anyway, it's a random collection of thoughts but hopefully it'll help.

-Bob

Harald Kuhr wrote:
> Hi,
>
> I've been developing an ImageIO plugin to read Photoshop Document format
> for some time, and would like some input on the best way to expose
> layers through the API.
>
> Pixel data and thumbnail support is quite complete, but in addition, I'd
> like to expose the image data in the various Photoshop layers (the
> actual reading is already implemented). What would be the best way to
> expose this functionality?
>
> a) A new API like readLayer(int index, ImageReadParam param), or
> readLayer(int imageIndex, int layerIndex, ImageReadParam param). The
> latter is useful in case there should be a format that supports
> multi-framed layered data. This is also in line with the
> readThumbnail(int imageIndex, int thumbnailIndex). Anyone know of other
> image formats that has a concept of layers?
>
> b) Use existing read(int index ImageReadParam param) method, with
> indexes < 0 or > getNumImages (breaking the contract of the read
> method). It's clearly a hack, but it avoids extra API.. You still need
> to know how this works though, so it may not mean anything in practice.
>
> c) None of the above. Please suggest. :-)
>
> Another question is where to put the layer blending data (opacity,
> visibility, blend mode etc)? I'd like to put it close to the image data,
> perhaps available through BufferedImage.getProperty(..). However, the
> properties are read-only and only exposed at creation-time. And the
> ImageReader does not neccesarily create the BI. So I guess I need to
> invent something similar to IIOImage to achieve that.
>
> Another possibility is to just leave the blending data as metadata, and
> leave it to third party to figure out the details.
>
> What do you think? I'd be happy to hear your thougts!
>
>
> Best regards,
>

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Harald Kuhr

Hi Bob,

Thanks a lot for your thoughts and suggestions! :-) Appreciate it.

I must say don't really like using the read method's index for layers,
and having getNumImages() return the number of layers (plus one for
the composite image*) becuase there really is only one "image" in the
PSD file (made up of the different layers). It's not like a multi-page
TIFF, for instance, where there are distinct images for each page. The
layer data is more useful if you have a specialized application that
knows how to deal with them IMO. But it would of course work.

Using the ImageReadParam to specify a singe layer instead of the
composite image is an interesting option. I thought about it after
posting the message, actually, and I like it. But wouldn't it be weird
to query the read param for the number of layers? Or decode the meta
data first? Hmm.. I'll investigate this a little more.

Reading all the layers in one go, using readAsRenderedImage and using
the JAI RenderedImageList (or something similar) might work too.. I'll
have to read up on that though, as I haven't really used JAI a lot.
Great pointer anyway!

The problem with the BufferedImage properties only being exposed at
creation time, is that client code can pass in the destination BI as
part of the ImageReadParam. Or it can specify a BI of certain type or
pixel layout using ImageTypeSpecifier, which has it's own factory
methods. So the ImageReader doesn't really control the creation in
most cases. readAsRenderedImage has more relaxed semantics in this
regard, so it might just be possible.

But just putting the data into the metadata/stream metadata should
work, and something I should do anyway. Metadata is currently on my
todo-list though.

*) Just a note, the PSD file contains a composite image in addition to
the layer data for the convenience of image viewers/readers, so we
don't have to implement all the layer effects and composition magic
(thanks Adobe! ;-) ).

Regards,

--
Harald K

On 30. okt.. 2009, at 21.49, Bob Deen wrote:

> Cool! A photoshop plugin would be quite handy.
>
> I haven't thought deeply about this, but a few things come to mind.
>
> Could layers simply be represented using the image index? Each
> layer is a different "image" in that context. So getNumImages()
> would return numLayers. This seems to make the most sense if the
> format doesn't support multiple actual images in the file. The
> layers really are separate images, so this actually makes sense.
>
> You could have an option on ImageReadParam that says to read as
> layers or as flattened. Presumably the default would be flat, but
> you could turn on layered read if you wanted it and knew how to deal
> with it. It would require opening the file a second time to switch,
> but that doesn't sound horrible.
>
> If using the image index is not viable, then you could also have a
> layer number as part of ImageReadParam and treat each layer as a
> completely separate entity. Not super nice but might work.
>
> JAI has a class called RenderedImageList which can contain a set of
> images. It would seem to be a natural for holding the layers, but
> I'm not sure how you get to there from the IIO plugin. We did some
> work along those lines several years ago but the relevant brain
> cells have died off. ;-/ We were looking at jpeg2000 and having
> the multiple resolutions come out of the IIO plugin and into a
> RIL... but I don't remember the mechanism. Might have used the
> index #, I'm not sure. But that might be somewhere to look.
>
> I didn't follow what the problem was with the metadata. Can't you
> use ImageReader.getImageMetadata (or getStreamMetadata)? Even if
> the getProperty() stuff is only available at creation time, that
> shouldn't be a problem since you should know what the values are at
> BI creation time, right? And I'm not so sure about BI but I know
> RenderedImage allows for dynamically-created properties (they may
> need to be immutable per contract but can be dynamically created).
>
> Anyway, it's a random collection of thoughts but hopefully it'll help.
>
> -Bob
>
> Harald Kuhr wrote:
>> Hi,
>> I've been developing an ImageIO plugin to read Photoshop Document
>> format for some time, and would like some input on the best way to
>> expose layers through the API.
>> Pixel data and thumbnail support is quite complete, but in
>> addition, I'd like to expose the image data in the various
>> Photoshop layers (the actual reading is already implemented). What
>> would be the best way to expose this functionality?
>> a) A new API like readLayer(int index, ImageReadParam param), or
>> readLayer(int imageIndex, int layerIndex, ImageReadParam param).
>> The latter is useful in case there should be a format that
>> supports multi-framed layered data. This is also in line with the
>> readThumbnail(int imageIndex, int thumbnailIndex). Anyone know of
>> other image formats that has a concept of layers?
>> b) Use existing read(int index ImageReadParam param) method, with
>> indexes < 0 or > getNumImages (breaking the contract of the read
>> method). It's clearly a hack, but it avoids extra API.. You still
>> need to know how this works though, so it may not mean anything in
>> practice.
>> c) None of the above. Please suggest. :-)
>> Another question is where to put the layer blending data (opacity,
>> visibility, blend mode etc)? I'd like to put it close to the image
>> data, perhaps available through BufferedImage.getProperty(..).
>> However, the properties are read-only and only exposed at creation-
>> time. And the ImageReader does not neccesarily create the BI. So I
>> guess I need to invent something similar to IIOImage to achieve that.
>> Another possibility is to just leave the blending data as metadata,
>> and leave it to third party to figure out the details.
>> What do you think? I'd be happy to hear your thougts!
>> Best regards,
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-
> imageio.dev.java.net
>

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Bob Deen

Hi Harald...

For me it seems rather natural to treat each layer as a separate
"image". I think it meets the semantic definition of "image", or at
least close enough. Even though they are logically parts of the same
entity, they really are different images in their own right. Any
collection of multiple images in the same file are going to be related
in some way, after all... frames from a movie, a slideshow, layers.

I might suggest a combination approach. If you don't use
ImageReadParam, or set it to the default, then you get only the
composite image... no layers. Metadata could indicate layers are
present, but you wouldn't see them. This would make it compatible with
most image programs out there, who don't understand layers.

But then if you set the parameter in ImageReadParam, what you get
instead is the set of layers, as different images (with or without the
composite too, your choice). So programs that do understand layers
would be able to access them easily, via a convenient API.

Another alternative to the ImageReadParam is to actually have different
readers... one that returns layers, one that doesn't. Same effect, but
*might* be easier to use. It would allow a program that understands
multiple images but not layers per se to read the layers without
modification, just by mucking around with the order in which the readers
are registered.

Anyway, it sounds like you're doing good work... keep it up! ;-)

-Bob

Harald Kuhr wrote:
> Hi Bob,
>
> Thanks a lot for your thoughts and suggestions! :-) Appreciate it.
>
> I must say don't really like using the read method's index for layers,
> and having getNumImages() return the number of layers (plus one for the
> composite image*) becuase there really is only one "image" in the PSD
> file (made up of the different layers). It's not like a multi-page TIFF,
> for instance, where there are distinct images for each page. The layer
> data is more useful if you have a specialized application that knows how
> to deal with them IMO. But it would of course work.
>
> Using the ImageReadParam to specify a singe layer instead of the
> composite image is an interesting option. I thought about it after
> posting the message, actually, and I like it. But wouldn't it be weird
> to query the read param for the number of layers? Or decode the meta
> data first? Hmm.. I'll investigate this a little more.
>
> Reading all the layers in one go, using readAsRenderedImage and using
> the JAI RenderedImageList (or something similar) might work too.. I'll
> have to read up on that though, as I haven't really used JAI a lot.
> Great pointer anyway!
>
> The problem with the BufferedImage properties only being exposed at
> creation time, is that client code can pass in the destination BI as
> part of the ImageReadParam. Or it can specify a BI of certain type or
> pixel layout using ImageTypeSpecifier, which has it's own factory
> methods. So the ImageReader doesn't really control the creation in most
> cases. readAsRenderedImage has more relaxed semantics in this regard, so
> it might just be possible.
>
> But just putting the data into the metadata/stream metadata should work,
> and something I should do anyway. Metadata is currently on my todo-list
> though.
>
>
> *) Just a note, the PSD file contains a composite image in addition to
> the layer data for the convenience of image viewers/readers, so we don't
> have to implement all the layer effects and composition magic (thanks
> Adobe! ;-) ).
>
>
> Regards,
>

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net