2009/1/20 Steven Dolg <[email protected]>: > Andy Stevens schrieb: >> 2009/1/19 Steven Dolg <[email protected]>: >>> Vadim Gritsenko schrieb: >>>> On Jan 15, 2009, at 9:05 AM, Reinhard Pötz wrote: >>>> But question is, can you aggregate, include images? >>> >>> There is no component for that yet. But I'm confident this is easily >>> possible. >> >> Interesting problem - what exactly would an "aggregate" image be? The >> relevant parts side by side, one below the other, as separate layers >> in a combined image? If the latter, what "mode" would you use to >> combine them - blend/burn/multiply/as a mask - and what opacities? >> Should they be scaled to the same size before combining or not? >> Doesn't really fit with the usual map:aggregate/map:part without a ton >> of extra info as to how it should be done. >> > > Yes, we could easily end up with having thousands of possible ways users > would like to use. > > I thought about this and implemented a simple first approach > * use one image as the "background" > * use one image as the "overlay" > * define an anchor for the overlay (Center, North, South, Southeast, ...) > relative to the background > * allow for an additional offset to the anchor > * draw the overlay on the background, overwriting it - but applying existing > transparency information in the overlay > > [This is also the way Amazon does it: > e.g. > http://ecx.images-amazon.com/images/I/41CHSFA4GTL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg > "TopRight,35,-75" is anchor, offsetX, offsetY - try changing it, it's fun > ;-)] > > In the imaging module this would look like: > Pipeline pipeline = new NonCachingPipeline(); > > // the background > pipeline.addComponent(new ImageGenerator(backgroundUrl)); > // scale the background to a fixed size (to have a predictable > "background-to-overlay" size ratio) > pipeline.addComponent(new MaxSizeImageTransformer(200, 200)); > // apply the overlay (TopRight, slightly beyond the right and the top > border) > pipeline.addComponent(new AggregateImageTransformer(additionalUrl, > Anchor.NORTHEAST, 22, -20)); > // scale again to fixed size (overlay increases image size) > pipeline.addComponent(new MaxSizeImageTransformer(200, 200)); > // write the image > pipeline.addComponent(new ImageSerializer()); > > Theoretically this should allow to create what you called "combined images" > (if I understood your idea correct) as well as the "side by side" approach. > And this would only require 3 additional parameters (making the offset > optional would reduce it to one required parameter).
Yes, that'd work, although it's more akin to (in the "old" ways) <map:generate src="firstimage.jpg"/> <map:transform type="combineimages" src="secondimage.jpg"> <map:parameter ... (settings for how to position/combine them) /> ... rather than <map:aggregate> <map:part src="firstimage.jpg"/> <map:part src="secondimage.jpg"/> ... But perhaps I should have mentioned that I've not been following the C3 stuff, so I've no idea how things are done there... It was just the concept of image-based pipelines rather than XML-based ones that caught my imagination :-) > However blend/burn/multiply/as mask would certainly require more (and me > finding out what this actually means and how to achieve that :-) ). I was thinking along the lines of aggregation being equivalent to combining the images as layers, in which case there are a number of ways they could be combined e.g. see http://docs.gimp.org/en/gimp-concepts-layer-modes.html > As to the scaling (or generally transforming) before combining: I guess this > could be achieved by applying a transformation to the overlay before using > it. > In a sitemap this would be rather simple - with some little changes, this > should also be possible with the pure Pipeline API, like allowing the > AggregationImageTransformer (already existing on my machine, but yet to be > published) to read the overlay from an InputStream which is created by > another pipeline, or something like that. Indeed, in the same way as before you could have had <map:transform type="combineimages" src="cocoon:/secondimage"> where the secondimage pipeline reads secondimage.jpg and has a scaling transformer before its serialiser. > I still think it should be possible to provide some general purpose (and > rather basic) transformers. As long as you can combine them, a lot of > different effects should be possible. > E.g. the AggregateImageTransformer will increase the image size so that both > background and overlay are fully contained. If that's not desired, one can > apply an CropImageTransformer afterwards, cutting of the unwanted parts. > Of course this will require some more flexibility as some of the > configuration of the transformers must be determined while executing the > pipeline - but I think it should be possible in most cases... > >> OTOH, something like the include transformer might work better - an >> input document describing how the images should be combined, with >> :include elements specifying the various other input sources. But >> then you need a pipeline that handles both XML and image data... >> Sounds like fun ;-) >> > > Not sure I understand what you mean. > Is that like describing the image transformation in XML and having a > transformer evaluate the XML and then process images based on that > description? I guess I was thinking something like how in the past you could aggregate XML pipelines using <map:aggregate> or by using the cinclude/xinclude transformer. So you could have an XML document, say, with <imagecombine:include> elements that describe how to combine the images and when you run that through the imageinclude transformer it outputs the aggregated image. Doesn't really work with a pure image pipeline, unless you can figure out some way to nest the include commands in the first image (EXIF-type metadata, maybe?), hence the use of an XML input document. But it has the advantage over a purely pipeline-based aggregation that the images to be combined (and how to combine them) could be generated dynamically by some other pipeline or transformation (SQLTransformer with SELECT image, transformation FROM IMAGE_LIST, XSLed into the relevant input document, anyone?) > I think such an approach would limit the usage scenarios for the > transformer, as it could not be used after some other transformation that > returns only the resulting image. Well, you can't put a map:aggregate after another transformation either, you have to use the cocoon pseudo-protocol in the part's src. Not that different. > But I guess, we could have a transformer that is configured with an URL to > the XML document describing the transformation. That would even allow to > have another pipeline build that document (if that makes any sense) or > retrieving it from somewhere else - making it easier to adjust it during > runtime than having it directly in your code/sitemap/whatever. > > An interesting idea... It's amazing how many of those you can have when you're not limited by knowing what you're talking about ;-) Andy. -- http://pseudoq.sourceforge.net/
