diff --git a/doc/design_guide.rst b/doc/design_guide.rst index b3dcf8287..6896df64a 100644 --- a/doc/design_guide.rst +++ b/doc/design_guide.rst @@ -156,7 +156,7 @@ GIL uses a two-dimensional point, which is a refinement of Models ~~~~~~ -GIL provides a model of ``Point2DConcept``, ``point2`` where +GIL provides a model of ``Point2DConcept``, ``point`` where ``T`` is the coordinate type. Channel @@ -1014,7 +1014,7 @@ to another base iterator:: concept MutableIteratorAdaptorConcept : IteratorAdaptorConcept {}; .. seealso:: - + - `IteratorAdaptorConcept `_ - `MutableIteratorAdaptorConcept `_ @@ -1396,7 +1396,7 @@ Here is some sample code using locators:: below=loc.cache_location(0, 1); ++loc.x(); // move to (11,10) loc.y()+=15; // move to (11,25) - loc-=point2(1,1);// move to (10,24) + loc-=point(1,1);// move to (10,24) *loc=(loc(0,-1)+loc(0,1))/2; // set pixel (10,24) to the average of (10,23) and (10,25) (grayscale pixels only) *loc=(loc[above]+loc[below])/2; // the same, but faster using cached relative neighbor locations @@ -2064,7 +2064,7 @@ GIL's ``any_image_view`` and ``any_image`` are subclasses of ``variant``:: typedef ... const_t; // immutable equivalent of this typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image_view(); template explicit any_image_view(const T& obj); @@ -2089,7 +2089,7 @@ GIL's ``any_image_view`` and ``any_image`` are subclasses of ``variant``:: typedef ... view_t; typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image(); template explicit any_image(const T& obj); @@ -2442,7 +2442,7 @@ or "png" for the APIs of the other libraries):: // Returns the width and height of the JPEG file at the specified location. // Throws std::ios_base::failure if the location does not correspond to a valid JPEG file - point2 jpeg_read_dimensions(const char*); + point jpeg_read_dimensions(const char*); // Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it. // Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension. diff --git a/doc/doxygen/design_guide.dox b/doc/doxygen/design_guide.dox index 4c5006601..fce4ecb47 100644 --- a/doc/doxygen/design_guide.dox +++ b/doc/doxygen/design_guide.dox @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////////////// -/// \file +/// \file /// \brief Doxygen documentation /// \author Lubomir Bourdev and Hailin Jin \n /// Adobe Systems Incorporated @@ -16,7 +16,7 @@ \date September 15, 2007 -

This document describes the design of the Generic Image Library, a C++ image-processing library that abstracts image representation from algorithms on images. +

This document describes the design of the Generic Image Library, a C++ image-processing library that abstracts image representation from algorithms on images. It covers more than you need to know for a causal use of GIL. You can find a quick, jump-start GIL tutorial on the main GIL page at http://stlab.adobe.com/gil - \ref OverviewSectionDG @@ -25,7 +25,7 @@ It covers more than you need to know for a causal use of GIL. You can find a qui - \ref ChannelSectionDG - \ref ColorSpaceSectionDG - \ref ColorBaseSectionDG -- \ref PixelSectionDG +- \ref PixelSectionDG - \ref PixelIteratorSectionDG - \ref FundamentalIteratorDG - \ref IteratorAdaptorDG @@ -57,13 +57,13 @@ It covers more than you need to know for a causal use of GIL. You can find a qui


