[GIL] image rescale algorithms

Hi, I'm still working on updating my image management codebase, and I noticed that GIL does come only with by a very limited image rescaling/resampling algorithm (in gil/extension/numeric/resample.hpp) which does proper filtering for upsampling an image. As I need more robust image resampling, I came up with a source code for GIL, inspired by FreeImage implementation<http://freeimage.cvs.sourceforge.net/viewvc/freeimage/FreeImage/Source/FreeImageToolkit/>; this code is available here :: http://code.google.com/p/rotoglup-scratchpad/source/browse/trunk/#trunk/rtgu... This implementation is certainly not as generic as it could be, and could certainly benefit from 'gil concept checking' and various improvements ; I tried to make the code more 'readable' than 'efficient', and as I'm not really at ease with template metaprogramming, I may have missed a few points. For example, I think the mechanism I use to select the intermediate pixel format (used to store the averaged pixels during resizing) may be improved, and that there must be a way to let the user select a better pixel format if needed. I came up with virtual rescale view type, that allows to seamlessly rescale virtual views of any kind - it is not very efficient, but can be proved useful. I tried, as much as possible, to provide access to separable rescale functions (X & Y) so that users can control when/how (or whether) they should allocate the intermediate view for image rescaling. Feel free to use this work, and I'd be very happy to have some feedback on things that could be improved. The main functions defined are, in rescale.hpp<http://code.google.com/p/rotoglup-scratchpad/source/browse/trunk/rtgu/image/rescale.hpp>:: // horizontal rescale only, rescale src view into dst view, matching dst view width template <typename SrcView, typename DstView, typename Filter> inline void rescale_cols(const SrcView& src, const DstView& dst, const Filter& filter); // vertical rescale only, rescale src view into dst view, matching dst view height template <typename SrcView, typename DstView, typename Filter> inline void rescale_rows(const SrcView& src, const DstView& dst, const Filter& filter); // rescale src view into dst view, matching dst view dimensions template <typename SrcView, typename DstView, typename Filter> inline void rescale(const SrcView& src, const DstView& dst, const Filter& filter); in rescale_any_view.hpp<http://code.google.com/p/rotoglup-scratchpad/source/browse/trunk/rtgu/image/rescale_any_view.hpp>:: template <typename ViewTypes, typename Filter> inline void rescale_any_view(any_image_view<ViewTypes>& src, any_image_view<ViewTypes>& dst, const Filter& filter); in rescale_virtual_view.hpp<http://code.google.com/p/rotoglup-scratchpad/source/browse/trunk/rtgu/image/rescale_virtual_view.hpp>:: // view factories template <typename SourceView, typename Filter> typename rescale_x_view_type<SourceView>::view_t rescale_x_view(SourceView const& view, typename SourceView::coord_t dst_width, const Filter& filter); template <typename SourceView, typename Filter> typename rescale_y_view_type<SourceView>::view_t rescale_y_view(SourceView const& view, typename SourceView::coord_t dst_height, const Filter& filter); template <typename SourceView, typename Filter> typename rescale_view_type<SourceView>::view_t rescale_view(SourceView const& view, typename SourceView::coord_t dst_width, typename SourceView::coord_t dst_height, const Filter& filter); and a few filters<http://code.google.com/p/rotoglup-scratchpad/source/browse/trunk/rtgu/image/filters.hpp>are provided. Cheers, Nicolas. **

Hi Nicolas, I have been reading and testing some of your code, mainly the resampling part. It's great stuff! Thanks. Please read my comments. They are in random order and of different priorities: * You have created a clamp_channel_fn. Isn't that the same as gil's scoped_channel_value? * I would like to invite you to format your code with the appropriate headers into the boost format. I can help you here. * Can you use source code from the freeimage project and relabel it under the MIT license? * You define a vertical_flip algorithm. Did you notice gil's flipped_left_right_view? * I would move filters.hpp and filter_weight_table.hpp into your detail\ folder. * resample.hpp should include filters.hpp. * for writing test I recommend boost::test/ As, I said, I like your contribution. What do you think of adding it to my gil contribution subversion? This is place where people, including me, keep their submissions. I would add you as a member though you have the access permissions. The URL is http://code.google.com/p/gil-contributions/ . Another idea is to write a freeimage image reader and writer and add it to my gil::io_new project. What do you think of that? Regards, Christian

