Hi Geert,
Since it could be a while before I'm able to make a significant code
contribution, I'll reply to what can be done right away. :)
See the rest inline...
Shalom,
Josh
--
Joshua Hansen
Up Bear Enterprises
(541) 760-7685
Geert Bevin wrote:
Hi Joshua,
I think the heart of my question is really a question about the
performance of java.awt.Image. :) If the performance (speed, memory)
of java.awt.Image is poor, then that creates a bottleneck in
transforming images and loading them (and their properties) into the
database. So, abstracting to allow a drop-in representation or
library seems logical and an additional advantage. :) However, "don't
guess, measure", eh? :)
java.awt.Image is the most basic of Image classes possible, other image
classes extend this one. So it should be totally appropriate as the
common data vehicle for image handling and transformation.
My specific task is that I'm building a photo gallery app, and I want
to generate 3 (maybe more) versions of an uploaded file. Since there
could potentially be a lot of files uploaded, it would be nice to have
"low" memory and CPU usage.
Well, the thing is that if you want to resize, convert or transform an
image, you need to load it into memory at some point in time. If you
just want to store the image, you can stream it straight to the content
manager framework using the RAW target mime type.
Image transform-wise, I've run into a situation (twice now) where I
set a 'width' or 'height' value, but the orientation of some of the
images is opposite which causes it to be scaled incorrectly (i.e. both
1200x1600 images and 1600x1200 images should use the same scaling
ratio but simply setting a width or height doesn't give this result),
so I created a transformer which uses attributes 'short-edge-length'
and 'long-edge-length', which does just what I want. Yay! :)
I wonder if this class that you added to the wiki should be included
into RIFE and use a content attribute to make the CMF to adopt it. What
do you think?
I think it's a good complement to the 'width' and 'height' setters, so
yeah, it would be a useful item to have in the CMF.
Before I go on and talk about RIFE, I'll say that I'm still a little
fuzzy on the workflow for how an image (file) goes from the temporary
upload directory through the transformers, validator(s) and into the
database.
Does this answer your question?
http://rifers.org/wiki/display/RIFE/Content+management+framework#Contentmanagementframework-2
That document is really helpful, and I spent some time looking at it
(and will be spending more), but what I was referring to is how some of
the items get instantiated, then get referenced, and finally get
invoked. That document shows what happens ultimately, but the actual
sequence of class instantiations, references, and then method calls is
not as straight-forward. I think it will just come from spending more
time with it. :) You are also making heavy use of Java 5.0 features too
(which is great), which I'm still coming up to speed on, so that's
something else for me.
MimeType: Yes, making the constructor public would allow additional
MimeTypes. Would it also allow overriding the static MimeTypes?
It should. Can you please add a Jira issue for this?
Done. Suggestion: Add a 'cmf' component to Jira. I filed it in
Unknown, and against 1.4 (since that's what's I'm using), and marked it
bite-size with the assumption that the only change is to make the
constructor protected or public. I'll leave it to you to change make
any relevant adjustments.
Good thing or bad thing since they would need to be changed before
DatabaseImageStore is instantiated? Would a Participant be able to
handle this, like the ResourceFinder mechanism?
Yes.
Cool.
DatabaseImageStore: The only thing here that is obviously image
specific is getContentForHtml(), and that's not image type specific,
so pulling the list of MimeTypes from something that could be
overridden seems possible, though I don't have any quick and elegant
ideas about how to do it either. BTW -- it seems weird to me that
getContentForHtml() is in this class. I suspect I keep think of
'Store' as a verb when it's really a noun. :)
It is indeed a noun in this case ;-)
Other notes, and ideas...
In looking at ImageFormatter, the scaling feature (setting the
width/height) seems like it should really be extracted as a separate
content transformer. Conversion from various formats to jpg should
also be considered transforms (a single 'jumbo' converter transformer
could be used). This leaves the storage mechanism as a validator ("Is
what I'm getting an actual jpeg?") and property extractor (width,
height, whatever you like). (Maybe property extractor should be
considered a type of transformer too? But, leave that question for
later.)
These would indeed be good refactorings, something that should be added
then too is some way of registering multiple transformers and to be able
to specify their order. Feel free to propose a approach for this. You
seem to have a good chain of thoughts going on here with (what looks
like) a very distinct goal. This is a perfect opportunity to contribute
to the project!
I think this approach has a couple advantages. The conversion from
arbitrary formats becomes explicit which allows the user the option to
reject non-jpeg files (such as a case where conversion could introduce
artifacts and so you want to enforce/provide a strict
garbage-in-garbage-out behavior).
True, though one thing to consider is that the CMF should somehow know
which transformers to use based on the content attributes that are
provided. Maybe we should just iterate through all the active
transformers and each one decides if the transformations need to be
performed or not.
See below...
Another aspect is that it allows for lightweight analysis tools. A
shortcut validator (again, this could be a decision by the user) could
potentially just analyze the header and extract properties from it
which makes it very low impact on cpu and memory.
Interesting idea, indeed.
Maybe a convenient addition to the ConstrainedProperty api would be to
support multiple transformers. But, it isn't it's required to have
this, since a single custom transformer can be written which just
calls each of the additional desired transformers.
See, we're on the same page ;-)
Haha! :) I think the ConstrainedProperty API could be modified to have
an 'addTransformer(ContentTransformer)' method. This would be a list of
transformers, ordered by the call to addTransformer().
Example:
[in the MetaData class]
addConstraint(new ConstrainedProperty("imageMedium")
.notNull(true)
.file(true)
.editable(false)
.mimeType(MimeType.IMAGE_JPEG)
.contentAttribute("long-edge-length", 240)
.addTransformer(new PhotoScalingImageTransformer())
.addTransformer(new GreyScaleTransformer()))
);
This would result in 2 transformers being added to a list of
transformers to be executed for the 'imageMedium' property. They would
be executed in order, and each determine their activity based on the
provided attributes. The example above could represent a flow which
then scales the image by the longest edge, then converts the scaled
image to greyscale.
The existing ConstrainedProperty.transformer() method could be modified
to call the addTransformer() method, making the whole thing backwards
compatible.
As I think about it, teasing out the image conversion (from non-jpg to
jpg) will be more difficult, so, I'm just leaving it as is for this
discussion. :)
Sorry I don't have more constructive/concrete suggestions. I'll keep
thinking about it. The more I work w/ the framework, the more I
understand what it's doing and intent. :)
Cool :-)
I'll take a look into the RAW type again. I got stuck with file
uploads and mime-types when I first plunged into RIFE, and I've
learned a lot since then. Heck, I've learned a lot since 2 nights
ago. :)
At any rate, I think adding MimeTypes would be a big advantage. There
are a lot of MimeTypes out there, and being able to publish and
download additional handlers would be awesome. Now that I think about
it, maybe the whole CMF system should really be constructed in terms
of pluggable MimeType handlers, then provide some default
implementations for the currently supported types.
Again, I agree that this should be investigated. When I created the
current limited set of enum mime-types, I did realize that it was not
flexible enough and that should would probably have to be changed and
refactored later. Seems this time has come :-)
Thanks again for an awesome framework! :)
Thanks :-) Please consider contributing code that reflects your ideas,
so that RIFE becomes even better.
I'm starting to plan on it, particularly since I'm getting further into
it and am seeing some opportunities for contribution! :)
Shalom,
Josh
Take care,
Geert
Shalom,
Josh
Geert Bevin wrote:
Hi Joshua,
currently there is no extension mechanism for this, but I'm willing
to look into any proposals since this rigidness has always troubled
me. With the enum mechanism that we use in RIFE, you can add any
other MimeType but the constructor is currently too closed down,
maybe it should just be made public. This means that you would be
able to add new MimeTypes.
One thing that you have to realize though, is that MimeType entries
specify how they they are validated and formatted, they don't however
indicate where they need to be stored. This is a tricky thing to
solve since the content storage back-ends are abstracted away and
currently detect directly on the MimeType enum elements (they provide
a collection of MimeTypes that they're able to handle). When you add
your custom MimeTypes, those storage backe-end wouldn't be able to
handle them though. This is sadly currently hardcoded in the
constructor of the DatabaseContent class and ideally it should be
opened up. Doing this, you could add your own content store (that
could extend an existing one) and add the MimeTypes that this one
supports.
I'm curious to see what you want to do with a custom IMAGE_JPEG
loader/formatter? What actually happens is that RIFE tried to load
any possible image, not just JPEGS. To do this is goes over the image
loader backends it knows about. These are setup in
ImageContentLoader. Ideally, this order should also become
configurable. The JPEG type is only used for the format of the final
image storage (the loaded image will be transformed into the target
type). If you just want to store anything as-is, use the RAW type.
Note that you can always change and interact with your content by
using a ContentTransformer. We chose to use the standard
java.awt.Image type as the format into which to load the images
before writing them out again. If you want another type, you can use
the RAW type with your own ContentTransform to handle it the way you
want.
Hope this helps.
Best regards,
Geert
On 08 Dec 2006, at 17:56, Joshua Hansen wrote:
Hi Geert (and others),
I've been working a little with the CMF and I was wondering: is it
possible to specify a custom MimeType class? I can't extend it
because the constructor is private, and I can't reset the static
enum defs (IMAGE_JPEG, IMAGE_PNG, etc) with custom versions for the
same reason.
I'd like to add new MimeTypes, and or replace existing types, such
as to use a custom IMAGE_JPEG loader/formatter. A specific example
would be to use a more efficient third party or native library for
image manipulation/handling (instead of java.awt.Image).
I'm using RIFE 1.4.
Shalom (complete peace),
Josh
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
--Geert Bevin
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
--
Geert Bevin
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users