GIL Review: GIL extensibility example: packed pixel

A few reviewers have remarked on whether GIL can handle more complex formats, such as packed RGB565 format, (i.e. 5 bits red, 6 bits green, 5 bits blue). Since we can handle even images representing syntethic functions, we can certainly handle packed pixels. We took a stab at providing a model for packed pixel formats and posted it here: http://opensource.adobe.com/gil/packed_pixel.hpp This just serves as an example. The code could be improved and made more generic. Here is how you can define a packed pixel of three channels: typedef packed3_pixel<rgb_t,boost::uint16_t,boost::uint8_t,5,11> rgb565_pixel_t; This defines an RGB pixel over 16-bit data. The first channel always starts at bit 0. The second channel starts at bit 5, and the third at bit 11. Of course, you can define a whole range of packed pixels. Here is an LAB pixel that fits in a byte: typedef packed3_pixel<lab_t,boost::uint8_t,boost::uint8_t,2,2> lab223_pixel_t; Here is example code of using packed pixels: boost::function_requires<HeterogeneousPixelValueConcept<rgb565_pixel_t>
(); boost::function_requires<ChannelConcept<rgb565_pixel_t::kth_channel_t<0> ::reference> >();
typedef type_from_x_iterator<rgb565_pixel_t*>::view_t rgb565_view_t; typedef image<rgb565_view_t> rgb565_image_t; // Read a test image rgb8_image_t unpacked_image; jpeg_read_image("test.jpg",unpacked_image); // copy it into packed 565 form rgb565_image_t packed565_image(get_dimensions(unpacked_image)); copy_pixels(color_converted_view<rgb565_pixel_t>(view(unpacked_image),pa cked3_color_converter()),view(packed565_image)); // save it back unpacked. You will see dithering artifacts, especially for channels of low bit depth jpeg_write_view("test2.jpg",color_converted_view<rgb8_pixel_t>(view(pack ed565_image),packed3_color_converter())); // Invoke gradient on the packed data directly. Note: You need the most // generic version of x_gradient that supports heterogeneous pixels rgb8_image_t gradient(get_dimensions(unpacked_image)); x_gradient(view(packed565_image), view(gradient)); Note that everything you can do with GIL already automatically extends to packed pixels. You can run GIL heterogeneous algorithms on them. You can color convert them. You can include them in runtime types... Most importantly, GIL core does not need to change. Lubomir

Hi, On Fri, Oct 13, 2006 at 10:13:08AM -0700, Lubomir Bourdev <lbourdev@adobe.com> wrote:
A few reviewers have remarked on whether GIL can handle more complex formats, such as packed RGB565 format, (i.e. 5 bits red, 6 bits green, 5 bits blue). Since we can handle even images representing syntethic functions, we can certainly handle packed pixels.
I just started using GIL, and I think I will need a mixture of packed thus interleaved pixels and a planar form: RGB565A8 The alpha channel is stored in a separate buffer. How can I discribe this pixel layout? Regards Andreas Pokorny

Andreas Pokorny wrote:
I just started using GIL, and I think I will need a mixture of packed thus interleaved pixels and a planar form: RGB565A8 The alpha channel is stored in a separate buffer. How can I discribe this pixel layout?
Here is a general strategy that will work with any type of format. If you look at the Mandelbrot function example, it takes a point defining the coordinates of the pixel within the image and returns a reference to the pixel. (The Mandelbrot view is immutable, so it returns the value of the pixel, but one can return a reference (proxy) for mutable views) You can use the Mandelbrot example as a starting point. In your function object you can keep a pointer to the source image (in your case, the two images, packed RGB and alpha) and replace the body of operator() to return the correct RGB565A8 reference. The GIL virtual view support takes care of everything you need to create an image view, and associated locators, x/y iterators, etc. The only thing you need to provide is the mapping from coordiantes to pixel reference. The disadvantage is that this could be suboptimal. It is often faster to compute the reference given a pointer to the pixel instead of given its coordinates. ________________ What I would do in your case is start from the interleaved_ptr example. This is an example of how to write pixel pointers and references. It creates the simplest possible models - that of an interleaved pixel pointer and reference. interleaved_ptr contains a pointer to the first channel of the current pixel and advances it accordingly. Upon dereferencing it returns an interlaved_ref - a model of a pixel reference, which also contains inside a pointer to the first channel of the current pixel. Its channel(), semantic_channel() and operator[] return references to the corresponding channels STEP 1: Create a model of a RGB565A8 pixel reference Start from interleaved_ref and extend it with a second pointer to the current alpha channel in the second image. But one complication in your case is that your pixel type is heterogeneous (meaning that not all of your channels have the same type). So you want to implement channel<0>() ... channel<3>() similar to the way they are implemented in packed3_pixel (which is an example of a model of a packed pixel reference). Your channel<4>() will simply dereference the alpha pointer. STEP 2: Create a model of a RGB565A8 pixel value You can use rgba8_pixel_t for the value type. Any class that is large enough to store the values of the channels will do. STEP 3: Create a model of a RGB565A8 pixel iterator Start from interleaved_ptr and extend it with a second pointer to the current alpha channel in the second image. Upon dereference it should construct your model of a pixel reference giving it the two pointers. You can now construct related types, such as a locator and a view, from your pixel iterator (see interleaved_ptr.cpp): typedef type_from_x_iterator<rgb565a8_ptr_t>::view_t rgb565a8_view_t; Lubomir
participants (2)
-
Andreas Pokorny
-
Lubomir Bourdev