Hi Christian, thanks for your feedback. I'll try to answer your comments, reordered - comments to rescaling code first, then comments on other parts of the source code in my test repo : * I would like to invite you to format your code with the appropriate
headers into the boost format. I can help you here.
No problem, I'd certainly appreciate some help or guidelines on this point.
* Can you use source code from the freeimage project and relabel it
under the MIT license?
That's a question I already asked myself - but more to the point, I do not explicitly use FreeImage code 'as-is' - I went into a rewrite/refactor process on the code. The code I linked is closely related to the FreeImage source code only in filters.hpp and filter_weight_table.hpp, all other code is mine only. I shall take a look towards a complete rewrite, or taking bits and pieces of proven/tested public domain for these parts. * I would move filters.hpp and filter_weight_table.hpp into your detail\
folder.
I forgot to do it first hand for 'filter_weight_table.hpp', consider it done. For filters.hpp, as the constructs it defines are, IMO, not meant to be in a 'detail' namespace, I thought about letting it live with 'resample.hpp' * resample.hpp should include filters.hpp.
Does they physically depends one on another ? I think it is not the case (if it is, it's my mistake) - I'd more incline to have a 'resample_all.hpp' header to make it easy on users who don't care on compile times - but I may be nitpicking here. * for writing test I recommend boost::test/
I agree that boost::tests would be suitable for a proper boost::gil extension - but for now, the tests are tied to my specific needs, and I don't plan to use boost::test for my personal developments. Talking about this, I didn't get many ideas about how to properly unit test the rescale code. Apart from testing simple width/height results, it would need to test the source & rescaled image contents, and I don't know how to setup such a system. Any ideas ? According to the rest of your comments : * You have created a clamp_channel_fn. Isn't that the same as gil's
scoped_channel_value?
hm, I am under the impression that scoped_channel_value provides the min/max values for channel values, but have no mechanism to enforce that a value is clamped to these limits. Hence this algorithm. But I may be mistaken and may have missed an existing way of clamping values to channel limits. I saw nothing in channel.hpp.
* You define a vertical_flip algorithm. Did you notice gil's flipped_left_right_view?
Yep, in fact it would be 'flipped_up_down_view' - but this algorithm allows me to suit one of my 'personnal' needs to vertically flip the image memory representation inplace. Using 'flipped_up_down_view' would make do an image copy, and hence use twice as much memory. As, I said, I like your contribution. What do you think of adding it
to my gil contribution subversion? This is place where people, including me, keep their submissions. I would add you as a member though you have the access permissions. The URL is http://code.google.com/p/gil-contributions/ .
It would be a good idea, I need first to fix the few standing issues discussed before. Another idea is to write a freeimage image reader and writer and add
it to my gil::io_new project. What do you think of that?
It could be possible, but, IMHO, I'm not sure that it would fit in your io_new extension. My understanding is that your project aims to provide a 'standalone' image input/output library, and tying it to FreeImage may not be a good idea for a whole set of users. Maybe it would be better as a 'code snippet' that could used and modified by the people needing boost::gil and FreeImage. As I lack time, I'll be more willing to concentrate my work on resampling, that would be a nice extension to GIL, that on this FreeImage binding code. But feel free to precise your thoughts, I may be able to give you a hand on this. Cheers, Nicolas.

Nicolas,
* Can you use source code from the freeimage project and relabel it
under the MIT license?
That's a question I already asked myself - but more to the point, I do not explicitly use FreeImage code 'as-is' - I went into a rewrite/refactor process on the code. The code I linked is closely related to the FreeImage source code only in filters.hpp and filter_weight_table.hpp, all other code is mine only. I shall take a look towards a complete rewrite, or taking bits and pieces of proven/tested public domain for these parts.
I'm have really no idea if that's good enough or not. We could ask the freeimage people.
Does they physically depends one on another ? I think it is not the case (if it is, it's my mistake) - I'd more incline to have a 'resample_all.hpp' header to make it easy on users who don't care on compile times - but I may be nitpicking here.
resample_all is good enough, I believe.
* for writing test I recommend boost::test/
I agree that boost::tests would be suitable for a proper boost::gil extension - but for now, the tests are tied to my specific needs, and I don't plan to use boost::test for my personal developments. Talking about this, I didn't get many ideas about how to properly unit test the rescale code. Apart from testing simple width/height results, it would need to test the source & rescaled image contents, and I don't know how to setup such a system. Any ideas ?
For writing a gil extension I recommend boost::test. There is really no need to introduce another testing framework. For your own code, you can do what's best for you, of course. ;-)
* You define a vertical_flip algorithm. Did you notice gil's flipped_left_right_view?
Yep, in fact it would be 'flipped_up_down_view' - but this algorithm allows me to suit one of my 'personnal' needs to vertically flip the image memory representation inplace. Using 'flipped_up_down_view' would make do an image copy, and hence use twice as much memory.
vertical_flip is up_side_down? Mhmm, is it just me or is this counterintuitive?
As, I said, I like your contribution. What do you think of adding it
to my gil contribution subversion? This is place where people, including me, keep their submissions. I would add you as a member though you have the access permissions. The URL is http://code.google.com/p/gil-contributions/ .
It would be a good idea, I need first to fix the few standing issues discussed before.
Let me know how it goes.
Another idea is to write a freeimage image reader and writer and add
it to my gil::io_new project. What do you think of that?
It could be possible, but, IMHO, I'm not sure that it would fit in your io_new extension. My understanding is that your project aims to provide a 'standalone' image input/output library, and tying it to FreeImage may not be a good idea for a whole set of users. Maybe it would be better as a 'code snippet' that could used and modified by the people needing boost::gil and FreeImage. As I lack time, I'll be more willing to concentrate my work on resampling, that would be a nice extension to GIL, that on this FreeImage binding code. But feel free to precise your thoughts, I may be able to give you a hand on this.
The io_new extension depends already on libjpeg, libpng, and libtiff. FWIW, a potential freeimage extension should have the same interface as the current io_new interface. That's why I thought of adding it to io_new. On the contrary, image magick might be even better since has many more formats. Just to get the gil::io stuff over and down with. I mean boost would have all the necessary formats available. Regards, Christian

vertical_flip is up_side_down? Mhmm, is it just me or is this counterintuitive?
hehe, various people, various conventions - it looks like FreeImage (once more) has a similar notion than mine - it looks like this function is a good candidate to be renamed to 'flip_upside_down' then !
Let me know how it goes.
Sure, I got to find some spare time to integrate the changes.
The io_new extension depends already on libjpeg, libpng, and libtiff.
OK, I didn't get that there were external dependencies.
FWIW, a potential freeimage extension should have the same interface as the current io_new interface.
Fair enough, could you point me to some documentation that describes the public interface of io_new library ? I'll see if I can conform to it.
That's why I thought of adding it to io_new. On the contrary, image magick might be even better since has many more formats. Just to get the gil::io stuff over and down with. I mean boost would have all the necessary formats available.
At the expense of additional external dependencies, yes. ImageMagick could be another candidate, or XnView API, or DevIL, or OpenImageIO - there are many flavours out there, depending on features required by people - it would be hard to match everyone needs. I'm pretty glad with FreeImage right now for my needs, so I'm not ready to invest time elsewhere. Cheers, Nicolas.
participants (2)
-
Christian Henning
-
Nicolas Lelong