\section OverviewSectionDG 1. Overview -Images are essential in any image processing, vision and video project, and yet the variability in image representations makes it difficult +Images are essential in any image processing, vision and video project, and yet the variability in image representations makes it difficult to write imaging algorithms that are both generic and efficient. In this section we will describe some of the challenges that we would like to address. In the following discussion an image is a 2D array of pixels. A pixel is a set of color channels that represents the color at a given point in an image. Each channel represents the value of a color component. -There are two common memory structures for an image. Interleaved images are represented by grouping the pixels together in memory and -interleaving all channels together, whereas planar images keep the channels in separate color planes. Here is a 4x3 RGB image in +There are two common memory structures for an image. Interleaved images are represented by grouping the pixels together in memory and +interleaving all channels together, whereas planar images keep the channels in separate color planes. Here is a 4x3 RGB image in which the second pixel of the first row is marked in red, in interleaved form: \image html interleaved.jpg @@ -84,7 +84,7 @@ It also supports user-defined models of images, and images whose parameters are GIL abstracts image representation from algorithms applied on images and allows us to write the algorithm once and have it work on any of the above image variations while generating code that is comparable in speed to that of hand-writing the algorithm for a specific image type. -This document follows bottom-up design. Each section defines concepts that build on top of concepts defined in previous sections. +This document follows bottom-up design. Each section defines concepts that build on top of concepts defined in previous sections. It is recommended to read the sections in order.
@@ -93,10 +93,10 @@ It is recommended to read the sections in order. All constructs in GIL are models of GIL concepts. A \em concept is a set of requirements that a type (or a set of related types) must fulfill to be used correctly in generic algorithms. The requirements include syntactic and algorithming guarantees. For example, GIL's class \p pixel is a model of GIL's \p PixelConcept. The user may substitute the pixel class with one of their own, and, as long as -it satisfies the requirements of \p PixelConcept, all other GIL classes and algorithms can be used with it. See more about concepts here: +it satisfies the requirements of \p PixelConcept, all other GIL classes and algorithms can be used with it. See more about concepts here: http://www.generic-programming.org/languages/conceptcpp/ -In this document we will use a syntax for defining concepts that is described in a proposal for a Concepts extension to C++0x specified here: +In this document we will use a syntax for defining concepts that is described in a proposal for a Concepts extension to C++0x specified here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf Here are some common concepts that will be used in GIL. Most of them are defined here: @@ -104,7 +104,7 @@ http://www.generic-programming.org/languages/conceptcpp/concept_web.php \code auto concept DefaultConstructible { - T::T(); + T::T(); }; auto concept CopyConstructible { @@ -114,11 +114,11 @@ auto concept CopyConstructible { auto concept Assignable { typename result_type; - result_type operator=(T&, U); + result_type operator=(T&, U); }; auto concept EqualityComparable { - bool operator==(T x, T y); + bool operator==(T x, T y); bool operator!=(T x, T y) { return !(x==y); } }; @@ -132,7 +132,7 @@ auto concept Swappable { Here are some additional basic concepts that GIL needs: -\code +\code auto concept Regular : DefaultConstructible, CopyConstructible, EqualityComparable, Assignable, Swappable {}; @@ -164,12 +164,12 @@ A point defines the location of a pixel inside an image. It can also be used to In most general terms, points are N-dimensional and model the following concept: \code -concept PointNDConcept : Regular { +concept PointNDConcept : Regular { // the type of a coordinate along each axis template struct axis; where Metafunction; - + const size_t num_dimensions; - + // accessor/modifier of the value of each axis. template const typename axis::type& T::axis_value() const; template typename axis::type& T::axis_value(); @@ -179,7 +179,7 @@ concept PointNDConcept : Regular { GIL uses a two-dimensional point, which is a refinement of \p PointNDConcept in which both dimensions are of the same type: \code -concept Point2DConcept : PointNDConcept { +concept Point2DConcept : PointNDConcept { where num_dimensions == 2; where SameType::type, axis<1>::type>; @@ -199,7 +199,7 @@ concept Point2DConcept : PointNDConcept { Models: -GIL provides a model of \p Point2DConcept, \p point2 where \p T is the coordinate type. +GIL provides a model of \p Point2DConcept, \p point where \p T is the coordinate type. @@ -223,7 +223,7 @@ GIL provides a model of \p Point2DConcept, \p point2 where \p T is the coordi
\section ChannelSectionDG 4. Channel -A channel indicates the intensity of a color component (for example, the red channel in an RGB pixel). +A channel indicates the intensity of a color component (for example, the red channel in an RGB pixel). Typical channel operations are getting, comparing and setting the channel values. Channels have associated minimum and maximum value. GIL channels model the following concept: @@ -244,13 +244,13 @@ concept ChannelConcept : EqualityComparable { concept MutableChannelConcept : Swappable, Assignable {}; -concept ChannelValueConcept : Regular {}; +concept ChannelValueConcept : Regular {}; \endcode GIL allows built-in integral and floating point types to be channels. Therefore the associated types and range information are defined in \p channel_traits with the following default implementation: -\code +\code template struct channel_traits { typedef T value_type; @@ -258,13 +258,13 @@ struct channel_traits { typedef T* pointer; typedef T& const const_reference; typedef T* const const_pointer; - + static value_type min_value() { return std::numeric_limits::min(); } static value_type max_value() { return std::numeric_limits::max(); } }; \endcode -Two channel types are compatible if they have the same value type: +Two channel types are compatible if they have the same value type: \code concept ChannelsCompatibleConcept { @@ -285,7 +285,7 @@ Note that \p ChannelConcept and \p MutableChannelConcept do not require a defaul support default construction (and thus are regular types) model \p ChannelValueConcept. To understand the motivation for this distinction, consider a 16-bit RGB pixel in a "565" bit pattern. Its channels correspond to bit ranges. To support such channels, we need to create a custom proxy class corresponding to a reference to a subbyte channel. -Such a proxy reference class models only \p ChannelConcept, because, similar to native C++ references, it +Such a proxy reference class models only \p ChannelConcept, because, similar to native C++ references, it may not have a default constructor. Note also that algorithms may impose additional requirements on channels, such as support for arithmentic operations. @@ -311,8 +311,8 @@ typedef boost::int16_t bits16s; typedef boost::int32_t bits32s; \endcode -The minimum and maximum values of a channel modeled by a built-in type correspond to the minimum and maximum physical range of the built-in type, -as specified by its \p std::numeric_limits. Sometimes the physical range is not appropriate. GIL provides \p scoped_channel_value, a model for a +The minimum and maximum values of a channel modeled by a built-in type correspond to the minimum and maximum physical range of the built-in type, +as specified by its \p std::numeric_limits. Sometimes the physical range is not appropriate. GIL provides \p scoped_channel_value, a model for a channel adapter that allows for specifying a custom range. We use it to define a [0..1] floating point channel type as follows: \code @@ -328,14 +328,14 @@ GIL also provides models for channels corresponding to ranges of bits: template class packed_channel_value; // Reference to a channel defined over NumBits bits. Models ChannelConcept -template // true if the reference is mutable +template // true if the reference is mutable class packed_channel_reference; // Reference to a channel defined over NumBits bits. Its FirstBit is a run-time parameter. Models ChannelConcept -template // true if the reference is mutable +template // true if the reference is mutable class packed_dynamic_channel_reference; \endcode @@ -422,7 +422,7 @@ typename channel_traits::value_type channel_multiply(Channel a, Channel
\section ColorSpaceSectionDG 5. Color Space and Layout -A color space captures the set and interpretation of channels comprising a pixel. It is an MPL random access sequence containing the types +A color space captures the set and interpretation of channels comprising a pixel. It is an MPL random access sequence containing the types of all elements in the color space. Two color spaces are considered compatible if they are equal (i.e. have the same set of colors in the same order). Related Concepts: @@ -433,9 +433,9 @@ of all elements in the color space. Two color spaces are considered compatibl Models: -GIL currently provides the following color spaces: \p gray_t, \p rgb_t, \p rgba_t, and \p cmyk_t. It also provides unnamed -N-channel color spaces of two to five channels, \p devicen_t<2>, -\p devicen_t<3>, \p devicen_t<4>, \p devicen_t<5>. Besides the standard layouts, it provides \p bgr_layout_t, \p bgra_layout_t, \p abgr_layout_t +GIL currently provides the following color spaces: \p gray_t, \p rgb_t, \p rgba_t, and \p cmyk_t. It also provides unnamed +N-channel color spaces of two to five channels, \p devicen_t<2>, +\p devicen_t<3>, \p devicen_t<4>, \p devicen_t<5>. Besides the standard layouts, it provides \p bgr_layout_t, \p bgra_layout_t, \p abgr_layout_t and \p argb_layout_t. As an example, here is how GIL defines the RGBA color space: @@ -454,7 +454,7 @@ specified by \p ChannelMappingConcept, which is an MPL random access sequence of Thus they are grouped in GIL's layout: \code -template ::value> > struct layout { typedef ColorSpace color_space_t; @@ -511,22 +511,22 @@ Color base models must satisfy the following concepts: concept ColorBaseConcept : CopyConstructible, EqualityComparable { // a GIL layout (the color space and element permutation) typename layout_t; - + // The type of K-th element template struct kth_element_type; where Metafunction; - + // The result of at_c template struct kth_element_const_reference_type; - where Metafunction; - + where Metafunction; + template kth_element_const_reference_type::type at_c(T); - - template where { ColorBasesCompatibleConcept } + + template where { ColorBasesCompatibleConcept } T::T(T2); - template where { ColorBasesCompatibleConcept } + template where { ColorBasesCompatibleConcept } bool operator==(const T&, const T2&); - template where { ColorBasesCompatibleConcept } + template where { ColorBasesCompatibleConcept } bool operator!=(const T&, const T2&); }; @@ -536,8 +536,8 @@ concept MutableColorBaseConcept : Assignable, Swappable; template kth_element_reference_type::type at_c(T); - - template where { ColorBasesCompatibleConcept } + + template where { ColorBasesCompatibleConcept } T& operator=(T&, const T2&); }; @@ -546,7 +546,7 @@ concept ColorBaseValueConcept : MutableColorBaseConcept, Regular< concept HomogeneousColorBaseConcept { // For all K in [0 ... size::value-1): - // where SameType::type, kth_element_type::type>; + // where SameType::type, kth_element_type::type>; kth_element_const_reference_type<0>::type dynamic_at_c(const CB&, std::size_t n) const; }; @@ -604,19 +604,19 @@ template struct kth_semantic_element_reference_type; template struct kth_semantic_element_const_reference_type; // Returns a reference to the element with K-th semantic index. -template -typename kth_semantic_element_reference_type::type semantic_at_c(ColorBase& p) -template -typename kth_semantic_element_const_reference_type::type semantic_at_c(const ColorBase& p) +template +typename kth_semantic_element_reference_type::type semantic_at_c(ColorBase& p) +template +typename kth_semantic_element_const_reference_type::type semantic_at_c(const ColorBase& p) // Returns the type of the return value of get_color(color_base) template struct color_reference_t; template struct color_const_reference_t; // Returns a reference to the element corresponding to the given color -template +template typename color_reference_t::type get_color(ColorBase& cb, Color=Color()); -template +template typename color_const_reference_t::type get_color(const ColorBase& cb, Color=Color()); // Returns the element type of the color base. Defined for homogeneous color bases only @@ -634,28 +634,28 @@ template void static_copy(const Src& src, Dst& dst template void static_generate(CB& dst,Op op); // Equivalents to std::transform -template Op static_transform( CB&,Dst&,Op); -template Op static_transform(const CB&,Dst&,Op); -template Op static_transform( CB1&, CB2&,Dst&,Op); -template Op static_transform(const CB1&, CB2&,Dst&,Op); -template Op static_transform( CB1&,const CB2&,Dst&,Op); -template Op static_transform(const CB1&,const CB2&,Dst&,Op); +template Op static_transform( CB&,Dst&,Op); +template Op static_transform(const CB&,Dst&,Op); +template Op static_transform( CB1&, CB2&,Dst&,Op); +template Op static_transform(const CB1&, CB2&,Dst&,Op); +template Op static_transform( CB1&,const CB2&,Dst&,Op); +template Op static_transform(const CB1&,const CB2&,Dst&,Op); // Equivalents to std::for_each -template Op static_for_each( CB1&,Op); -template Op static_for_each(const CB1&,Op); -template Op static_for_each( CB1&, CB2&,Op); -template Op static_for_each( CB1&,const CB2&,Op); -template Op static_for_each(const CB1&, CB2&,Op); -template Op static_for_each(const CB1&,const CB2&,Op); -template Op static_for_each( CB1&, CB2&, CB3&,Op); -template Op static_for_each( CB1&, CB2&,const CB3&,Op); -template Op static_for_each( CB1&,const CB2&, CB3&,Op); -template Op static_for_each( CB1&,const CB2&,const CB3&,Op); -template Op static_for_each(const CB1&, CB2&, CB3&,Op); -template Op static_for_each(const CB1&, CB2&,const CB3&,Op); -template Op static_for_each(const CB1&,const CB2&, CB3&,Op); -template Op static_for_each(const CB1&,const CB2&,const CB3&,Op); +template Op static_for_each( CB1&,Op); +template Op static_for_each(const CB1&,Op); +template Op static_for_each( CB1&, CB2&,Op); +template Op static_for_each( CB1&,const CB2&,Op); +template Op static_for_each(const CB1&, CB2&,Op); +template Op static_for_each(const CB1&,const CB2&,Op); +template Op static_for_each( CB1&, CB2&, CB3&,Op); +template Op static_for_each( CB1&, CB2&,const CB3&,Op); +template Op static_for_each( CB1&,const CB2&, CB3&,Op); +template Op static_for_each( CB1&,const CB2&,const CB3&,Op); +template Op static_for_each(const CB1&, CB2&, CB3&,Op); +template Op static_for_each(const CB1&, CB2&,const CB3&,Op); +template Op static_for_each(const CB1&,const CB2&, CB3&,Op); +template Op static_for_each(const CB1&,const CB2&,const CB3&,Op); // The following algorithms are only defined for homogeneous color bases: // Equivalent to std::fill @@ -669,16 +669,16 @@ template typename element_reference_type::type static_ \endcode These algorithms are designed after the corresponding STL algorithms, except that instead of ranges they take color bases and operate on their elements. -In addition, they are implemented with a compile-time recursion (thus the prefix "static_"). Finally, they pair the elements semantically instead of based +In addition, they are implemented with a compile-time recursion (thus the prefix "static_"). Finally, they pair the elements semantically instead of based on their physical order in memory. For example, here is the implementation of \p static_equal: \code namespace detail { template struct element_recursion { template - static bool static_equal(const P1& p1, const P2& p2) { + static bool static_equal(const P1& p1, const P2& p2) { return element_recursion::static_equal(p1,p2) && - semantic_at_c(p1)==semantic_at_c(p2); + semantic_at_c(p1)==semantic_at_c(p2); } }; template <> struct element_recursion<0> { @@ -689,12 +689,12 @@ template <> struct element_recursion<0> { template bool static_equal(const P1& p1, const P2& p2) { - gil_function_requires >(); - return detail::element_recursion::value>::static_equal(p1,p2); -} + gil_function_requires >(); + return detail::element_recursion::value>::static_equal(p1,p2); +} \endcode -This algorithm is used when invoking \p operator== on two pixels, for example. By using semantic accessors we are properly comparing an RGB pixel +This algorithm is used when invoking \p operator== on two pixels, for example. By using semantic accessors we are properly comparing an RGB pixel to a BGR pixel. Notice also that all of the above algorithms taking more than one color base require that they all have the same color space. @@ -739,12 +739,12 @@ to a BGR pixel. Notice also that all of the above algorithms taking more than on
\section PixelSectionDG 7. Pixel -A pixel is a set of channels defining the color at a given point in an image. Conceptually, a pixel is little more than a color base whose elements +A pixel is a set of channels defining the color at a given point in an image. Conceptually, a pixel is little more than a color base whose elements model \p ChannelConcept. -All properties of pixels inherit from color bases: pixels may be homogeneous if all of their channels have the same type; otherwise they are -called heterogeneous. The channels of a pixel may be addressed using semantic or physical indexing, or by color; all color-base algorithms -work on pixels as well. Two pixels are compatible if their color spaces are the same and their channels, paired semantically, are compatible. -Note that constness, memory organization and reference/value are ignored. For example, an 8-bit RGB planar reference is compatible to a constant 8-bit +All properties of pixels inherit from color bases: pixels may be homogeneous if all of their channels have the same type; otherwise they are +called heterogeneous. The channels of a pixel may be addressed using semantic or physical indexing, or by color; all color-base algorithms +work on pixels as well. Two pixels are compatible if their color spaces are the same and their channels, paired semantically, are compatible. +Note that constness, memory organization and reference/value are ignored. For example, an 8-bit RGB planar reference is compatible to a constant 8-bit BGR interleaved pixel value. Most pairwise pixel operations (copy construction, assignment, equality, etc.) are only defined for compatible pixels. Pixels (as well as other GIL constructs built on pixels, such as iterators, locators, views and images) must provide metafunctions to access @@ -752,11 +752,11 @@ their color space, channel mapping, number of channels, and (for homogeneous pix \code concept PixelBasedConcept { - typename color_space_type; + typename color_space_type; where Metafunction >; where ColorSpaceConcept::type>; - typename channel_mapping_type; - where Metafunction >; + typename channel_mapping_type; + where Metafunction >; where ChannelMappingConcept::type>; typename is_planar; where Metafunction >; @@ -764,7 +764,7 @@ concept PixelBasedConcept { }; concept HomogeneousPixelBasedConcept { - typename channel_type; + typename channel_type; where Metafunction >; where ChannelConcept::type>; }; @@ -773,39 +773,39 @@ concept HomogeneousPixelBasedConcept { Pixels model the following concepts: \code -concept PixelConcept : ColorBaseConcept

, PixelBasedConcept

{ +concept PixelConcept : ColorBaseConcept

, PixelBasedConcept

{ where is_pixel

::type::value==true; // where for each K [0..size

::value-1]: // ChannelConcept >; - + typename value_type; where PixelValueConcept; typename reference; where PixelConcept; typename const_reference; where PixelConcept; static const bool P::is_mutable; - template where { PixelConcept } + template where { PixelConcept } P::P(P2); - template where { PixelConcept } + template where { PixelConcept } bool operator==(const P&, const P2&); - template where { PixelConcept } + template where { PixelConcept } bool operator!=(const P&, const P2&); -}; +}; concept MutablePixelConcept : PixelConcept

, MutableColorBaseConcept

{ where is_mutable==true; }; -concept HomogeneousPixelConcept : HomogeneousColorBaseConcept

, HomogeneousPixelBasedConcept

{ +concept HomogeneousPixelConcept : HomogeneousColorBaseConcept

, HomogeneousPixelBasedConcept

{ P::template element_const_reference_type

::type operator[](P p, std::size_t i) const { return dynamic_at_c(P,i); } }; -concept MutableHomogeneousPixelConcept : MutableHomogeneousColorBaseConcept

{ +concept MutableHomogeneousPixelConcept : MutableHomogeneousColorBaseConcept

{ P::template element_reference_type

::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); } }; concept PixelValueConcept : PixelConcept

, Regular

{ where SameType; -}; +}; concept PixelsCompatibleConcept : ColorBasesCompatibleConcept { // where for each K [0..size::value): @@ -863,7 +863,7 @@ assert(dynamic_at_c(bgr8,0) != dynamic_at_c(rgb8,0)); assert(rgb8[0] != bgr8[0]); // same as above (but operator[] is defined for pixels only) \endcode -Planar pixels have their channels distributed in memory. While they share the same value type (\p pixel) with interleaved pixels, their +Planar pixels have their channels distributed in memory. While they share the same value type (\p pixel) with interleaved pixels, their reference type is a proxy class containing references to each of the channels. This is implemented with the struct \p planar_pixel_reference: \code @@ -875,7 +875,7 @@ typedef planar_pixel_reference< bits8&,rgb_t> rgb8_planar_ref_t; typedef planar_pixel_reference rgb8c_planar_ref_t; \endcode -Note that, unlike the \p pixel struct, planar pixel references are templated over the color space, not over the pixel layout. They always +Note that, unlike the \p pixel struct, planar pixel references are templated over the color space, not over the pixel layout. They always use a cannonical channel ordering. Ordering of their elements is unnecessary because their elements are references to the channels. Sometimes the channels of a pixel may not be byte-aligned. For example an RGB pixel in '5-5-6' format is a 16-bit pixel whose red, green and blue @@ -911,13 +911,13 @@ typedef const bit_aligned_pixel_reference bgr232_ptr_t; // BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused) -typedef std::iterator_traits::value_type bgr232_pixel_t; +typedef std::iterator_traits::value_type bgr232_pixel_t; BOOST_STATIC_ASSERT((sizeof(bgr232_pixel_t)==1)); bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000 = 0x60 // a buffer of 7 bytes fits exactly 8 BGR232 pixels. -unsigned char pix_buffer[7]; +unsigned char pix_buffer[7]; std::fill(pix_buffer,pix_buffer+7,0); // Fill the 8 pixels with red @@ -965,7 +965,7 @@ rgb8_pixel_t rgb_full(255,255,255); get_color(r565,red_t()) = channel_convert(get_color(rgb_full,red_t())); get_color(r565,green_t()) = channel_convert(get_color(rgb_full,green_t())); get_color(r565,blue_t()) = channel_convert(get_color(rgb_full,blue_t())); -assert(r565 == rgb565_pixel_t((uint16_t)65535)); +assert(r565 == rgb565_pixel_t((uint16_t)65535)); \endcode GIL also provides the \p color_convert algorithm to convert between pixels of different color spaces and channel types: @@ -1025,9 +1025,9 @@ to get the immutable (read-only) type of the iterator, and to determine whether \code concept PixelIteratorConcept : PixelBasedConcept { where PixelValueConcept; - typename const_iterator_type::type; + typename const_iterator_type::type; where PixelIteratorConcept::type>; - static const bool iterator_is_mutable::type::value; + static const bool iterator_is_mutable::type::value; static const bool is_iterator_adaptor::type::value; // is it an iterator adaptor }; @@ -1067,7 +1067,7 @@ struct inc : public std::unary_function { }; template -planar_pixel_iterator& +planar_pixel_iterator& planar_pixel_iterator::operator++() { static_transform(*this,*this,inc()); return *this; @@ -1080,7 +1080,7 @@ the bit offset. \section IteratorAdaptorDG Iterator Adaptor -Iterator adaptor is an iterator that wraps around another iterator. Its \p is_iterator_adaptor metafunction must evaluate to true, and it +Iterator adaptor is an iterator that wraps around another iterator. Its \p is_iterator_adaptor metafunction must evaluate to true, and it needs to provide a member method to return the base iterator, a metafunction to get its type, and a metafunction to rebind to another base iterator: \code @@ -1090,8 +1090,8 @@ concept IteratorAdaptorConcept { typename iterator_adaptor_get_base; where Metafunction >; where boost_concepts::ForwardTraversalConcept::type>; - - typename another_iterator; + + typename another_iterator; typename iterator_adaptor_rebind::type; where boost_concepts::ForwardTraversalConcept; where IteratorAdaptorConcept::type>; @@ -1113,12 +1113,12 @@ concept MutableIteratorAdaptorConcept : IteratorAdaptorConcept {}; GIL provides several models of IteratorAdaptorConcept: - \p memory_based_step_iterator\: An iterator adaptor that changes the fundamental step of the base iterator (see \ref StepIteratorDG) - \p dereference_iterator_adaptor\: An iterator that applies a unary function \p Fn upon dereferencing. It is used, for example, -for on-the-fly color conversion. It can be used to construct a shallow image "view" that pretends to have a different color space or +for on-the-fly color conversion. It can be used to construct a shallow image "view" that pretends to have a different color space or channel depth. See \ref ImageViewFrowImageViewDG for more. The unary function \p Fn must model \p PixelDereferenceAdaptorConcept (see below). \section PixelDereferenceAdaptorAG Pixel Dereference Adaptor -Pixel dereference adaptor is a unary function that can be applied upon dereferencing a pixel iterator. Its argument type could be anything +Pixel dereference adaptor is a unary function that can be applied upon dereferencing a pixel iterator. Its argument type could be anything (usually a \p PixelConcept) and the result type must be convertible to \p PixelConcept \code @@ -1139,17 +1139,17 @@ concept PixelDereferenceAdaptorConcept : DefaultConstructibleConcept, CopyCon GIL provides several models of \p PixelDereferenceAdaptorConcept - \p color_convert_deref_fn: a function object that performs color conversion - \p detail::nth_channel_deref_fn: a function object that returns a grayscale pixel corresponding to the n-th channel of a given pixel - - \p deref_compose: a function object that composes two models of \p PixelDereferenceAdaptorConcept. Similar to \p std::unary_compose, except + - \p deref_compose: a function object that composes two models of \p PixelDereferenceAdaptorConcept. Similar to \p std::unary_compose, except it needs to pull the additional typedefs required by \p PixelDereferenceAdaptorConcept GIL uses pixel dereference adaptors to implement image views that perform color conversion upon dereferencing, or that return the N-th channel of the -underlying pixel. They can be used to model virtual image views that perform an arbitrary function upon dereferencing, for example a view of -the Mandelbrot set. \p dereference_iterator_adaptor is an iterator wrapper over a pixel iterator \p Iterator that invokes the given dereference +underlying pixel. They can be used to model virtual image views that perform an arbitrary function upon dereferencing, for example a view of +the Mandelbrot set. \p dereference_iterator_adaptor is an iterator wrapper over a pixel iterator \p Iterator that invokes the given dereference iterator adaptor \p Fn upon dereferencing. \section StepIteratorDG Step Iterator -Sometimes we want to traverse pixels with a unit step other than the one provided by the fundamental pixel iterators. +Sometimes we want to traverse pixels with a unit step other than the one provided by the fundamental pixel iterators. Examples where this would be useful: - a single-channel view of the red channel of an RGB interleaved image - left-to-right flipped image (step = -fundamental_step) @@ -1167,13 +1167,13 @@ concept StepIteratorConcept { concept MutableStepIteratorConcept : StepIteratorConcept {}; \endcode -GIL currently provides a step iterator whose \p value_type models \p PixelValueConcept. In addition, the step is specified in memory units (which are bytes or bits). +GIL currently provides a step iterator whose \p value_type models \p PixelValueConcept. In addition, the step is specified in memory units (which are bytes or bits). This is necessary, for example, when implementing an iterator navigating along a column of pixels - the size of a row of pixels may sometimes not be divisible by the size of a pixel; for example rows may be word-aligned. To advance in bytes/bits, the base iterator must model MemoryBasedIteratorConcept. A memory-based iterator has an inherent memory unit, which is either a bit or a byte. It must supply functions returning the number of bits per memory unit (1 or 8), the current step in memory units, -the memory-unit distance between two iterators, and a reference a given distance in memunits away. It must also supply a function that advances an iterator +the memory-unit distance between two iterators, and a reference a given distance in memunits away. It must also supply a function that advances an iterator a given distance in memory units. \p memunit_advanced and \p memunit_advanced_ref have a default implementation but some iterators may supply a more efficient version: @@ -1212,7 +1212,7 @@ All models of pixel iterators, locators and image views that GIL provides suppor All standard memory-based iterators GIL currently provides model \p MemoryBasedIteratorConcept. GIL provides the class \p memory_based_step_iterator which models \p PixelIteratorConcept, \p StepIteratorConcept, and \p MemoryBasedIteratorConcept. -It takes the base iterator as a template parameter (which must model \p PixelIteratorConcept and \p MemoryBasedIteratorConcept) +It takes the base iterator as a template parameter (which must model \p PixelIteratorConcept and \p MemoryBasedIteratorConcept) and allows changing the step dynamically. GIL's implementation contains the base iterator and a \p ptrdiff_t denoting the number of memory units (bytes or bits) to skip for a unit step. It may also be used with a negative number. GIL provides a function to create a step iterator from a base iterator and a step: @@ -1221,30 +1221,30 @@ template // Models MemoryBasedIteratorConcept, HasDynamicXStepType typename dynamic_x_step_type::type make_step_iterator(const I& it, std::ptrdiff_t step); \endcode -GIL also provides a model of an iterator over a virtual array of pixels, \p position_iterator. It is a step iterator that keeps track of the pixel position -and invokes a function object to get the value of the pixel upon dereferencing. It models \p PixelIteratorConcept and \p StepIteratorConcept but +GIL also provides a model of an iterator over a virtual array of pixels, \p position_iterator. It is a step iterator that keeps track of the pixel position +and invokes a function object to get the value of the pixel upon dereferencing. It models \p PixelIteratorConcept and \p StepIteratorConcept but not \p MemoryBasedIteratorConcept. \section LocatorDG Pixel Locator A Locator allows for navigation in two or more dimensions. Locators are N-dimensional iterators in spirit, but we use a different -name because they don't satisfy all the requirements of iterators. For example, they don't supply increment and decrement operators because it is unclear +name because they don't satisfy all the requirements of iterators. For example, they don't supply increment and decrement operators because it is unclear which dimension the operators should advance along. N-dimensional locators model the following concept: \code -concept RandomAccessNDLocatorConcept { +concept RandomAccessNDLocatorConcept { typename value_type; // value over which the locator navigates typename reference; // result of dereferencing typename difference_type; where PointNDConcept; // return value of operator-. typename const_t; // same as Loc, but operating over immutable values typename cached_location_t; // type to store relative location (for efficient repeated access) typename point_t = difference_type; - + static const size_t num_dimensions; // dimensionality of the locator where num_dimensions = point_t::num_dimensions; - - // The difference_type and iterator type along each dimension. The iterators may only differ in + + // The difference_type and iterator type along each dimension. The iterators may only differ in // difference_type. Their value_type must be the same as Loc::value_type template struct axis { typename coord_t = point_t::axis::coord_t; @@ -1257,19 +1257,19 @@ concept RandomAccessNDLocatorConcept { typename type; where RandomAccessNDLocatorConcept; static type make(const Loc& loc, const Deref& deref); }; - + Loc& operator+=(Loc&, const difference_type&); Loc& operator-=(Loc&, const difference_type&); Loc operator+(const Loc&, const difference_type&); Loc operator-(const Loc&, const difference_type&); - + reference operator*(const Loc&); reference operator[](const Loc&, const difference_type&); - - // Storing relative location for faster repeated access and accessing it + + // Storing relative location for faster repeated access and accessing it cached_location_t Loc::cache_location(const difference_type&) const; reference operator[](const Loc&,const cached_location_t&); - + // Accessing iterators along a given dimension at the current location or at a given offset template axis::iterator& Loc::axis_iterator(); template axis::iterator const& Loc::axis_iterator() const; @@ -1277,7 +1277,7 @@ concept RandomAccessNDLocatorConcept { }; template -concept MutableRandomAccessNDLocatorConcept : RandomAccessNDLocatorConcept { +concept MutableRandomAccessNDLocatorConcept : RandomAccessNDLocatorConcept { where Mutable; }; \endcode @@ -1288,12 +1288,12 @@ Two-dimensional locators have additional requirements: concept RandomAccess2DLocatorConcept { where num_dimensions==2; where Point2DConcept; - + typename x_iterator = axis<0>::iterator; typename y_iterator = axis<1>::iterator; typename x_coord_t = axis<0>::coord_t; typename y_coord_t = axis<1>::coord_t; - + // Only available to locators that have dynamic step in Y //Loc::Loc(const Loc& loc, y_coord_t); @@ -1301,14 +1301,14 @@ concept RandomAccess2DLocatorConcept { //Loc::Loc(const Loc& loc, x_coord_t, y_coord_t, bool transposed=false); x_iterator& Loc::x(); - x_iterator const& Loc::x() const; + x_iterator const& Loc::x() const; y_iterator& Loc::y(); - y_iterator const& Loc::y() const; - + y_iterator const& Loc::y() const; + x_iterator Loc::x_at(const difference_type&) const; y_iterator Loc::y_at(const difference_type&) const; Loc Loc::xy_at(const difference_type&) const; - + // x/y versions of all methods that can take difference type x_iterator Loc::x_at(x_coord_t, y_coord_t) const; y_iterator Loc::y_at(x_coord_t, y_coord_t) const; @@ -1377,7 +1377,7 @@ concept MutablePixelLocatorConcept : MutableRandomAcces GIL provides two models of \p PixelLocatorConcept - a memory-based locator, \p memory_based_2d_locator and a virtual locator \p virtual_2d_locator. \p memory_based_2d_locator is a locator over planar or interleaved images that have their pixels in memory. -It takes a model of \p StepIteratorConcept over pixels as a template parameter. (When instantiated with a model of \p MutableStepIteratorConcept, +It takes a model of \p StepIteratorConcept over pixels as a template parameter. (When instantiated with a model of \p MutableStepIteratorConcept, it models \p MutablePixelLocatorConcept). \code @@ -1385,11 +1385,11 @@ template // Models StepIteratorConcept, MemoryBasedIter class memory_based_2d_locator; \endcode -The step of \p StepIterator must be the number of memory units (bytes or bits) per row (thus it must be memunit advanceable). The class \p memory_based_2d_locator is a -wrapper around \p StepIterator and uses it to navigate vertically, while its base iterator is used to navigate horizontally. +The step of \p StepIterator must be the number of memory units (bytes or bits) per row (thus it must be memunit advanceable). The class \p memory_based_2d_locator is a +wrapper around \p StepIterator and uses it to navigate vertically, while its base iterator is used to navigate horizontally. Combining fundamental and step iterators allows us to create locators that describe complex -pixel memory organizations. First, we have a choice of iterator to use for horizontal direction, i.e. for iterating over the pixels on the same row. +pixel memory organizations. First, we have a choice of iterator to use for horizontal direction, i.e. for iterating over the pixels on the same row. Using the fundamental and step iterators gives us four choices: - \p pixel* (for interleaved images) - \p planar_pixel_iterator (for planar images) @@ -1405,11 +1405,11 @@ Given a horizontal iterator \p XIterator, we could choose the \e y-iterator, the Then we can instantiate \p memory_based_2d_locator > to obtain a 2D pixel locator, as the diagram indicates: \image html step_iterator.gif -\p virtual_2d_locator is a locator that is instantiated with a function object invoked upon dereferencing a pixel. It returns the value of a pixel -given its X,Y coordiantes. Virtual locators can be used to implement virtual image views that can model any user-defined function. See the GIL +\p virtual_2d_locator is a locator that is instantiated with a function object invoked upon dereferencing a pixel. It returns the value of a pixel +given its X,Y coordiantes. Virtual locators can be used to implement virtual image views that can model any user-defined function. See the GIL tutorial for an example of using virtual locators to create a view of the Mandelbrot set. -Both the virtual and the memory-based locators subclass from \p pixel_2d_locator_base, a base class that provides most of the interface required +Both the virtual and the memory-based locators subclass from \p pixel_2d_locator_base, a base class that provides most of the interface required by \p PixelLocatorConcept. Users may find this base class useful if they need to provide other models of \p PixelLocatorConcept. Here is some sample code using locators: @@ -1420,22 +1420,22 @@ above=loc.cache_location(0,-1); // remember relative locations of neighbors abo below=loc.cache_location(0, 1); ++loc.x(); // move to (11,10) loc.y()+=15; // move to (11,25) -loc-=point2(1,1);// move to (10,24) +loc-=point(1,1);// move to (10,24) *loc=(loc(0,-1)+loc(0,1))/2; // set pixel (10,24) to the average of (10,23) and (10,25) (grayscale pixels only) *loc=(loc[above]+loc[below])/2; // the same, but faster using cached relative neighbor locations \endcode The standard GIL locators are fast and lightweight objects. For example, the locator for a simple interleaved image consists of one raw pointer to the pixel location plus one integer for the row size in bytes, for a total of 8 bytes. ++loc.x() amounts to -incrementing a raw pointer (or N pointers for planar images). Computing 2D offsets is slower as it requires multiplication and addition. -Filters, for example, need to access the same neighbors for every pixel in the image, in which case the relative positions can be cached -into a raw byte difference using \p cache_location. In the above example loc[above] for simple interleaved images amounts to a raw array +incrementing a raw pointer (or N pointers for planar images). Computing 2D offsets is slower as it requires multiplication and addition. +Filters, for example, need to access the same neighbors for every pixel in the image, in which case the relative positions can be cached +into a raw byte difference using \p cache_location. In the above example loc[above] for simple interleaved images amounts to a raw array index operator. \section IteratorFrom2DDG Iterator over 2D image Sometimes we want to perform the same, location-independent operation over all pixels of an image. In such a case it is useful to represent the pixels -as a one-dimensional array. GIL's \p iterator_from_2d is a random access traversal iterator that visits all pixels in an image in the natural +as a one-dimensional array. GIL's \p iterator_from_2d is a random access traversal iterator that visits all pixels in an image in the natural memory-friendly order left-to-right inside top-to-bottom. It takes a locator, the width of the image and the current X position. This is sufficient information for it to determine when to do a "carriage return". Synopsis: @@ -1444,7 +1444,7 @@ template // Models PixelLocatorConcept class iterator_from_2d { public: iterator_from_2d(const Locator& loc, int x, int width); - + iterator_from_2d& operator++(); // if (++_x<_width) ++_p.x(); else _p+=point_t(-_width,1); ... @@ -1488,8 +1488,8 @@ adds about 15% performance delay (measured for interleaved images on Intel platf


\section ImageViewSectionDG 9. Image View -An image view is a generalization of STL's range concept to multiple dimensions. Similar to ranges (and iterators), image views are shallow, don't -own the underlying data and don't propagate their constness over the data. For example, a constant image view cannot be resized, but may allow +An image view is a generalization of STL's range concept to multiple dimensions. Similar to ranges (and iterators), image views are shallow, don't +own the underlying data and don't propagate their constness over the data. For example, a constant image view cannot be resized, but may allow modifying the pixels. For pixel-immutable operations, use constant-value image view (also called non-mutable image view). Most general N-dimensional views satisfy the following concept: @@ -1502,7 +1502,7 @@ concept RandomAccessNDImageViewConcept { typename point_t; where PointNDConcept; // N-dimensional point typename locator; where RandomAccessNDLocatorConcept; // N-dimensional locator. typename iterator; where RandomAccessTraversalConcept; // 1-dimensional iterator over all values - typename reverse_iterator; where RandomAccessTraversalConcept; + typename reverse_iterator; where RandomAccessTraversalConcept; typename size_type; // the return value of size() // Equivalent to RandomAccessNDLocatorConcept::axis @@ -1520,10 +1520,10 @@ concept RandomAccessNDImageViewConcept { }; static const size_t num_dimensions = point_t::num_dimensions; - + // Create from a locator at the top-left corner and dimensions View::View(const locator&, const point_type&); - + size_type View::size() const; // total number of elements reference operator[](View, const difference_type&) const; // 1-dimensional reference iterator View::begin() const; @@ -1556,10 +1556,10 @@ concept RandomAccess2DImageViewConcept { typename x_coord_t = axis<0>::coord_t; typename y_coord_t = axis<1>::coord_t; typename xy_locator = locator; - + x_coord_t View::width() const; y_coord_t View::height() const; - + // X-navigation x_iterator View::x_at(const point_t&) const; x_iterator View::row_begin(y_coord_t) const; @@ -1569,11 +1569,11 @@ concept RandomAccess2DImageViewConcept { y_iterator View::y_at(const point_t&) const; y_iterator View::col_begin(x_coord_t) const; y_iterator View::col_end (x_coord_t) const; - + // navigating in 2D xy_locator View::xy_at(const point_t&) const; - // (x,y) versions of all methods taking point_t + // (x,y) versions of all methods taking point_t View::View(x_coord_t,y_coord_t,const locator&); iterator View::at(x_coord_t,y_coord_t) const; reference operator()(View,x_coord_t,y_coord_t) const; @@ -1591,10 +1591,10 @@ Image views that GIL typically uses operate on value types that model \p PixelVa \code concept ImageViewConcept { where PixelValueConcept; - where PixelIteratorConcept; + where PixelIteratorConcept; where PixelIteratorConcept; where x_coord_t == y_coord_t; - + typename coord_t = x_coord_t; std::size_t View::num_channels() const; @@ -1626,7 +1626,7 @@ Compatible views must also have the same dimensions (i.e. the same width and hei Models: -GIL provides a model for \p ImageViewConcept called \p image_view. It is templated over a model of \p PixelLocatorConcept. +GIL provides a model for \p ImageViewConcept called \p image_view. It is templated over a model of \p PixelLocatorConcept. (If instantiated with a model of \p MutablePixelLocatorConcept, it models \p MutableImageViewConcept). Synopsis: \code @@ -1676,16 +1676,16 @@ derived from the type of the source. GIL uses the following metafunctions to get \code // Some result view types -template +template struct dynamic_xy_step_type : public dynamic_y_step_type::type> {}; -template +template struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type::type> {}; // color and bit depth converted view to match pixel type P template + typename ColorConverter=gil::default_color_converter> struct color_converted_view_type { typedef ... type; // image view adaptor with value type DstP, over SrcView }; @@ -1711,29 +1711,29 @@ template typename dynamic_xy_step_transposed_type::type ro template typename dynamic_xy_step_transposed_type::type rotated90ccw_view(const View& src); // view of an axis-aligned rectangular area within an image -template View subimage_view(const View& src, +template View subimage_view(const View& src, const View::point_t& top_left, const View::point_t& dimensions); // subsampled view (skipping pixels in X and Y) -template typename dynamic_xy_step_type::type subsampled_view(const View& src, +template typename dynamic_xy_step_type::type subsampled_view(const View& src, const View::point_t& step); -template +template color_converted_view_type::type color_converted_view(const View& src); template // with a custom color converter color_converted_view_type::type color_converted_view(const View& src); -template +template nth_channel_view_type::view_t nth_channel_view(const View& view, int n); \endcode -The implementations of most of these view factory methods are straightforward. Here is, for example, how the flip views are implemented. -The flip upside-down view creates a view whose first pixel is the bottom left pixel of the original view and whose y-step is the negated +The implementations of most of these view factory methods are straightforward. Here is, for example, how the flip views are implemented. +The flip upside-down view creates a view whose first pixel is the bottom left pixel of the original view and whose y-step is the negated step of the source. \code template -typename dynamic_y_step_type::type flipped_up_down_view(const View& src) { +typename dynamic_y_step_type::type flipped_up_down_view(const View& src) { gil_function_requires >(); typedef typename dynamic_y_step_type::type RView; return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1)); @@ -1741,7 +1741,7 @@ typename dynamic_y_step_type::type flipped_up_down_view(const View& src) { \endcode The call to \p gil_function_requires ensures (at compile time) that the template parameter is a valid model of \p ImageViewConcept. Using it -generates easier to track compile errors, creates no extra code and has no run-time performance impact. +generates easier to track compile errors, creates no extra code and has no run-time performance impact. We are using the \p boost::concept_check library, but wrapping it in \p gil_function_requires, which performs the check if the \p BOOST_GIL_USE_CONCEPT_CHECK is set. It is unset by default, because there is a significant increase in compile time when using concept checks. We will skip \p gil_function_requires in the code examples in this guide for the sake of succinctness. @@ -1763,7 +1763,7 @@ on the pixel data allocated when \p img was created. \subsection ImageViewAlgorithmsDG STL-Style Algorithms on Image Views -

Image views provide 1D iteration of their pixels via begin() and end() methods, which makes it possible to use STL +

Image views provide 1D iteration of their pixels via begin() and end() methods, which makes it possible to use STL algorithms with them. However, using nested loops over X and Y is in many cases more efficient. The algorithms in this section resemble STL algorithms, but they abstract away the nested loops and take views (as opposed to ranges) as input. @@ -1835,20 +1835,20 @@ Algorithms that take multiple views require that they have the same dimensions. \p for_each_pixel_position and \p transform_pixel_positions pass pixel locators, as opposed to pixel references, to their function objects. This allows for writing algorithms that use pixel neighbors, as the tutorial demonstrates. -Most of these algorithms check whether the image views are 1D-traversable. A 1D-traversable image view has no gaps at the end of the rows. -In other words, if an x_iterator of that view is advanced past the last pixel in a row it will move to the first pixel of the next row. -When image views are 1D-traversable, the algorithms use a single loop and run more efficiently. If one or more of the input views are not +Most of these algorithms check whether the image views are 1D-traversable. A 1D-traversable image view has no gaps at the end of the rows. +In other words, if an x_iterator of that view is advanced past the last pixel in a row it will move to the first pixel of the next row. +When image views are 1D-traversable, the algorithms use a single loop and run more efficiently. If one or more of the input views are not 1D-traversable, the algorithms fall-back to an X-loop nested inside a Y-loop. -The algorithms typically delegate the work to their corresponding STL algorithms. For example, \p copy_pixels calls \p std::copy either for each +The algorithms typically delegate the work to their corresponding STL algorithms. For example, \p copy_pixels calls \p std::copy either for each row, or, when the images are 1D-traversable, once for all pixels. -In addition, overloads are sometimes provided for the STL algorithms. For example, \p std::copy for planar iterators is overloaded to perform -\p std::copy for each of the planes. \p std::copy over bitwise-copiable pixels results in \p std::copy over unsigned char, which STL typically +In addition, overloads are sometimes provided for the STL algorithms. For example, \p std::copy for planar iterators is overloaded to perform +\p std::copy for each of the planes. \p std::copy over bitwise-copiable pixels results in \p std::copy over unsigned char, which STL typically implements via \p memmove. -As a result \p copy_pixels may result in a single call to \p memmove for interleaved 1D-traversable views, or one per each plane of planar -1D-traversable views, or one per each row of interleaved non-1D-traversable images, etc. +As a result \p copy_pixels may result in a single call to \p memmove for interleaved 1D-traversable views, or one per each plane of planar +1D-traversable views, or one per each row of interleaved non-1D-traversable images, etc. GIL also provides some beta-versions of image processing algorithms, such as resampling and convolution in a numerics extension available on http://stlab.adobe.com/gil/download.html. This code is in early stage of development and is not optimized for speed @@ -1875,9 +1875,9 @@ http://stlab.adobe.com/gil/download.html. This code is in early stage of develop


\section ImageSectionDG 10. Image -An image is a container that owns the pixels of a given image view. It allocates them in its constructor and deletes -them in the destructor. It has a deep assignment operator and copy constructor. Images are used rarely, just when -data ownership is important. Most STL algorithms operate on ranges, not containers. Similarly most GIL algorithms operate on image +An image is a container that owns the pixels of a given image view. It allocates them in its constructor and deletes +them in the destructor. It has a deep assignment operator and copy constructor. Images are used rarely, just when +data ownership is important. Most STL algorithms operate on ranges, not containers. Similarly most GIL algorithms operate on image views (which images provide). In the most general form images are N-dimensional and satisfy the following concept: @@ -1892,7 +1892,7 @@ concept RandomAccessNDImageConcept : Regular { Img::Img(point_t dims, std::size_t alignment=0); Img::Img(point_t dims, value_type fill_value, std::size_t alignment); - + void Img::recreate(point_t new_dims, std::size_t alignment=0); void Img::recreate(point_t new_dims, value_type fill_value, std::size_t alignment); @@ -1908,13 +1908,13 @@ Two-dimensional images have additional requirements: concept RandomAccess2DImageConcept { typename x_coord_t = const_view_t::x_coord_t; typename y_coord_t = const_view_t::y_coord_t; - + Img::Img(x_coord_t width, y_coord_t height, std::size_t alignment=0); Img::Img(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment); x_coord_t Img::width() const; y_coord_t Img::height() const; - + void Img::recreate(x_coord_t width, y_coord_t height, std::size_t alignment=1); void Img::recreate(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment); }; @@ -1922,7 +1922,7 @@ concept RandomAccess2DImageConcept { GIL's images have views that model \p ImageViewConcept and operate on pixels. -\code +\code concept ImageConcept { where MutableImageViewConcept; typename coord_t = view_t::coord_t; @@ -1944,13 +1944,13 @@ GIL provides a class, \p image, which is templated over the value type (the pixe \code template > + typename A=std::allocator > class image; \endcode The image constructor takes an alignment parameter which allows for constructing images that are word-aligned or 8-byte aligned. The alignment is specified in bytes. The default value for alignment is 0, which means there is no padding at the end of rows. Many operations are -faster using such 1D-traversable images, because \p image_view::x_iterator can be used to traverse the pixels, instead of the more complicated +faster using such 1D-traversable images, because \p image_view::x_iterator can be used to traverse the pixels, instead of the more complicated \p image_view::iterator. Note that when alignment is 0, packed images are aligned to the bit - i.e. there are no padding bits at the end of rows of packed images.
\section VariantSecDG 11. Run-time specified images and image views @@ -1994,7 +1994,7 @@ myImg = cmyk16_planar_image_t(200,100); myImg = gray8_image_t(); // will throw std::bad_cast \endcode -\p any_image and \p any_image_view subclass from GIL's \p variant class, which breaks down the instantiated type +\p any_image and \p any_image_view subclass from GIL's \p variant class, which breaks down the instantiated type into a non-templated underlying base type and a unique instantiation type identifier. The underlying base instance is represented as a block of bytes. The block is large enough to hold the largest of the specified types. @@ -2013,7 +2013,7 @@ public: variant(); variant(const variant& v); virtual ~variant(); - + variant& operator=(const variant& v); template friend bool operator==(const variant& x, const variant& y); template friend bool operator!=(const variant& x, const variant& y); @@ -2030,22 +2030,22 @@ public: template const T& _dynamic_cast() const; template T& _dynamic_cast(); - + template bool current_type_is() const; }; -template +template UOP::result_type apply_operation(variant& v, UOP op); -template +template UOP::result_type apply_operation(const variant& v, UOP op); -template +template BOP::result_type apply_operation( variant& v1, variant& v2, UOP op); -template +template BOP::result_type apply_operation(const variant& v1, variant& v2, UOP op); -template +template BOP::result_type apply_operation(const variant& v1, const variant& v2, UOP op); \endcode @@ -2058,7 +2058,7 @@ public: typedef ... const_t; // immutable equivalent of this typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image_view(); template explicit any_image_view(const T& obj); @@ -2082,7 +2082,7 @@ public: typedef ... view_t; typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image(); template explicit any_image(const T& obj); @@ -2104,8 +2104,8 @@ public: Operations are invoked on variants via \p apply_operation passing a function object to perform the operation. The code for every allowed type in the variant is instantiated and the appropriate instantiation is selected via a switch statement. Since image view algorithms typically have time complexity -at least linear on the number of pixels, the single switch statement of image view variant adds practically no measurable performance overhead compared -to templated image views. +at least linear on the number of pixels, the single switch statement of image view variant adds practically no measurable performance overhead compared +to templated image views. Variants behave like the underlying type. Their copy constructor will invoke the copy constructor of the underlying instance. Equality operator will check if the two instances are of the same type and then invoke their operator==, etc. The default constructor of a variant will default-construct the @@ -2114,7 +2114,7 @@ has deep ones. It is important to note that even though \p any_image_view and \p any_image resemble the static \p image_view and \p image, they do not model the full requirements of \p ImageViewConcept and \p ImageConcept. In particular they don't provide access to the pixels. There is no "any_pixel" or -"any_pixel_iterator" in GIL. Such constructs could be provided via the \p variant mechanism, but doing so would result in inefficient algorithms, since +"any_pixel_iterator" in GIL. Such constructs could be provided via the \p variant mechanism, but doing so would result in inefficient algorithms, since the type resolution would have to be performed per pixel. Image-level algorithms should be implemented via \p apply_operation. That said, many common operations are shared between the static and dynamic types. In addition, all of the image view transformations and many STL-like image view algorithms have overloads operating on \p any_image_view, as illustrated with \p copy_pixels: @@ -2124,8 +2124,8 @@ rgb8_view_t v1(...); // concrete image view bgr8_view_t v2(...); // concrete image view compatible with v1 and of the same size any_image_view av(...); // run-time specified image view -// Copies the pixels from v1 into v2. -// If the pixels are incompatible triggers compile error +// Copies the pixels from v1 into v2. +// If the pixels are incompatible triggers compile error copy_pixels(v1,v2); // The source or destination (or both) may be run-time instantiated. @@ -2154,15 +2154,15 @@ For example, here is how \p rotated180_view is implemented: \code // implementation using templated view -template +template typename dynamic_xy_step_type::type rotated180_view(const View& src) { ... } namespace detail { // the function, wrapped inside a function object template struct rotated180_view_fn { typedef Result result_type; - template result_type operator()(const View& src) const { - return result_type(rotated180_view(src)); + template result_type operator()(const View& src) const { + return result_type(rotated180_view(src)); } }; } @@ -2170,8 +2170,8 @@ namespace detail { // overloading of the function using variant. Takes and returns run-time bound view. // The returned view has a dynamic step template inline // Models MPL Random Access Container of models of ImageViewConcept -typename dynamic_xy_step_type >::type rotated180_view(const any_image_view& src) { - return apply_operation(src,detail::rotated180_view_fn >::type>()); +typename dynamic_xy_step_type >::type rotated180_view(const any_image_view& src) { + return apply_operation(src,detail::rotated180_view_fn >::type>()); } \endcode @@ -2186,15 +2186,15 @@ them in the same container. \section MetafunctionsDG 12. Useful Metafunctions and Typedefs Flexibility comes at a price. GIL types can be very long and hard to read. -To address this problem, GIL provides typedefs to refer to any standard image, pixel iterator, pixel locator, pixel reference or pixel value. +To address this problem, GIL provides typedefs to refer to any standard image, pixel iterator, pixel locator, pixel reference or pixel value. They follow this pattern:

\e ColorSpace + \e BitDepth + ["s|f"] + ["c"] + ["_planar"] + ["_step"] + \e ClassType + "_t"

Where \e ColorSpace also indicates the ordering of components. Examples are \p rgb, \p bgr, \p cmyk, \p rgba. \e BitDepth can be, for example, - \p 8,\p 16,\p 32. By default the bits are unsigned integral type. Append \p s to the bit depth to indicate signed integral, or \p f to indicate - floating point. \p c indicates object whose associated pixel reference is immutable. \p _planar indicates planar organization (as opposed to interleaved). -\p _step indicates the type has a dynamic step and \e ClassType is \p _image (image, using a standard allocator), \p _view (image view), \p _loc + \p 8,\p 16,\p 32. By default the bits are unsigned integral type. Append \p s to the bit depth to indicate signed integral, or \p f to indicate + floating point. \p c indicates object whose associated pixel reference is immutable. \p _planar indicates planar organization (as opposed to interleaved). +\p _step indicates the type has a dynamic step and \e ClassType is \p _image (image, using a standard allocator), \p _view (image view), \p _loc (pixel locator), \p _ptr (pixel iterator), \p _ref (pixel reference), \p _pixel (pixel value). Here are examples: \code @@ -2211,7 +2211,7 @@ the construct is planar, has a step along the X direction, and is mutable: template struct pixel_reference_type { typedef ... type; }; -template +template struct pixel_value_type { typedef ... type; }; template @@ -2236,27 +2236,27 @@ struct bit_aligned_image_type { typedef ... type; }; There are also helper metafunctions to construct packed and bit-aligned images with up to five channels: \code -template > struct packed_image1_type { typedef ... type; }; -template > struct packed_image2_type { typedef ... type; }; -template > struct packed_image3_type { typedef ... type; }; -template > struct packed_image4_type { typedef ... type; }; -template > struct packed_image5_type { typedef ... type; }; -template > struct bit_aligned_image1_type { typedef ... type; }; @@ -2264,64 +2264,64 @@ template > struct bit_aligned_image2_type { typedef ... type; }; -template > struct bit_aligned_image3_type { typedef ... type; }; -template > struct bit_aligned_image4_type { typedef ... type; }; -template > struct bit_aligned_image5_type { typedef ... type; }; \endcode -Here \p ChannelValue models \p ChannelValueConcept. We don't need \p IsYStep because GIL's memory-based locator and +Here \p ChannelValue models \p ChannelValueConcept. We don't need \p IsYStep because GIL's memory-based locator and view already allow the vertical step to be specified dynamically. Iterators and views can be constructed from a pixel type: \code -template +template struct iterator_type_from_pixel { typedef ... type; }; -template +template struct view_type_from_pixel { typedef ... type; }; \endcode Using a heterogeneous pixel type will result in heterogeneous iterators and views. Types can also be constructed from horizontal iterator: \code -template +template struct type_from_x_iterator { typedef ... step_iterator_t; typedef ... xy_locator_t; typedef ... view_t; }; \endcode - + There are metafunctions to construct the type of a construct from an existing type by changing one or more of its properties: \code -template struct derived_pixel_reference_type { typedef ... type; // Models PixelConcept }; -template struct derived_iterator_type { typedef ... type; // Models PixelIteratorConcept }; -template struct derived_view_type { typedef ... type; // Models ImageViewConcept }; -template struct derived_image_type { typedef ... type; // Models ImageConcept @@ -2335,7 +2335,7 @@ are MPL boolean constants. For example, here is how to create the type of a view typedef typename derived_view_type::type VT; \endcode -You can get pixel-related types of any pixel-based GIL constructs (pixels, iterators, locators and views) using the following +You can get pixel-related types of any pixel-based GIL constructs (pixels, iterators, locators and views) using the following metafunctions provided by PixelBasedConcept, HomogeneousPixelBasedConcept and metafunctions built on top of them: \code @@ -2374,17 +2374,17 @@ For example, a simple planar or interleaved, step or non-step RGB image view is GIL's I/O extension provides low level image i/o utilities. It supports loading and saving several image formats, each of which requires linking against the corresponding library: -- JPEG: To use JPEG files, include the file gil/extension/io/jpeg_io.hpp. If you are using run-time images, -you need to include gil/extension/io/jpeg_dynamic_io.hpp instead. You need to compile and link against libjpeg.lib -(available at http://www.ijg.org). You need to have jpeglib.h in your include path. +- JPEG: To use JPEG files, include the file gil/extension/io/jpeg_io.hpp. If you are using run-time images, +you need to include gil/extension/io/jpeg_dynamic_io.hpp instead. You need to compile and link against libjpeg.lib +(available at http://www.ijg.org). You need to have jpeglib.h in your include path. -- TIFF: To use TIFF files, include the file gil/extension/io/tiff_io.hpp. If you are using run-time images, -you need to include gil/extension/io/tiff_dynamic_io.hpp instead. You need to compile and link against libtiff.lib -(available at http://www.libtiff.org). You need to have tiffio.h in your include path. +- TIFF: To use TIFF files, include the file gil/extension/io/tiff_io.hpp. If you are using run-time images, +you need to include gil/extension/io/tiff_dynamic_io.hpp instead. You need to compile and link against libtiff.lib +(available at http://www.libtiff.org). You need to have tiffio.h in your include path. -- PNG: To use PNG files, include the file gil/extension/io/png_io.hpp. If you are using run-time images, -you need to include gil/extension/io/png_dynamic_io.hpp instead. You need to compile and link against libpng.lib -(available at http://wwwlibpng.org). You need to have png.h in your include path. +- PNG: To use PNG files, include the file gil/extension/io/png_io.hpp. If you are using run-time images, +you need to include gil/extension/io/png_dynamic_io.hpp instead. You need to compile and link against libpng.lib +(available at http://wwwlibpng.org). You need to have png.h in your include path. You don't need to install all these libraries; just the ones you will use. Here are the I/O APIs for JPEG files (replace \p "jpeg" with \p "tiff" or \p "png" for the APIs of the other libraries): @@ -2392,11 +2392,11 @@ Here are the I/O APIs for JPEG files (replace \p "jpeg" with \p "tiff" or \p "pn \code // Returns the width and height of the JPEG file at the specified location. // Throws std::ios_base::failure if the location does not correspond to a valid JPEG file -point2 jpeg_read_dimensions(const char*); +point jpeg_read_dimensions(const char*); // Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it. // Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension. -// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not +// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not // compatible with the ones specified by Image template void jpeg_read_image(const char*, Img&); @@ -2409,7 +2409,7 @@ template void jpeg_read_and_convert_image(const cha // Loads the image specified by the given jpeg image file name into the given view. // Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension. -// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not +// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not // compatible with the ones specified by View, or if its dimensions don't match the ones of the view. template void jpeg_read_view(const char*, const View&); @@ -2445,7 +2445,7 @@ In addition to the above methods, you have the following overloads dealing with template void jpeg_read_image(const char*, any_image&); // Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name. -// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension +// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension // or if it fails to create the file. template void jpeg_write_view(const char*, any_image_view&); \endcode @@ -2461,7 +2461,7 @@ Here are some operations you can do with pixel values, pointers and references: \code rgb8_pixel_t p1(255,0,0); // make a red RGB pixel -bgr8_pixel_t p2 = p1; // RGB and BGR are compatible and the channels will be properly mapped. +bgr8_pixel_t p2 = p1; // RGB and BGR are compatible and the channels will be properly mapped. assert(p1==p2); // p2 will also be red. assert(p2[0]!=p1[0]); // operator[] gives physical channel order (as laid down in memory) assert(semantic_at_c<0>(p1)==semantic_at_c<0>(p2)); // this is how to compare the two red channels @@ -2489,7 +2489,7 @@ Here is how to use pixels in generic code: \code template void gray_to_rgb(const GrayPixel& src, RGBPixel& dst) { - gil_function_requires >(); + gil_function_requires >(); gil_function_requires >(); typedef typename color_space_type::type gray_cs_t; @@ -2523,7 +2523,7 @@ and \p MutablePixelConcept respectively. \subsection SafeAreaExampleDG Creating a Copy of an Image with a Safe Buffer -Suppose we want to convolve an image with multiple kernels, the largest of which is 2K+1 x 2K+1 pixels. It may be worth +Suppose we want to convolve an image with multiple kernels, the largest of which is 2K+1 x 2K+1 pixels. It may be worth creating a margin of K pixels around the image borders. Here is how to do it: \code @@ -2533,7 +2533,7 @@ void create_with_margin(const SrcView& src, int k, DstImage& result) { gil_function_requires >(); gil_function_requires >(); gil_function_requires >(); - + result=DstImage(src.width()+2*k, src.height()+2*k); typename DstImage::view_t centerImg=subimage_view(view(result), k,k,src.width(),src.height()); std::copy(src.begin(), src.end(), centerImg.begin()); @@ -2555,15 +2555,15 @@ void create_with_margin(const SrcView& src, int k, DstImage& result) { (Note also that \p image::recreate is more efficient than \p operator=, as the latter will do an unnecessary copy construction). Not only does the above example work for planar and interleaved images of any color space and pixel depth; it is also optimized. -GIL overrides \p std::copy - when called on two identical interleaved images with no padding at the end of rows, it -simply does a \p memmove. For planar images it does \p memmove for each channel. If one of the images has padding, (as in +GIL overrides \p std::copy - when called on two identical interleaved images with no padding at the end of rows, it +simply does a \p memmove. For planar images it does \p memmove for each channel. If one of the images has padding, (as in our case) it will try to do \p memmove for each row. When an image has no padding, it will use its lightweight horizontal iterator (as opposed to the more complex 1D image iterator that has to check for the end of rows). It choses the fastest method, taking into account both static and run-time parameters. \subsection HistogramExampleDG Histogram -The histogram can be computed by counting the number of pixel values that fall in each bin. +The histogram can be computed by counting the number of pixel values that fall in each bin. The following method takes a grayscale (one-dimensional) image view, since only grayscale pixels are convertible to integers: \code @@ -2635,17 +2635,17 @@ If we call our \p luminosity_histogram with \p step5 it will do the right thing. \section ExtendingGIL_DG 15. Extending the Generic Image Library You can define your own pixel iterators, locators, image views, images, channel types, color spaces and algorithms. -You can make virtual images that live on the disk, inside a jpeg file, somewhere on the internet, or even fully-synthetic images +You can make virtual images that live on the disk, inside a jpeg file, somewhere on the internet, or even fully-synthetic images such as the Mandelbrot set. -As long as they properly model the corresponding concepts, they will work with any existing GIL code. -Most such extensions require no changes to the library and can thus be +As long as they properly model the corresponding concepts, they will work with any existing GIL code. +Most such extensions require no changes to the library and can thus be supplied in another module. \subsection NewColorSpacesDG Defining New Color Spaces Each color space is in a separate file. To add a new color space, just copy one of the existing ones (like rgb.hpp) and change it -accordingly. If you want color conversion support, you will have to provide methods to convert between it and the existing color spaces -(see color_convert.h). For convenience you may want to provide useful typedefs for pixels, pointers, references and images with the new +accordingly. If you want color conversion support, you will have to provide methods to convert between it and the existing color spaces +(see color_convert.h). For convenience you may want to provide useful typedefs for pixels, pointers, references and images with the new color space (see typedefs.h). \subsection NewChannelsDG Defining New Channel Types @@ -2653,7 +2653,7 @@ color space (see typedefs.h). Most of the time you don't need to do anything special to use a new channel type. You can just use it: \code -typedef pixel rgb64_pixel_t; // 64 bit RGB pixel +typedef pixel rgb64_pixel_t; // 64 bit RGB pixel typedef rgb64_pixel* rgb64_pixel_ptr_t;// pointer to 64-bit interleaved data typedef image_type::type rgb64_image_t; // 64-bit interleaved image \endcode @@ -2664,7 +2664,7 @@ If you want to do conversion between your and existing channel types, you will n \subsection NewColorConversionDG Overloading Color Conversion Suppose you want to provide your own color conversion. For example, you may want to implement higher quality color conversion using color profiles. -Typically you may want to redefine color conversion only in some instances and default to GIL's color conversion in all other cases. Here is, for +Typically you may want to redefine color conversion only in some instances and default to GIL's color conversion in all other cases. Here is, for example, how to overload color conversion so that color conversion to gray inverts the result but everything else remains the same: \code @@ -2687,7 +2687,7 @@ struct my_color_converter_impl { // create a color converter object that dispatches to your own implementation struct my_color_converter { template // Model PixelConcept - void operator()(const SrcP& src,DstP& dst) const { + void operator()(const SrcP& src,DstP& dst) const { typedef typename color_space_type::type SrcColorSpace; typedef typename color_space_type::type DstColorSpace; my_color_converter_impl()(src,dst); @@ -2704,9 +2704,9 @@ color_converted_view(img_view,my_color_converter()); \subsection NewImagesDG Defining New Image Views

You can provide your own pixel iterators, locators and views, overriding either the mechanism for getting from one pixel to the next or doing an arbitrary -pixel transformation on dereference. For example, let's look at the implementation of \p color_converted_view (an image factory method that, +pixel transformation on dereference. For example, let's look at the implementation of \p color_converted_view (an image factory method that, given any image view, returns a new, otherwise identical view, except that color conversion is performed on pixel access). -First we need to define a model of \p PixelDereferenceAdaptorConcept; a function object that will be called when we dereference a pixel iterator. +First we need to define a model of \p PixelDereferenceAdaptorConcept; a function object that will be called when we dereference a pixel iterator. It will call \p color_convert to convert to the destination pixel type: \code @@ -2757,7 +2757,7 @@ typename color_converted_view_type::type color_convert_view(const Vie \endcode (The actual color convert view transformation is slightly more complicated, as it takes an optional color conversion object, which -allows users to specify their own color conversion methods). +allows users to specify their own color conversion methods). See the GIL tutorial for an example of creating a virtual image view that defines the Mandelbrot set.


@@ -2841,7 +2841,7 @@ We are grateful to Dave Abrahams, Sean Parent and Alex Stepanov for suggesting t can be provided by modeling the corresponding GIL concepts. \li Compatibility. The library is designed as an STL complement. Generic STL algorithms can be used for pixel manipulation, and they are specifically targeted for optimization. The library works with existing raw pixel data from another image library. - +
*/ diff --git a/doc/doxygen/tutorial.dox b/doc/doxygen/tutorial.dox index 193a61639..49cd94f3b 100644 --- a/doc/doxygen/tutorial.dox +++ b/doc/doxygen/tutorial.dox @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////////////// -/// \file +/// \file /// \brief Doxygen documentation /// \author Lubomir Bourdev and Hailin Jin \n /// Adobe Systems Incorporated @@ -16,10 +16,10 @@ \version 2.1 \date September 15, 2007 -The Generic Image Library (GIL) is a C++ library that abstracts image representations from algorithms and allows writing code that can work on +The Generic Image Library (GIL) is a C++ library that abstracts image representations from algorithms and allows writing code that can work on a variety of images with performance similar to hand-writing for a specific image type.

This document will give you a jump-start in using GIL. It does not discuss the underlying design -of the library and does not cover all aspects of it. You can find a detailed library design document on the main GIL web page +of the library and does not cover all aspects of it. You can find a detailed library design document on the main GIL web page at http://stlab.adobe.com/gil - \ref InstallSec @@ -42,24 +42,24 @@ at http://stlab.adobe.com/gil \section InstallSec Installation The latest version of GIL can be downloaded from GIL's web page, at http://stlab.adobe.com/gil. -GIL is approved for integration into Boost and in the future will be installed simply by installing Boost from http://www.boost.org. +GIL is approved for integration into Boost and in the future will be installed simply by installing Boost from http://www.boost.org. GIL consists of header files only and does not require any libraries to link against. It does not require Boost to be built. Including \p boost/gil.hpp will be sufficient for most projects. \section ExampleSec Example - Computing the Image Gradient -This tutorial will walk through an example of using GIL to compute the image gradients. +This tutorial will walk through an example of using GIL to compute the image gradients. We will start with some very simple and non-generic code and make it more generic as we go along. Let us start with a horizontal gradient and use the simplest possible approximation to a gradient - central difference. The gradient at pixel x can be approximated with the half-difference of its two neighboring pixels: D[x] = (I[x-1] - I[x+1]) / 2 -For simplicity, we will also ignore the boundary cases - the pixels along the edges of the image for which one of the neighbors is not defined. +For simplicity, we will also ignore the boundary cases - the pixels along the edges of the image for which one of the neighbors is not defined. The focus of this document is how to use GIL, not how to create a good gradient generation algorithm. \subsection InterfaceSec Interface and Glue Code -Let us first start with 8-bit unsigned grayscale image as the input and 8-bit signed grayscale image as the output. +Let us first start with 8-bit unsigned grayscale image as the input and 8-bit signed grayscale image as the output. Here is how the interface to our algorithm looks like: \code @@ -86,7 +86,7 @@ allow for modifying its pixels. Most GIL algorithms operate on image views; images are rarely needed. GIL's design is very similar to that of the STL. The STL equivalent of GIL's image is a container, like \p std::vector, whereas GIL's image view corresponds to STL's range, which is often represented with a pair of iterators. STL algorithms operate on ranges, just like GIL algorithms operate on image views. -GIL's image views can be constructed from raw data - the dimensions, the number of bytes per row and the pixels, which for chunky views are represented with one pointer. Here is how to provide +GIL's image views can be constructed from raw data - the dimensions, the number of bytes per row and the pixels, which for chunky views are represented with one pointer. Here is how to provide the glue between your code and GIL: \code @@ -98,7 +98,7 @@ void ComputeXGradientGray8(const unsigned char* src_pixels, ptrdiff_t src_row_by } \endcode -This glue code is very fast and views are lightweight - in the above example the views have a size of 16 bytes. They consist of a pointer to the top left pixel and three integers - the width, height, +This glue code is very fast and views are lightweight - in the above example the views have a size of 16 bytes. They consist of a pointer to the top left pixel and three integers - the width, height, and number of bytes per row. \subsection FirstImplementationSec First Implementation @@ -116,7 +116,7 @@ void x_gradient(const gray8c_view_t& src, const gray8s_view_t& dst) { We use image view's \p operator(x,y) to get a reference to the pixel at a given location and we set it to the half-difference of its left and right neighbors. operator() returns a reference to a grayscale pixel. A grayscale pixel is convertible to its channel type (unsigned char for \p src) and it can be copy-constructed from a channel. (This is only true for grayscale pixels). -While the above code is easy to read, it is not very fast, because the binary \p operator() computes the location of the pixel in a 2D grid, which involves addition and multiplication. Here is +While the above code is easy to read, it is not very fast, because the binary \p operator() computes the location of the pixel in a 2D grid, which involves addition and multiplication. Here is a faster version of the above: \code @@ -131,7 +131,7 @@ void x_gradient(const gray8c_view_t& src, const gray8s_view_t& dst) { } \endcode -We use pixel iterators initialized at the beginning of each row. GIL's iterators are Random Access Traversal iterators. If you are not familiar with random access iterators, think of them as if they +We use pixel iterators initialized at the beginning of each row. GIL's iterators are Random Access Traversal iterators. If you are not familiar with random access iterators, think of them as if they were pointers. In fact, in the above example the two iterator types are raw C pointers and their \p operator[] is a fast pointer indexing operator. The code to compute gradient in the vertical direction is very similar: @@ -194,13 +194,13 @@ void y_gradient(const gray8c_view_t& src, const gray8s_view_t& dst) { ++dst_it; ++src_loc.x(); // each dimension can be advanced separately } - src_loc+=point2(-src.width(),1); // carriage return + src_loc+=point(-src.width(),1); // carriage return } } \endcode The first line creates a locator pointing to the first pixel of the second row of the source view. A GIL pixel locator is very similar to an iterator, -except that it can move both horizontally and vertically. \p src_loc.x() and \p src_loc.y() return references to a horizontal and a vertical iterator +except that it can move both horizontally and vertically. \p src_loc.x() and \p src_loc.y() return references to a horizontal and a vertical iterator respectively, which can be used to move the locator along the desired dimension, as shown above. Additionally, the locator can be advanced in both dimensions simultaneously using its \p operator+= and \p operator-=. Similar to image views, locators provide binary \p operator() which returns a reference to a pixel with a relative offset to the current locator position. For example, \p src_loc(0,1) returns a reference to the neighbor below the current pixel. @@ -221,9 +221,9 @@ void y_gradient(const gray8c_view_t& src, const gray8s_view_t& dst) { for (int x=0; x(-src.width(),1); + src_loc+=point(-src.width(),1); } } \endcode @@ -241,21 +241,21 @@ void x_gradient(const SrcView& src, const DstView& dst) { gil_function_requires >(); gil_function_requires >(); gil_function_requires::type, + typename color_space_type::type, typename color_space_type::type> >(); - + ... // compute the gradient } \endcode The new algorithm now takes the types of the input and output image views as template parameters. That allows using both built-in GIL image views, as well as any user-defined image view classes. -The first three lines are optional; they use \p boost::concept_check to ensure that the two arguments +The first three lines are optional; they use \p boost::concept_check to ensure that the two arguments are valid GIL image views, that the second one is mutable and that their color spaces are compatible (i.e. have the same set of channels). GIL does not require using its own built-in constructs. You are free to use your own channels, color spaces, iterators, locators, views and images. However, to work with the rest of GIL they have to satisfy a set of requirements; in other words, they have to \e model the corresponding GIL \e concept. -GIL's concepts are defined in the user guide. +GIL's concepts are defined in the user guide. One of the biggest drawbacks of using templates and generic programming in C++ is that compile errors can be very difficult to comprehend. @@ -263,8 +263,8 @@ This is a side-effect of the lack of early type checking - a generic argument ma but the incompatibility may be triggered deep into a nested call, in code unfamiliar and hardly related to the problem. GIL uses \p boost::concept_check to mitigate this problem. The above three lines of code check whether the template parameters are valid models of their corresponding concepts. -If a model is incorrect, the compile error will be inside \p gil_function_requires, which is much closer to the problem -and easier to track. Furthermore, such checks get compiled out and have zero performance overhead. The disadvantage of using +If a model is incorrect, the compile error will be inside \p gil_function_requires, which is much closer to the problem +and easier to track. Furthermore, such checks get compiled out and have zero performance overhead. The disadvantage of using concept checks is the sometimes severe impact they have on compile time. This is why GIL performs concept checks only in debug mode, and only if \p BOOST_GIL_USE_CONCEPT_CHECK is defined (off by default). @@ -304,7 +304,7 @@ void x_gradient(const SrcView& src, const DstView& dst) { typename DstView::x_iterator dst_it = dst.row_begin(y); for (int x=1; x()); } } @@ -312,8 +312,8 @@ void x_gradient(const SrcView& src, const DstView& dst) { \p static_transform is an example of a channel-level GIL algorithm. Other such algorithms are \p static_generate, \p static_fill and \p static_for_each. They are the channel-level equivalents of STL's \p generate, \p transform, \p fill and \p for_each respectively. GIL channel algorithms use static recursion to unroll the loops; they never loop over the channels explicitly. -Note that sometimes modern compilers (at least Visual Studio 8) already unroll channel-level loops, such as the one above. However, another advantage of using -GIL's channel-level algorithms is that they pair the channels semantically, not based on their order in memory. For example, the above example will properly match an RGB source +Note that sometimes modern compilers (at least Visual Studio 8) already unroll channel-level loops, such as the one above. However, another advantage of using +GIL's channel-level algorithms is that they pair the channels semantically, not based on their order in memory. For example, the above example will properly match an RGB source with a BGR destination. Here is how we can use our generic version with images of different types: @@ -337,7 +337,7 @@ void XGradientRGB8_BGR16(const unsigned char* src_pixels, ptrdiff_t src_row_byte // Either or both the source and the destination could be planar - the gradient code does not change void XGradientPlanarRGB8_RGB32( - const unsigned short* src_r, const unsigned short* src_g, const unsigned short* src_b, + const unsigned short* src_r, const unsigned short* src_g, const unsigned short* src_b, ptrdiff_t src_row_bytes, int w, int h, signed int* dst_pixels, ptrdiff_t dst_row_bytes) { rgb16c_planar_view_t src=planar_rgb_view (w,h, src_r,src_g,src_b, src_row_bytes); @@ -346,7 +346,7 @@ void XGradientPlanarRGB8_RGB32( } \endcode -As these examples illustrate, both the source and the destination can be interleaved or planar, of any channel depth (assuming the destination channel is +As these examples illustrate, both the source and the destination can be interleaved or planar, of any channel depth (assuming the destination channel is assignable to the source), and of any compatible color spaces. GIL 2.1 can also natively represent images whose channels are not byte-aligned, such as 6-bit RGB222 image or a 1-bit Gray1 image. @@ -375,8 +375,8 @@ void y_gradient(const SrcView& src, const DstView& dst) { \endcode \p rotated90ccw_view takes an image view and returns an image view representing 90-degrees counter-clockwise rotation of its input. It is an example of a GIL view transformation function. GIL provides -a variety of transformation functions that can perform any axis-aligned rotation, transpose the view, flip it vertically or horizontally, extract a rectangular subimage, -perform color conversion, subsample view, etc. The view transformation functions are fast and shallow - they don't copy the pixels, they just change the "coordinate system" of +a variety of transformation functions that can perform any axis-aligned rotation, transpose the view, flip it vertically or horizontally, extract a rectangular subimage, +perform color conversion, subsample view, etc. The view transformation functions are fast and shallow - they don't copy the pixels, they just change the "coordinate system" of accessing the pixels. \p rotated90cw_view, for example, returns a view whose horizontal iterators are the vertical iterators of the original view. The above code to compute \p y_gradient is slow because of the memory access pattern; using \p rotated90cw_view does not make it any slower. @@ -439,9 +439,9 @@ void x_gradient_unguarded(const gray8c_view_t& src, const gray8s_view_t& dst) { } \endcode -GIL image views provide \p begin() and \p end() methods that return one dimensional pixel iterators which iterate over each pixel in the view, -left to right and top to bottom. They do a proper "carriage return" - they skip any unused bytes at the end of a row. As such, they are slightly suboptimal, because they need to keep -track of their current position with respect to the end of the row. Their increment operator performs one extra check (are we at the end of the row?), a check that is avoided if two +GIL image views provide \p begin() and \p end() methods that return one dimensional pixel iterators which iterate over each pixel in the view, +left to right and top to bottom. They do a proper "carriage return" - they skip any unused bytes at the end of a row. As such, they are slightly suboptimal, because they need to keep +track of their current position with respect to the end of the row. Their increment operator performs one extra check (are we at the end of the row?), a check that is avoided if two nested loops are used instead. These iterators have a method \p x() which returns the more lightweight horizontal iterator that we used previously. Horizontal iterators have no notion of the end of rows. In this case, the horizontal iterators are raw C pointers. In our example, we must use the horizontal iterators to access the two neighbors properly, since they could reside outside the image view. @@ -464,7 +464,7 @@ void x_gradient_unguarded(const gray8c_view_t& src, const gray8s_view_t& dst) { } \endcode -GIL provides the algorithms \p for_each_pixel and \p transform_pixels which are image view equivalents of STL's \p std::for_each and \p std::transform. It also provides +GIL provides the algorithms \p for_each_pixel and \p transform_pixels which are image view equivalents of STL's \p std::for_each and \p std::transform. It also provides \p for_each_pixel_position and \p transform_pixel_positions, which instead of references to pixels, pass to the generic function pixel locators. This allows for more powerful functions that can use the pixel neighbors through the passed locators. GIL algorithms iterate through the pixels using the more efficient two nested loops (as opposed to the single loop using 1-D iterators) @@ -480,7 +480,7 @@ void x_gradient_rgb_luminosity(const rgb32fc_view_t& src, const gray8s_view_t& d } \endcode -\p color_converted_view is a GIL view transformation function that takes any image view and returns a view in a target color space and channel depth (specified +\p color_converted_view is a GIL view transformation function that takes any image view and returns a view in a target color space and channel depth (specified as template parameters). In our example, it constructs an 8-bit integer grayscale view over 32-bit float RGB pixels. Like all other view transformation functions, \p color_converted_view is very fast and shallow. It doesn't copy the data or perform any color conversion. Instead it returns a view that performs color conversion every time its pixels are accessed. @@ -536,13 +536,13 @@ void x_luminosity_gradient(const SrcView& src, const DstView& dst) { First we use the \p channel_type metafunction to get the channel type of the destination view. A metafunction is a function operating on types. In GIL metafunctions are structs which take their parameters as template parameters and return their result in a nested typedef called \p type. In this case, \p channel_type is -a unary metafunction which in this example is called with the type of an image view and returns the type of the channel associated with that image view. +a unary metafunction which in this example is called with the type of an image view and returns the type of the channel associated with that image view. GIL constructs that have an associated pixel type, such as pixels, pixel iterators, locators, views and images, all model \p PixelBasedConcept, which means -that they provide a set of metafunctions to query the pixel properties, such as \p channel_type, \p color_space_type, \p channel_mapping_type, and \p num_channels. +that they provide a set of metafunctions to query the pixel properties, such as \p channel_type, \p color_space_type, \p channel_mapping_type, and \p num_channels. After we get the channel type of the destination view, we use another metafunction to remove its sign (if it is a signed integral type) and then use it -to generate the type of a grayscale pixel. From the pixel type we create the image type. GIL's image class is templated over the pixel type and a boolean +to generate the type of a grayscale pixel. From the pixel type we create the image type. GIL's image class is templated over the pixel type and a boolean indicating whether the image should be planar or interleaved. Single-channel (grayscale) images in GIL must always be interleaved. There are multiple ways of constructing types in GIL. Instead of instantiating the classes directly we could have used type factory metafunctions. The following code is equivalent: @@ -563,11 +563,11 @@ void x_luminosity_gradient(const SrcView& src, const DstView& dst) { GIL provides a set of metafunctions that generate GIL types - \p image_type is one such meta-function that constructs the type of an image from a given channel type, color layout, and planar/interleaved option (the default is interleaved). There are also similar meta-functions to -construct the types of pixel references, iterators, locators and image views. GIL also has metafunctions \p derived_pixel_reference_type, \p derived_iterator_type, -\p derived_view_type and \p derived_image_type that construct the type of a GIL construct from a given source one by changing one or more properties of +construct the types of pixel references, iterators, locators and image views. GIL also has metafunctions \p derived_pixel_reference_type, \p derived_iterator_type, +\p derived_view_type and \p derived_image_type that construct the type of a GIL construct from a given source one by changing one or more properties of the type and keeping the rest. -From the image type we can use the nested typedef \p value_type to obtain the type of a pixel. GIL images, image views and locators have nested typedefs +From the image type we can use the nested typedef \p value_type to obtain the type of a pixel. GIL images, image views and locators have nested typedefs \p value_type and \p reference to obtain the type of the pixel and a reference to the pixel. If you have a pixel iterator, you can get these types from its \p iterator_traits. Note also the algorithm \p copy_and_convert_pixels, which is an abbreviated version of \p copy_pixels with a color converted source view. @@ -579,7 +579,7 @@ First, we need to create a function object that computes the value of the Mandel \code // models PixelDereferenceAdaptorConcept struct mandelbrot_fn { - typedef point2 point_t; + typedef point point_t; typedef mandelbrot_fn const_t; typedef gray8_pixel_t value_type; @@ -594,16 +594,16 @@ struct mandelbrot_fn { result_type operator()(const point_t& p) const { // normalize the coords to (-2..1, -1.5..1.5) - double t=get_num_iter(point2(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.5f)); + double t=get_num_iter(point(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.5f)); return value_type((bits8)(pow(t,0.2)*255)); // raise to power suitable for viewing } private: point_t _img_size; - double get_num_iter(const point2& p) const { - point2 Z(0,0); + double get_num_iter(const point& p) const { + point Z(0,0); for (int i=0; i<100; ++i) { // 100 iterations - Z = point2(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); + Z = point(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); if (Z.x*Z.x + Z.y*Z.y > 4) return i/(double)100; } @@ -645,7 +645,7 @@ Here is what the two files look like: So far we have created a generic function that computes the image gradient of a templated image view. Sometimes, however, the properties of an image view, such as its color space and channel depth, may not be available at compile time. GIL's \p dynamic_image extension allows for working with GIL constructs that are specified at run time, also called \e variants. GIL provides -models of a run-time instantiated image, \p any_image, and a run-time instantiated image view, \p any_image_view. The mechanisms are in place to create +models of a run-time instantiated image, \p any_image, and a run-time instantiated image view, \p any_image_view. The mechanisms are in place to create other variants, such as \p any_pixel, \p any_pixel_iterator, etc. Most of GIL's algorithms and all of the view transformation functions also work with run-time instantiated image views and binary algorithms, such as \p copy_pixels can have either or both arguments be variants. @@ -661,11 +661,11 @@ First, we need to make a function object that contains the templated destination template struct x_gradient_obj { typedef void result_type; // required typedef - + const DstView& _dst; x_gradient_obj(const DstView& dst) : _dst(dst) {} - template + template void operator()(const SrcView& src) const { x_luminosity_gradient(src, _dst); } }; \endcode @@ -711,9 +711,9 @@ For templated images \p view(img) returns a templated view, whereas for image va For example, the return type of \p view(runtime_image) is \p any_image_view where \p Views enumerates four views corresponding to the four image types. \p const_view(runtime_image) returns a \p any_image_view of the four read-only view types, etc. -A warning about using variants: instantiating an algorithm with a variant effectively instantiates it with every possible type the variant can take. -For binary algorithms, the algorithm is instantiated with every possible combination of the two input types! This can take a toll on both the compile time -and the executable size. +A warning about using variants: instantiating an algorithm with a variant effectively instantiates it with every possible type the variant can take. +For binary algorithms, the algorithm is instantiated with every possible combination of the two input types! This can take a toll on both the compile time +and the executable size. \section ConclusionSec Conclusion @@ -725,16 +725,16 @@ is comparable to that of a C version of the algorithm, hand-written for the spec Yet, even for such a simple algorithm, we are far from making a fully generic and optimized code. In particular, the presented algorithms work on homogeneous images, i.e. images whose pixels have channels that are all of the same type. There are examples of images, such as a packed 565 RGB format, which contain -channels of different types. While GIL provides concepts and algorithms operating on heterogeneous pixels, we leave the task of extending x_gradient as an +channels of different types. While GIL provides concepts and algorithms operating on heterogeneous pixels, we leave the task of extending x_gradient as an exercise for the reader. -Second, after computing the value of the gradient we are simply casting it to the destination channel type. This may not always be the desired operation. For -example, if the source channel is a float with range [0..1] and the destination is unsigned char, casting the half-difference to unsigned char will result in +Second, after computing the value of the gradient we are simply casting it to the destination channel type. This may not always be the desired operation. For +example, if the source channel is a float with range [0..1] and the destination is unsigned char, casting the half-difference to unsigned char will result in either 0 or 1. Instead, what we might want to do is scale the result into the range of the destination channel. GIL's channel-level algorithms might be useful in such cases. For example, \p channel_convert converts between channels by linearly scaling the source channel value into the range of the destination channel. -There is a lot to be done in improving the performance as well. Channel-level operations, such as the half-difference, could be abstracted out into atomic -channel-level algorithms and performance overloads could be provided for concrete channel types. Processor-specific operations could be used, for example, -to perform the operation over an entire row of pixels simultaneously, or the data could be prefetched. All of these optimizations can be realized as performance +There is a lot to be done in improving the performance as well. Channel-level operations, such as the half-difference, could be abstracted out into atomic +channel-level algorithms and performance overloads could be provided for concrete channel types. Processor-specific operations could be used, for example, +to perform the operation over an entire row of pixels simultaneously, or the data could be prefetched. All of these optimizations can be realized as performance specializations of the generic algorithm. Finally, compilers, while getting better over time, are still failing to fully optimize generic code in some cases, such as failing to inline some functions or put some variables into registers. If performance is an issue, it might be worth trying your code with different compilers. @@ -748,12 +748,12 @@ Concrete (non-generic) GIL types follow this naming convention: \e ColorSpace + \e BitDepth + [\p f | \p s]+ [\p c] + [\p _planar] + [\p _step] + \e ClassType + \p _t

-Where \e ColorSpace also indicates the ordering of components. Examples are \p rgb, \p bgr, \p cmyk, \p rgba. +Where \e ColorSpace also indicates the ordering of components. Examples are \p rgb, \p bgr, \p cmyk, \p rgba. \e BitDepth indicates the bit depth of the color channel. Examples are \p 8,\p 16,\p 32. By default the type of channel is unsigned integral; using \p s indicates -signed integral and \p f - a floating point type, which is always signed. \p c indicates object operating over immutable pixels. \p _planar indicates planar organization -(as opposed to interleaved). \p _step indicates special image views, -locators and iterators which traverse the data in non-trivial way (for example, backwards or every other pixel). -\e ClassType is \p _image (image), \p _view (image view), \p _loc (pixel 2D locator) \p _ptr (pixel iterator), \p _ref (pixel reference), +signed integral and \p f - a floating point type, which is always signed. \p c indicates object operating over immutable pixels. \p _planar indicates planar organization +(as opposed to interleaved). \p _step indicates special image views, +locators and iterators which traverse the data in non-trivial way (for example, backwards or every other pixel). +\e ClassType is \p _image (image), \p _view (image view), \p _loc (pixel 2D locator) \p _ptr (pixel iterator), \p _ref (pixel reference), \p _pixel (pixel value). \code diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 2f917f641..eeacb69e9 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -216,7 +216,7 @@ relative access can be done with GIL locators:: ++dst_it; ++src_loc.x(); // each dimension can be advanced separately } - src_loc+=point2(-src.width(),1); // carriage return + src_loc+=point(-src.width(),1); // carriage return } } @@ -259,7 +259,7 @@ reuse this offset:: ++dst_it; ++src_loc.x(); } - src_loc+=point2(-src.width(),1); + src_loc+=point(-src.width(),1); } } @@ -720,7 +720,7 @@ location (x,y) in the image:: // models PixelDereferenceAdaptorConcept struct mandelbrot_fn { - typedef point2 point_t; + typedef point point_t; typedef mandelbrot_fn const_t; typedef gray8_pixel_t value_type; @@ -736,18 +736,18 @@ location (x,y) in the image:: result_type operator()(const point_t& p) const { // normalize the coords to (-2..1, -1.5..1.5) - double t=get_num_iter(point2(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.5f)); + double t=get_num_iter(point(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.5f)); return value_type((bits8)(pow(t,0.2)*255)); // raise to power suitable for viewing } private: point_t _img_size; - double get_num_iter(const point2& p) const + double get_num_iter(const point& p) const { - point2 Z(0,0); + point Z(0,0); for (int i=0; i<100; ++i) // 100 iterations { - Z = point2(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); + Z = point(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); if (Z.x*Z.x + Z.y*Z.y > 4) return i/(double)100; } diff --git a/example/affine.cpp b/example/affine.cpp index f8f2b2cfa..a54cfaa1d 100644 --- a/example/affine.cpp +++ b/example/affine.cpp @@ -25,7 +25,7 @@ int main() gil::fill_pixels(gil::view(transf), gil::rgb8_pixel_t(255, 0, 0)); // the background is red gil::matrix3x2 mat = - gil::matrix3x2::get_translate(-gil::point2(200,250)) * + gil::matrix3x2::get_translate(-gil::point(200,250)) * gil::matrix3x2::get_rotate(-15*3.14/180.0); gil::resample_pixels(const_view(img), gil::view(transf), mat, gil::nearest_neighbor_sampler()); gil::write_view("out-affine.jpg", gil::view(transf), gil::jpeg_tag()); diff --git a/example/mandelbrot.cpp b/example/mandelbrot.cpp index 0bd86c1c5..cdd543ed8 100644 --- a/example/mandelbrot.cpp +++ b/example/mandelbrot.cpp @@ -17,8 +17,7 @@ using namespace boost::gil; template // Models PixelValueConcept struct mandelbrot_fn { - typedef point2 point_t; - + using point_t = boost::gil::point_t; typedef mandelbrot_fn const_t; typedef P value_type; typedef value_type reference; @@ -37,7 +36,7 @@ struct mandelbrot_fn result_type operator()(const point_t& p) const { // normalize the coords to (-2..1, -1.5..1.5) // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods) - double t=get_num_iter(point2(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); + double t=get_num_iter(point(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); t=pow(t,0.2); value_type ret; @@ -47,10 +46,10 @@ struct mandelbrot_fn } private: - double get_num_iter(const point2& p) const { - point2 Z(0,0); + double get_num_iter(const point& p) const { + point Z(0,0); for (int i=0; i(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); + Z = point(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); if (Z.x*Z.x + Z.y*Z.y > 4) return i/(double)MAX_ITER; } diff --git a/include/boost/gil/concepts.hpp b/include/boost/gil/concepts.hpp index c5847e22d..89baf766a 100644 --- a/include/boost/gil/concepts.hpp +++ b/include/boost/gil/concepts.hpp @@ -39,9 +39,9 @@ template struct channel_traits; template struct is_pixel; template typename channel_traits::value_type channel_convert(const srcT& val); -template class point2; -template const T& axis_value(const point2& p); -template T& axis_value( point2& p); +template class point; +template const T& axis_value(point const& p); +template T& axis_value(point& p); template struct kth_element_type; template struct kth_element_reference_type; template struct kth_element_const_reference_type; diff --git a/include/boost/gil/extension/dynamic_image/any_image.hpp b/include/boost/gil/extension/dynamic_image/any_image.hpp index ccbb2577f..66d0e47fc 100644 --- a/include/boost/gil/extension/dynamic_image/any_image.hpp +++ b/include/boost/gil/extension/dynamic_image/any_image.hpp @@ -15,8 +15,8 @@ #include #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -#pragma warning(push) -#pragma warning(disable:4512) //assignment operator could not be generated +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated #endif namespace boost { namespace gil { @@ -28,13 +28,15 @@ namespace detail { template struct get_const_view_t { typedef typename T::const_view_t type; }; template struct images_get_const_views_t : public mpl::transform > {}; - struct recreate_image_fnobj { + struct recreate_image_fnobj + { typedef void result_type; - const point2& _dimensions; + point const& _dimensions; unsigned _alignment; - recreate_image_fnobj(const point2& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {} - template result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); } + recreate_image_fnobj(point const& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {} + template + result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); } }; template // Models AnyViewConcept @@ -53,7 +55,7 @@ namespace detail { //////////////////////////////////////////////////////////////////////////////////////// /// \ingroup ImageModel /// \brief Represents a run-time specified image. Note it does NOT model ImageConcept -/// +/// /// Represents an image whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time. /// It is the runtime equivalent of \p image. /// Some of the requirements of ImageConcept, such as the \p value_type typedef cannot be fulfilled, since the language does not allow runtime type specification. @@ -68,7 +70,7 @@ public: typedef any_image_view::type> view_t; typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image() : parent_t() {} template explicit any_image(const T& obj) : parent_t(obj) {} @@ -80,8 +82,15 @@ public: any_image& operator=(const any_image& v) { parent_t::operator=((const parent_t&)v); return *this;} template any_image& operator=(const any_image& v) { parent_t::operator=((const variant&)v); return *this;} - void recreate(const point_t& dims, unsigned alignment=1) { apply_operation(*this,detail::recreate_image_fnobj(dims,alignment)); } - void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1) { recreate(point2(width,height),alignment); } + void recreate(const point_t& dims, unsigned alignment=1) + { + apply_operation(*this,detail::recreate_image_fnobj(dims,alignment)); + } + + void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1) + { + recreate({width, height}, alignment); + } std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); } point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); } @@ -97,21 +106,21 @@ public: /// \brief Returns the non-constant-pixel view of any image. The returned view is any view. template BOOST_FORCEINLINE // Models ImageVectorConcept -typename any_image::view_t view(any_image& anyImage) { +typename any_image::view_t view(any_image& anyImage) { return apply_operation(anyImage, detail::any_image_get_view::view_t>()); } /// \brief Returns the constant-pixel view of any image. The returned view is any view. template BOOST_FORCEINLINE // Models ImageVectorConcept -typename any_image::const_view_t const_view(const any_image& anyImage) { +typename any_image::const_view_t const_view(const any_image& anyImage) { return apply_operation(anyImage, detail::any_image_get_const_view::const_view_t>()); } ///@} }} // namespace boost::gil -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -#pragma warning(pop) -#endif +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif #endif diff --git a/include/boost/gil/extension/dynamic_image/any_image_view.hpp b/include/boost/gil/extension/dynamic_image/any_image_view.hpp index 2a3527e59..7c9bfa08b 100644 --- a/include/boost/gil/extension/dynamic_image/any_image_view.hpp +++ b/include/boost/gil/extension/dynamic_image/any_image_view.hpp @@ -24,13 +24,21 @@ template struct dynamic_xy_step_type; template struct dynamic_xy_step_transposed_type; namespace detail { - struct any_type_get_num_channels { // works for both image_view and image + + // works for both image_view and image + struct any_type_get_num_channels + { typedef int result_type; - template result_type operator()(const T&) const { return num_channels::value; } + template + result_type operator()(const T&) const { return num_channels::value; } }; - struct any_type_get_dimensions { // works for both image_view and image - typedef point2 result_type; - template result_type operator()(const T& v) const { return v.dimensions(); } + + // works for both image_view and image + struct any_type_get_dimensions + { + using result_type = point; + template + result_type operator()(const T& v) const { return v.dimensions(); } }; } @@ -55,7 +63,7 @@ public: typedef any_image_view::type> const_t; typedef std::ptrdiff_t x_coord_t; typedef std::ptrdiff_t y_coord_t; - typedef point2 point_t; + typedef point point_t; any_image_view() : parent_t() {} template explicit any_image_view(const T& obj) : parent_t(obj) {} diff --git a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp index cf644d147..f46e24a2b 100644 --- a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp +++ b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp @@ -43,18 +43,40 @@ template struct rotated180_view_fn { typedef Result result_type; template result_type operator()(const View& src) const { return result_type(rotated180_view(src)); } }; -template struct subimage_view_fn { + +template +struct subimage_view_fn +{ typedef Result result_type; - subimage_view_fn(const point2& topleft, const point2& dimensions) : _topleft(topleft), _size2(dimensions) {} - point2 _topleft,_size2; - template result_type operator()(const View& src) const { return result_type(subimage_view(src,_topleft,_size2)); } + subimage_view_fn(point_t const& topleft, point_t const& dimensions) + : _topleft(topleft), _size2(dimensions) + {} + + template + result_type operator()(const View& src) const + { + return result_type(subimage_view(src,_topleft,_size2)); + } + + point_t _topleft; + point_t _size2; }; -template struct subsampled_view_fn { + +template +struct subsampled_view_fn +{ typedef Result result_type; - subsampled_view_fn(const point2& step) : _step(step) {} - point2 _step; - template result_type operator()(const View& src) const { return result_type(subsampled_view(src,_step)); } + subsampled_view_fn(point_t const& step) : _step(step) {} + + template + result_type operator()(const View& src) const + { + return result_type(subsampled_view(src,_step)); + } + + point_t _step; }; + template struct nth_channel_view_fn { typedef Result result_type; nth_channel_view_fn(int n) : _n(n) {} @@ -104,33 +126,57 @@ typename dynamic_xy_step_transposed_type >::type rotat } /// \ingroup ImageViewTransformations180 -template inline // Models MPL Random Access Container of models of ImageViewConcept -typename dynamic_xy_step_type >::type rotated180_view(const any_image_view& src) { - return apply_operation(src,detail::rotated180_view_fn >::type>()); +/// Models MPL Random Access Container of models of ImageViewConcept +template +inline auto rotated180_view(const any_image_view& src) + -> typename dynamic_xy_step_type>::type +{ + using step_type = typename dynamic_xy_step_type>::type; + return apply_operation(src, detail::rotated180_view_fn()); } /// \ingroup ImageViewTransformationsSubimage -template inline // Models MPL Random Access Container of models of ImageViewConcept -any_image_view subimage_view(const any_image_view& src, const point2& topleft, const point2& dimensions) { - return apply_operation(src,detail::subimage_view_fn >(topleft,dimensions)); +/// // Models MPL Random Access Container of models of ImageViewConcept +template +inline auto subimage_view(any_image_view const& src, + point_t const& topleft, point_t const& dimensions) + -> any_image_view +{ + using subimage_view_fn = detail::subimage_view_fn>; + return apply_operation(src, subimage_view_fn(topleft, dimensions)); } /// \ingroup ImageViewTransformationsSubimage -template inline // Models MPL Random Access Container of models of ImageViewConcept -any_image_view subimage_view(const any_image_view& src, int xMin, int yMin, int width, int height) { - return apply_operation(src,detail::subimage_view_fn >(point2(xMin,yMin),point2(width,height))); +/// Models MPL Random Access Container of models of ImageViewConcept +template +inline auto subimage_view(any_image_view const& src, + int xMin, int yMin, int width, int height) + -> any_image_view +{ + using subimage_view_fn = detail::subimage_view_fn>; + return apply_operation(src, subimage_view_fn(point_t(xMin, yMin),point_t(width, height))); } /// \ingroup ImageViewTransformationsSubsampled -template inline // Models MPL Random Access Container of models of ImageViewConcept -typename dynamic_xy_step_type >::type subsampled_view(const any_image_view& src, const point2& step) { - return apply_operation(src,detail::subsampled_view_fn >::type>(step)); +/// Models MPL Random Access Container of models of ImageViewConcept +template +inline auto subsampled_view(any_image_view const& src, point_t const& step) + -> typename dynamic_xy_step_type>::type +{ + using step_type = typename dynamic_xy_step_type>::type; + using subsampled_view = detail::subsampled_view_fn; + return apply_operation(src, subsampled_view(step)); } /// \ingroup ImageViewTransformationsSubsampled -template inline // Models MPL Random Access Container of models of ImageViewConcept -typename dynamic_xy_step_type >::type subsampled_view(const any_image_view& src, int xStep, int yStep) { - return apply_operation(src,detail::subsampled_view_fn >::type>(point2(xStep,yStep))); +/// Models MPL Random Access Container of models of ImageViewConcept +template +inline auto subsampled_view(any_image_view const& src, int xStep, int yStep) + -> typename dynamic_xy_step_type>::type +{ + using step_type = typename dynamic_xy_step_type>::type; + using subsampled_view_fn = detail::subsampled_view_fn; + return apply_operation(src, subsampled_view_fn(point_t(xStep, yStep))); } namespace detail { diff --git a/include/boost/gil/extension/io/bmp/old.hpp b/include/boost/gil/extension/io/bmp/old.hpp index d783a9e2e..3a7e496c5 100644 --- a/include/boost/gil/extension/io/bmp/old.hpp +++ b/include/boost/gil/extension/io/bmp/old.hpp @@ -15,24 +15,14 @@ namespace boost { namespace gil { /// \ingroup BMP_IO /// \brief Returns the width and height of the BMP file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid BMP file -template< typename String > -inline -point2< std::ptrdiff_t > bmp_read_dimensions( const String& filename ) +template +inline point_t bmp_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , bmp_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , bmp_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, bmp_tag()); + return { backend._info._width, backend._info._height }; } - /// \ingroup BMP_IO /// \brief Loads the image specified by the given bmp image file name into the given view. /// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension. diff --git a/include/boost/gil/extension/io/jpeg/old.hpp b/include/boost/gil/extension/io/jpeg/old.hpp index 96a5b674e..5abc0af1a 100644 --- a/include/boost/gil/extension/io/jpeg/old.hpp +++ b/include/boost/gil/extension/io/jpeg/old.hpp @@ -15,24 +15,14 @@ namespace boost { namespace gil { /// \ingroup JPEG_IO /// \brief Returns the width and height of the JPEG file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file -template< typename String > -inline -point2< std::ptrdiff_t > jpeg_read_dimensions( const String& filename ) +template +inline point_t jpeg_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , jpeg_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , jpeg_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, jpeg_tag()); + return { backend._info._width, backend._info._height }; } - /// \ingroup JPEG_IO /// \brief Loads the image specified by the given jpeg image file name into the given view. /// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension. diff --git a/include/boost/gil/extension/io/png/old.hpp b/include/boost/gil/extension/io/png/old.hpp index 342472b49..f0300d25c 100644 --- a/include/boost/gil/extension/io/png/old.hpp +++ b/include/boost/gil/extension/io/png/old.hpp @@ -15,21 +15,12 @@ namespace boost { namespace gil { /// \ingroup PNG_IO /// \brief Returns the width and height of the PNG file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid PNG file -template< typename String > -inline -point2< std::ptrdiff_t > png_read_dimensions( const String& filename ) +template +inline point_t png_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , png_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , png_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, png_tag()); + return { backend._info._width, backend._info._height }; } /// \ingroup PNG_IO diff --git a/include/boost/gil/extension/io/pnm/old.hpp b/include/boost/gil/extension/io/pnm/old.hpp index d4bbfd3b8..b09e21b19 100644 --- a/include/boost/gil/extension/io/pnm/old.hpp +++ b/include/boost/gil/extension/io/pnm/old.hpp @@ -15,24 +15,14 @@ namespace boost { namespace gil { /// \ingroup PNM_IO /// \brief Returns the width and height of the PNM file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid PNM file -template< typename String > -inline -point2< std::ptrdiff_t > pnm_read_dimensions( const String& filename ) +template +inline point_t pnm_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , pnm_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , pnm_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, pnm_tag()); + return { backend._info._width, backend._info._height }; } - /// \ingroup PNM_IO /// \brief Loads the image specified by the given pnm image file name into the given view. /// Triggers a compile assert if the view color space and channel depth are not supported by the PNM library or by the I/O extension. diff --git a/include/boost/gil/extension/io/targa/old.hpp b/include/boost/gil/extension/io/targa/old.hpp index 83d3544a1..18c095f30 100644 --- a/include/boost/gil/extension/io/targa/old.hpp +++ b/include/boost/gil/extension/io/targa/old.hpp @@ -15,24 +15,14 @@ namespace boost { namespace gil { /// \ingroup BMP_IO /// \brief Returns the width and height of the BMP file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid BMP file -template< typename String > -inline -point2< std::ptrdiff_t > targa_read_dimensions( const String& filename ) +template +inline point_t targa_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , targa_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , targa_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, targa_tag()); + return { backend._info._width, backend._info._height }; } - /// \ingroup BMP_IO /// \brief Loads the image specified by the given targa image file name into the given view. /// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension. diff --git a/include/boost/gil/extension/io/tiff/old.hpp b/include/boost/gil/extension/io/tiff/old.hpp index 93bf9e3f6..cd2d97e2e 100644 --- a/include/boost/gil/extension/io/tiff/old.hpp +++ b/include/boost/gil/extension/io/tiff/old.hpp @@ -15,21 +15,12 @@ namespace boost { namespace gil { /// \ingroup TIFF_IO /// \brief Returns the width and height of the TIFF file at the specified location. /// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file -template< typename String > -inline -point2< std::ptrdiff_t > tiff_read_dimensions( const String& filename ) +template +inline point_t tiff_read_dimensions(String const& filename) { - typedef typename get_reader_backend< String - , tiff_tag - >::type backend_t; - - backend_t backend = read_image_info( filename - , tiff_tag() - ); - - return point2< std::ptrdiff_t >( backend._info._width - , backend._info._height - ); + using backend_t = typename get_reader_backend::type; + backend_t backend = read_image_info(filename, tiff_tag()); + return { backend._info._width, backend._info._height }; } /// \ingroup TIFF_IO diff --git a/include/boost/gil/extension/numeric/affine.hpp b/include/boost/gil/extension/numeric/affine.hpp index c5ebaa1d5..ebef93afc 100644 --- a/include/boost/gil/extension/numeric/affine.hpp +++ b/include/boost/gil/extension/numeric/affine.hpp @@ -8,7 +8,7 @@ #ifndef BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP #define BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP -#include // point2 +#include namespace boost { namespace gil { @@ -28,11 +28,17 @@ public: matrix3x2& operator*=(const matrix3x2& m) { (*this) = (*this)*m; return *this; } static matrix3x2 get_rotate(T rads) { T c=std::cos(rads); T s=std::sin(rads); return matrix3x2(c,s,-s,c,0,0); } - static matrix3x2 get_translate(const point2& t) { return matrix3x2(1 ,0,0,1 ,t.x,t.y); } + static matrix3x2 get_translate(point const& t) + { + return matrix3x2(1, 0, 0, 1, t.x, t.y); + } static matrix3x2 get_translate(T x, T y) { return matrix3x2(1 ,0,0,1 ,x, y ); } - static matrix3x2 get_scale (const point2& s) { return matrix3x2(s.x,0,0,s.y,0 ,0 ); } - static matrix3x2 get_scale (T x, T y) { return matrix3x2(x, 0,0,y, 0 ,0 ); } - static matrix3x2 get_scale (T s) { return matrix3x2(s ,0,0,s ,0 ,0 ); } + static matrix3x2 get_scale(point const& s) + { + return matrix3x2(s.x, 0, 0, s.y, 0, 0); + } + static matrix3x2 get_scale(T x, T y) { return matrix3x2(x, 0,0,y, 0 ,0 ); } + static matrix3x2 get_scale(T s) { return matrix3x2(s ,0,0,s ,0 ,0 ); } T a,b,c,d,e,f; }; @@ -48,9 +54,11 @@ matrix3x2 operator*(const matrix3x2& m1, const matrix3x2& m2) { m1.e * m2.b + m1.f * m2.d + m2.f ); } -template BOOST_FORCEINLINE -point2 operator*(const point2& p, const matrix3x2& m) { - return point2(m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f); +template +BOOST_FORCEINLINE +point operator*(point const& p, matrix3x2 const& m) +{ + return { m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f }; } //////////////////////////////////////////////////////////////////////////////////////// @@ -69,12 +77,17 @@ concept MappingFunctionConcept { template struct mapping_traits; template -struct mapping_traits > { - typedef point2 result_type; +struct mapping_traits> +{ + using result_type = point; }; -template BOOST_FORCEINLINE -point2 transform(const matrix3x2& mat, const point2& src) { return src * mat; } +template +BOOST_FORCEINLINE +point transform(matrix3x2 const& mat, point const& src) +{ + return src * mat; +} }} // namespace boost::gil diff --git a/include/boost/gil/extension/numeric/sampler.hpp b/include/boost/gil/extension/numeric/sampler.hpp index c4da3e320..ba8fa0522 100644 --- a/include/boost/gil/extension/numeric/sampler.hpp +++ b/include/boost/gil/extension/numeric/sampler.hpp @@ -36,9 +36,11 @@ concept SamplerConcept { struct nearest_neighbor_sampler {}; template -bool sample(nearest_neighbor_sampler, const SrcView& src, const point2& p, DstP& result) { +bool sample(nearest_neighbor_sampler, SrcView const& src, point const& p, DstP& result) +{ typename SrcView::point_t center(iround(p)); - if (center.x>=0 && center.y>=0 && center.x= 0 && center.y >= 0 && center.x < src.width() && center.y < src.height()) + { result=src(center.x,center.y); return true; } @@ -91,12 +93,11 @@ struct add_dst_mul_src { struct bilinear_sampler {}; template -bool sample(bilinear_sampler, const SrcView& src, const point2& p, DstP& result) +bool sample(bilinear_sampler, SrcView const& src, point const& p, DstP& result) { - typedef typename SrcView::value_type SrcP; - - point2 p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p - point2 frac(p.x-p0.x, p.y-p0.y); + using SrcP = typename SrcView::value_type; + point_t p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p + point frac(p.x-p0.x, p.y-p0.y); if (p0.x < -1 || p0.y < -1 || p0.x>=src.width() || p0.y>=src.height()) { diff --git a/include/boost/gil/extension/toolbox/image_types/indexed_image.hpp b/include/boost/gil/extension/toolbox/image_types/indexed_image.hpp index 01af3d7bb..4ee7966f3 100644 --- a/include/boost/gil/extension/toolbox/image_types/indexed_image.hpp +++ b/include/boost/gil/extension/toolbox/image_types/indexed_image.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -21,8 +22,6 @@ namespace boost{ namespace gil { -typedef boost::gil::point2< std::ptrdiff_t > point_t; - template< typename Locator > struct get_pixel_type_locator : mpl::if_< typename is_bit_aligned< typename Locator::value_type >::type , typename Locator::reference @@ -204,7 +203,7 @@ private: template indexed_image_view < - typename indexed_image_locator_type + typename indexed_image_locator_type < typename Index_View::locator , typename Palette_View::locator @@ -212,14 +211,14 @@ indexed_image_view > view(Index_View iv, Palette_View pv) { - typedef indexed_image_view< + typedef indexed_image_view< typename indexed_image_locator_type< typename Index_View::locator , typename Palette_View::locator >::type > view_t; - typedef indexed_image_deref_fn< + typedef indexed_image_deref_fn< typename Index_View::locator , typename Palette_View::locator > defer_fn_t; diff --git a/include/boost/gil/extension/toolbox/image_types/subchroma_image.hpp b/include/boost/gil/extension/toolbox/image_types/subchroma_image.hpp index 10a3ba09a..1d961f791 100644 --- a/include/boost/gil/extension/toolbox/image_types/subchroma_image.hpp +++ b/include/boost/gil/extension/toolbox/image_types/subchroma_image.hpp @@ -9,6 +9,7 @@ #define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP #include +#include #include #include @@ -22,8 +23,6 @@ namespace boost{ namespace gil { -typedef boost::gil::point2< std::ptrdiff_t > point_t; - //////////////////////////////////////////////////////////////////////////////////////// /// \class subchroma_image_deref_fn /// \ingroup PixelLocatorModel PixelBasedModel @@ -77,13 +76,13 @@ struct subchroma_image_deref_fn ); } - /// + /// const plane_locator_t& y_locator() const { return _y_locator; } const plane_locator_t& v_locator() const { return _v_locator; } const plane_locator_t& u_locator() const { return _u_locator; } private: - + plane_locator_t _y_locator; plane_locator_t _v_locator; plane_locator_t _u_locator; @@ -93,7 +92,7 @@ private: //////////////////////////////////////////////////////////////////////////////////////// /// \class subchroma_image_locator_type /// \ingroup PixelLocatorModel PixelBasedModel -/// \brief +/// \brief /// //////////////////////////////////////////////////////////////////////////////////////// template< typename Locator @@ -114,19 +113,19 @@ struct subchroma_image_locator ///////////////////////////// template < typename Locator, typename Factors > -struct channel_type< subchroma_image_locator< Locator, Factors > > +struct channel_type< subchroma_image_locator< Locator, Factors > > : public channel_type< typename subchroma_image_locator< Locator, Factors >::type > {}; template < typename Locator, typename Factors > -struct color_space_type< subchroma_image_locator< Locator, Factors > > +struct color_space_type< subchroma_image_locator< Locator, Factors > > : public color_space_type< typename subchroma_image_locator< Locator, Factors >::type > {}; template < typename Locator, typename Factors > -struct channel_mapping_type< subchroma_image_locator< Locator, Factors > > +struct channel_mapping_type< subchroma_image_locator< Locator, Factors > > : public channel_mapping_type< typename subchroma_image_locator< Locator, Factors >::type > {}; template < typename Locator, typename Factors > -struct is_planar< subchroma_image_locator< Locator, Factors > > +struct is_planar< subchroma_image_locator< Locator, Factors > > : public is_planar< typename subchroma_image_locator< Locator, Factors >::type > {}; ///////////////////////////// @@ -168,7 +167,7 @@ struct transposed_type< subchroma_image_locator< Locator, Factors > > /// //////////////////////////////////////////////////////////////////////////////////////// template< typename Locator - , typename Factors = mpl::vector_c< int, 4, 4, 4 > + , typename Factors = mpl::vector_c< int, 4, 4, 4 > > class subchroma_image_view : public image_view< Locator > { @@ -199,7 +198,7 @@ public: , _v_dimensions( v_dimensions ) , _u_dimensions( u_dimensions ) {} - + /// copy constructor template< typename Subchroma_View > subchroma_image_view( const Subchroma_View& v ) @@ -241,11 +240,11 @@ private: ///////////////////////////// template < typename Locator, typename Factors > -struct channel_type< subchroma_image_view< Locator, Factors > > - : public channel_type< Locator > {}; +struct channel_type< subchroma_image_view< Locator, Factors > > + : public channel_type< Locator > {}; template < typename Locator, typename Factors > -struct color_space_type< subchroma_image_view< Locator, Factors > > +struct color_space_type< subchroma_image_view< Locator, Factors > > : public color_space_type< Locator > {}; template < typename Locator, typename Factors > @@ -253,7 +252,7 @@ struct channel_mapping_type< subchroma_image_view< Locator, Factors > > : public channel_mapping_type< Locator > {}; template < typename Locator, typename Factors > -struct is_planar< subchroma_image_view< Locator, Factors > > +struct is_planar< subchroma_image_view< Locator, Factors > > : public is_planar< Locator > {}; ///////////////////////////// @@ -301,7 +300,7 @@ struct Scaling_Factors , mpl::equal_to< mpl::int_< a >, mpl::int_< 1 > > > >::type::value - )); + )); BOOST_STATIC_ASSERT(( mpl::or_< mpl::equal_to< mpl::int_< b >, mpl::int_< 4 > > , mpl::or_< mpl::equal_to< mpl::int_< b >, mpl::int_< 2 > > @@ -310,7 +309,7 @@ struct Scaling_Factors > > >::type::value - )); + )); BOOST_STATIC_CONSTANT( int, ss_X = ( mpl::divides< mpl::int_< J > , mpl::int_< a > @@ -337,7 +336,7 @@ struct Scaling_Factors /// //////////////////////////////////////////////////////////////////////////////////////// template< typename Pixel - , typename Factors = mpl::vector_c< int, 4, 4, 4 > + , typename Factors = mpl::vector_c< int, 4, 4, 4 > , typename Allocator = std::allocator< unsigned char > > class subchroma_image : public Scaling_Factors< mpl::at_c< Factors, 0 >::type::value @@ -347,7 +346,7 @@ class subchroma_image : public Scaling_Factors< mpl::at_c< Factors, 0 >::type::v { public: - + typedef typename channel_type< Pixel >::type channel_t; typedef pixel< channel_t, gray_layout_t> pixel_t; @@ -411,7 +410,7 @@ private: , locator ); } - + private: @@ -508,7 +507,7 @@ typename subchroma_image< Pixel std::size_t u_channel_size = 1; unsigned char* u_base = y_base + ( y_width * y_height * y_channel_size ); - unsigned char* v_base = u_base + ( y_width / scaling_factors_t::ss_X ) + unsigned char* v_base = u_base + ( y_width / scaling_factors_t::ss_X ) * u_channel_size; typedef subchroma_image< Pixel, Factors >::plane_view_t plane_view_t; @@ -541,7 +540,7 @@ typename subchroma_image< Pixel , v_plane.xy_at( 0, 0 ) , u_plane.xy_at( 0, 0 ) ); - + typedef subchroma_image< Pixel , Factors diff --git a/include/boost/gil/image_view_factory.hpp b/include/boost/gil/image_view_factory.hpp index 46a3da026..bfd76630f 100644 --- a/include/boost/gil/image_view_factory.hpp +++ b/include/boost/gil/image_view_factory.hpp @@ -59,10 +59,11 @@ interleaved_view(std::size_t width, std::size_t height, /// \ingroup ImageViewConstructors /// \brief Constructing image views from raw interleaved pixel data template -typename type_from_x_iterator::view_t -interleaved_view(point2 dim, - Iterator pixels, std::ptrdiff_t rowsize_in_bytes) { - typedef typename type_from_x_iterator::view_t RView; +auto interleaved_view(point dim, Iterator pixels, + std::ptrdiff_t rowsize_in_bytes) + -> typename type_from_x_iterator::view_t +{ + using RView = typename type_from_x_iterator::view_t; return RView(dim, typename RView::locator(pixels, rowsize_in_bytes)); } diff --git a/include/boost/gil/io/typedefs.hpp b/include/boost/gil/io/typedefs.hpp index 5b3c5a771..20914baf4 100644 --- a/include/boost/gil/io/typedefs.hpp +++ b/include/boost/gil/io/typedefs.hpp @@ -25,10 +25,8 @@ namespace boost { namespace gil { struct double_zero { static double apply() { return 0.0; } }; struct double_one { static double apply() { return 1.0; } }; -typedef unsigned char byte_t; -typedef std::vector< byte_t > byte_vector_t; - -typedef point2< std::ptrdiff_t > point_t; +using byte_t = unsigned char; +using byte_vector_t = std::vector; } // namespace gil } // namespace boost diff --git a/include/boost/gil/iterator_from_2d.hpp b/include/boost/gil/iterator_from_2d.hpp index a12b8923f..c75b4b2f9 100644 --- a/include/boost/gil/iterator_from_2d.hpp +++ b/include/boost/gil/iterator_from_2d.hpp @@ -121,7 +121,7 @@ private: return _coords==it._coords && _p==it._p; } - point2 _coords; + point_t _coords; std::ptrdiff_t _width; Loc2 _p; }; diff --git a/include/boost/gil/locator.hpp b/include/boost/gil/locator.hpp index 8a75c7bbb..69a623b73 100644 --- a/include/boost/gil/locator.hpp +++ b/include/boost/gil/locator.hpp @@ -23,7 +23,7 @@ template std::ptrdiff_t memunit_step(const P*); template P* memunit_advanced(const P* p, std::ptrdiff_t diff); template P& memunit_advanced_ref(P* p, std::ptrdiff_t diff); template struct iterator_add_deref; -template class point2; +template class point; namespace detail { // helper class specialized for each axis of pixel_2d_locator template class locator_axis; @@ -112,7 +112,7 @@ public: typedef typename std::iterator_traits::value_type value_type; typedef typename std::iterator_traits::reference reference; // result of dereferencing typedef typename std::iterator_traits::difference_type coord_t; // 1D difference type (same for all dimensions) - typedef point2 difference_type; // result of operator-(locator,locator) + typedef point difference_type; // result of operator-(locator,locator) typedef difference_type point_t; template struct axis { typedef typename detail::locator_axis::coord_t coord_t; diff --git a/include/boost/gil/point.hpp b/include/boost/gil/point.hpp index 9423f0030..78969d646 100644 --- a/include/boost/gil/point.hpp +++ b/include/boost/gil/point.hpp @@ -21,7 +21,7 @@ namespace boost { namespace gil { /// /// Example: /// \code -/// point2 p(3,2); +/// point p(3,2); /// assert((p[0] == p.x) && (p[1] == p.y)); /// assert(axis_value<0>(p) == 3); /// assert(axis_value<1>(p) == 2); @@ -31,7 +31,7 @@ namespace boost { namespace gil { /// \ingroup PointModel /// Models: Point2DConcept template -class point2 +class point { public: using value_type = T; @@ -44,34 +44,34 @@ public: static constexpr std::size_t num_dimensions = 2; - point2() = default; - point2(T px, T py) : x(px), y(py) {} + point() = default; + point(T px, T py) : x(px), y(py) {} - point2 operator<<(std::ptrdiff_t shift) const + point operator<<(std::ptrdiff_t shift) const { - return point2(x << shift, y << shift); + return point(x << shift, y << shift); } - point2 operator>>(std::ptrdiff_t shift) const + point operator>>(std::ptrdiff_t shift) const { - return point2(x >> shift, y >> shift); + return point(x >> shift, y >> shift); } - point2& operator+=(point2 const& p) + point& operator+=(point const& p) { x += p.x; y += p.y; return *this; } - point2& operator-=(point2 const& p) + point& operator-=(point const& p) { x -= p.x; y -= p.y; return *this; } - point2& operator/=(double t) + point& operator/=(double t) { if (t < 0 || 0 < t) { x /= t; y /= t; } return *this; @@ -93,20 +93,28 @@ public: private: // this static array of pointers to member variables makes operator[] safe // and doesn't seem to exhibit any performance penalty. - static T point2::* const mem_array[num_dimensions]; + static T point::* const mem_array[num_dimensions]; }; +/// Alias template for backward compatibility with Boost <=1.68. template -T point2::* const point2::mem_array[point2::num_dimensions] = +using point2 = point; + +/// Common type to represent 2D dimensions or in-memory size of image or view. +/// @todo TODO: rename to dims_t or dimensions_t for purpose clarity? +using point_t = point; + +template +T point::* const point::mem_array[point::num_dimensions] = { - & point2::x, - & point2::y + & point::x, + & point::y }; /// \ingroup PointModel template BOOST_FORCEINLINE -bool operator==(const point2& p1, const point2& p2) +bool operator==(const point& p1, const point& p2) { return (p1.x == p2.x && p1.y == p2.y); } @@ -114,7 +122,7 @@ bool operator==(const point2& p1, const point2& p2) /// \ingroup PointModel template BOOST_FORCEINLINE -bool operator!=(const point2& p1, const point2& p2) +bool operator!=(const point& p1, const point& p2) { return p1.x != p2.x || p1.y != p2.y; } @@ -122,104 +130,104 @@ bool operator!=(const point2& p1, const point2& p2) /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator+(const point2& p1, const point2& p2) +point operator+(const point& p1, const point& p2) { - return point2(p1.x + p2.x, p1.y + p2.y); + return point(p1.x + p2.x, p1.y + p2.y); } /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator-(const point2& p) +point operator-(const point& p) { - return point2(-p.x, -p.y); + return point(-p.x, -p.y); } /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator-(const point2& p1, const point2& p2) +point operator-(const point& p1, const point& p2) { - return point2(p1.x - p2.x, p1.y - p2.y); + return point(p1.x - p2.x, p1.y - p2.y); } /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator/(const point2& p, double t) +point operator/(const point& p, double t) { return (t < 0 || 0 < t) - ? point2(p.x / t, p.y / t) - : point2(0, 0); + ? point(p.x / t, p.y / t) + : point(0, 0); } /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator*(const point2& p, std::ptrdiff_t t) +point operator*(const point& p, std::ptrdiff_t t) { - return point2(p.x * t, p.y * t); + return point(p.x * t, p.y * t); } /// \ingroup PointModel template BOOST_FORCEINLINE -point2 operator*(std::ptrdiff_t t, const point2& p) +point operator*(std::ptrdiff_t t, const point& p) { - return point2(p.x * t, p.y * t); + return point(p.x * t, p.y * t); } /// \ingroup PointModel template BOOST_FORCEINLINE -T const& axis_value(const point2& p) { return p[K]; } +T const& axis_value(const point& p) { return p[K]; } /// \ingroup PointModel template BOOST_FORCEINLINE -T& axis_value(point2& p) { return p[K]; } +T& axis_value(point& p) { return p[K]; } /// \addtogroup PointAlgorithm /// /// Example: /// \code -/// assert(iround(point2(3.1, 3.9)) == point2(3,4)); +/// assert(iround(point(3.1, 3.9)) == point(3,4)); /// \endcode /// \ingroup PointAlgorithm -inline point2 iround(const point2& p) +inline point iround(const point& p) { - return point2(iround(p.x), iround(p.y)); + return point(iround(p.x), iround(p.y)); } /// \ingroup PointAlgorithm -inline point2 iround(const point2& p) +inline point iround(const point& p) { - return point2(iround(p.x), iround(p.y)); + return point(iround(p.x), iround(p.y)); } /// \ingroup PointAlgorithm -inline point2 ifloor(const point2& p) +inline point ifloor(const point& p) { - return point2(ifloor(p.x), ifloor(p.y)); + return point(ifloor(p.x), ifloor(p.y)); } /// \ingroup PointAlgorithm -inline point2 ifloor(const point2& p) +inline point ifloor(const point& p) { - return point2(ifloor(p.x), ifloor(p.y)); + return point(ifloor(p.x), ifloor(p.y)); } /// \ingroup PointAlgorithm -inline point2 iceil(const point2& p) +inline point iceil(const point& p) { - return point2(iceil(p.x), iceil(p.y)); + return point(iceil(p.x), iceil(p.y)); } /// \ingroup PointAlgorithm -inline point2 iceil(const point2& p) +inline point iceil(const point& p) { - return point2(iceil(p.x), iceil(p.y)); + return point(iceil(p.x), iceil(p.y)); } }} // namespace boost::gil diff --git a/include/boost/gil/typedefs.hpp b/include/boost/gil/typedefs.hpp index fa0f7cc34..d1f5170af 100644 --- a/include/boost/gil/typedefs.hpp +++ b/include/boost/gil/typedefs.hpp @@ -26,7 +26,7 @@ template struct planar_pixel_reference; \ template struct planar_pixel_iterator; \ template class memory_based_step_iterator; \ - template class point2; \ + template class point; \ template class memory_based_2d_locator; \ template class image_view; \ template class image; \ diff --git a/io/test/bmp_old_test.cpp b/io/test/bmp_old_test.cpp index db7e97dad..3b4887e4a 100644 --- a/io/test/bmp_old_test.cpp +++ b/io/test/bmp_old_test.cpp @@ -24,8 +24,7 @@ BOOST_AUTO_TEST_SUITE( gil_io_bmp_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - point2< std::ptrdiff_t > dim = bmp_read_dimensions( bmp_filename ); - + boost::gil::point_t dim = bmp_read_dimensions(bmp_filename); BOOST_CHECK_EQUAL( dim.x, 1000 ); BOOST_CHECK_EQUAL( dim.y, 600 ); } diff --git a/io/test/jpeg_old_test.cpp b/io/test/jpeg_old_test.cpp index c52c48145..95dfba9f2 100644 --- a/io/test/jpeg_old_test.cpp +++ b/io/test/jpeg_old_test.cpp @@ -24,8 +24,7 @@ BOOST_AUTO_TEST_SUITE( gil_io_jpeg_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - point2< std::ptrdiff_t > dim = jpeg_read_dimensions( jpeg_filename ); - + boost::gil::point_t dim = jpeg_read_dimensions(jpeg_filename); BOOST_CHECK_EQUAL( dim.x, 1000 ); BOOST_CHECK_EQUAL( dim.y, 600 ); } diff --git a/io/test/mandel_view.hpp b/io/test/mandel_view.hpp index cc2135f89..c9c604846 100644 --- a/io/test/mandel_view.hpp +++ b/io/test/mandel_view.hpp @@ -17,8 +17,7 @@ using namespace gil; // Models a Unary Function template // Models PixelValueConcept struct mandelbrot_fn { - typedef point2 point_t; - + using point_t = boost::gil::point_t; typedef mandelbrot_fn const_t; typedef P value_type; typedef value_type reference; @@ -40,7 +39,7 @@ struct mandelbrot_fn { result_type operator()(const point_t& p) const { // normalize the coords to (-2..1, -1.5..1.5) // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods) - double t=get_num_iter(point2(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); + double t=get_num_iter(point(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); t=pow(t,0.2); value_type ret; @@ -50,10 +49,10 @@ struct mandelbrot_fn { } private: - double get_num_iter(const point2& p) const { - point2 Z(0,0); + double get_num_iter(const point& p) const { + point Z(0,0); for (int i=0; i(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); + Z = point(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); if (Z.x*Z.x + Z.y*Z.y > 4) return i/(double)MAX_ITER; } diff --git a/io/test/png_old_test.cpp b/io/test/png_old_test.cpp index 24db9e42c..a4ec8b670 100644 --- a/io/test/png_old_test.cpp +++ b/io/test/png_old_test.cpp @@ -24,8 +24,7 @@ BOOST_AUTO_TEST_SUITE( gil_io_png_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - point2< std::ptrdiff_t > dim = png_read_dimensions( png_filename ); - + boost::gil::point_t dim = png_read_dimensions(png_filename); BOOST_CHECK_EQUAL( dim.x, 1000 ); BOOST_CHECK_EQUAL( dim.y, 600 ); } diff --git a/io/test/pnm_old_test.cpp b/io/test/pnm_old_test.cpp index 4d16c301d..821eff870 100644 --- a/io/test/pnm_old_test.cpp +++ b/io/test/pnm_old_test.cpp @@ -23,12 +23,9 @@ BOOST_AUTO_TEST_SUITE( gil_io_pnm_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - { - point2< std::ptrdiff_t > dim = pnm_read_dimensions( pnm_filename ); - - BOOST_CHECK_EQUAL( dim.x, 256 ); - BOOST_CHECK_EQUAL( dim.y, 256 ); - } + boost::gil::point_t dim = pnm_read_dimensions(pnm_filename); + BOOST_CHECK_EQUAL( dim.x, 256 ); + BOOST_CHECK_EQUAL( dim.y, 256 ); } BOOST_AUTO_TEST_CASE( old_read_image_test ) diff --git a/io/test/targa_old_test.cpp b/io/test/targa_old_test.cpp index 214ab9b18..0486ffead 100644 --- a/io/test/targa_old_test.cpp +++ b/io/test/targa_old_test.cpp @@ -25,8 +25,7 @@ BOOST_AUTO_TEST_SUITE( gil_io_targa_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - point2< std::ptrdiff_t > dim = targa_read_dimensions( targa_filename ); - + boost::gil::point_t dim = targa_read_dimensions(targa_filename); BOOST_CHECK_EQUAL( dim.x, 124 ); BOOST_CHECK_EQUAL( dim.y, 124 ); } diff --git a/io/test/tiff_old_test.cpp b/io/test/tiff_old_test.cpp index 8ef1b81ad..226f099b0 100644 --- a/io/test/tiff_old_test.cpp +++ b/io/test/tiff_old_test.cpp @@ -27,8 +27,7 @@ BOOST_AUTO_TEST_SUITE( gil_io_tiff_tests ) BOOST_AUTO_TEST_CASE( old_read_dimensions_test ) { - point2< std::ptrdiff_t > dim = tiff_read_dimensions( tiff_filename ); - + boost::gil::point_t dim = tiff_read_dimensions(tiff_filename); BOOST_CHECK_EQUAL( dim.x, 1000 ); BOOST_CHECK_EQUAL( dim.y, 600 ); } diff --git a/numeric/test/numeric.cpp b/numeric/test/numeric.cpp index 99cb1d9fb..e42667f33 100644 --- a/numeric/test/numeric.cpp +++ b/numeric/test/numeric.cpp @@ -22,14 +22,13 @@ using namespace gil; template < class F, class I > struct TestMapFn { - typedef point2 point_t; - typedef point_t result_type; - result_type operator()( point2 const& src ) const + using point_t = point; + using result_type = point_t; + result_type operator()(point const& src) const { F x = static_cast( src.x ) - 0.5; F y = static_cast( src.y ) - 0.5; - - return point_t( x, y ); + return { x, y }; } }; @@ -44,9 +43,8 @@ struct mapping_traits< TestMapFn > { typedef typename TestMapFn::result_type result_type; }; -template < class F, class I > -inline -point2 transform( TestMapFn const& mf, point2 const& src ) +template +inline point transform(TestMapFn const& mf, point const& src) { return mf(src); } diff --git a/test/image.cpp b/test/image.cpp index 0fc126e97..e7b9b513f 100644 --- a/test/image.cpp +++ b/test/image.cpp @@ -84,8 +84,7 @@ struct my_color_converter { // Models a Unary Function template // Models PixelValueConcept struct mandelbrot_fn { - typedef point2 point_t; - + using point_t = boost::gil::point_t; typedef mandelbrot_fn const_t; typedef P value_type; typedef value_type reference; @@ -104,7 +103,7 @@ struct mandelbrot_fn { result_type operator()(const point_t& p) const { // normalize the coords to (-2..1, -1.5..1.5) // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods) - double t=get_num_iter(point2(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); + double t=get_num_iter(point(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f)); t=pow(t,0.2); value_type ret; @@ -114,10 +113,10 @@ struct mandelbrot_fn { } private: - double get_num_iter(const point2& p) const { - point2 Z(0,0); + double get_num_iter(const point& p) const { + point Z(0,0); for (int i=0; i(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); + Z = point(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y); if (Z.x*Z.x + Z.y*Z.y > 4) return i/(double)MAX_ITER; } @@ -352,7 +351,7 @@ void image_test::run() { image_all_test("bgr121_"); // TODO: Remove? - view_transformations_test(subsampled_view(sample_view,point2(1,2)),"subsampled_"); + view_transformations_test(subsampled_view(sample_view, point_t(1,2)), "subsampled_"); view_transformations_test(color_converted_view(sample_view),"color_converted_"); virtual_view_test(); diff --git a/test/pixel_iterator.cpp b/test/pixel_iterator.cpp index 5c47da998..f24505176 100644 --- a/test/pixel_iterator.cpp +++ b/test/pixel_iterator.cpp @@ -19,7 +19,7 @@ using namespace std; void test_pixel_iterator() { - boost::function_requires > >(); + boost::function_requires>>(); boost::function_requires >(); boost::function_requires >(); @@ -249,7 +249,7 @@ void test_pixel_iterator() { xy_locator.x()++; // memory_based_step_iterator& yit=xy_locator.y(); xy_locator.y()++; - xy_locator+=point2(3,4); + xy_locator+=point(3,4); // *xy_locator=(xy_locator(-1,0)+xy_locator(0,1))/2; rgb8_pixel_t& rf=*xy_locator; ignore_unused_variable_warning(rf); diff --git a/test/recreate_image.cpp b/test/recreate_image.cpp index a3af12187..7ac17d543 100644 --- a/test/recreate_image.cpp +++ b/test/recreate_image.cpp @@ -86,8 +86,8 @@ BOOST_AUTO_TEST_SUITE(GIL_Tests) BOOST_AUTO_TEST_CASE(recreate_image_test) { - auto tasib_1 = total_allocated_size_in_bytes< rgb8_view_t, false >( point2< rgb8_view_t::coord_t >( 640, 480 ) ); - auto tasib_2 = total_allocated_size_in_bytes< rgb8_view_t, false >( point2< rgb8_view_t::coord_t >( 320, 200 ) ); + auto tasib_1 = total_allocated_size_in_bytes({640, 480}); + auto tasib_2 = total_allocated_size_in_bytes({320, 200}); rgb8_image_t img( 640, 480 ); img.recreate( 320, 200 );