€cdocutils.nodes document q)q}q(U nametypesq}q(Xusing image viewsqNX histogramqNXexamplesqNXpixel-level operationsq NUcontentsq NXresizing image canvasq NuUsubstitution_defsq }q Uparse_messagesq]qUcurrent_sourceqNU decorationqNUautofootnote_startqKUnameidsq}q(hUusing-image-viewsqhU histogramqhUexamplesqh Upixel-level-operationsqh Ucontentsqh Uresizing-image-canvasquUchildrenq]qcdocutils.nodes section q)q}q(U rawsourceq UUparentq!hUsourceq"X./root/project/libs/gil/doc/design/examples.rstq#Utagnameq$Usectionq%U attributesq&}q'(Udupnamesq(]Uclassesq)]Ubackrefsq*]Uidsq+]q,haUnamesq-]q.hauUlineq/KUdocumentq0hh]q1(cdocutils.nodes title q2)q3}q4(h XExamplesq5h!hh"h#h$Utitleq6h&}q7(h(]h)]h*]h+]h-]uh/Kh0hh]q8cdocutils.nodes Text q9XExamplesq:…q;}q<(h h5h!h3ubaubcdocutils.nodes topic q=)q>}q?(h Uh!hh"h#h$Utopicq@h&}qA(h(]h)]qB(UcontentsqCUlocalqDeh*]h+]qEhah-]qFh auh/Kh0hh]qGcdocutils.nodes bullet_list qH)qI}qJ(h Uh!h>h"Nh$U bullet_listqKh&}qL(h(]h)]h*]h+]h-]uh/Nh0hh]qM(cdocutils.nodes list_item qN)qO}qP(h Uh&}qQ(h(]h)]h*]h+]h-]uh!hIh]qRcdocutils.nodes paragraph qS)qT}qU(h Uh&}qV(h(]h)]h*]h+]h-]uh!hOh]qWcdocutils.nodes reference qX)qY}qZ(h Uh&}q[(h+]q\Uid1q]ah*]h(]h)]h-]Urefidhuh!hTh]q^h9XPixel-level Operationsq_…q`}qa(h XPixel-level Operationsqbh!hYubah$U referenceqcubah$U paragraphqdubah$U list_itemqeubhN)qf}qg(h Uh&}qh(h(]h)]h*]h+]h-]uh!hIh]qihS)qj}qk(h Uh&}ql(h(]h)]h*]h+]h-]uh!hfh]qmhX)qn}qo(h Uh&}qp(h+]qqUid2qrah*]h(]h)]h-]Urefidhuh!hjh]qsh9XResizing image canvasqt…qu}qv(h XResizing image canvasqwh!hnubah$hcubah$hdubah$heubhN)qx}qy(h Uh&}qz(h(]h)]h*]h+]h-]uh!hIh]q{hS)q|}q}(h Uh&}q~(h(]h)]h*]h+]h-]uh!hxh]qhX)q€}q(h Uh&}q‚(h+]qƒUid3q„ah*]h(]h)]h-]Urefidhuh!h|h]q…h9X Histogramq†…q‡}qˆ(h X Histogramq‰h!h€ubah$hcubah$hdubah$heubhN)qŠ}q‹(h Uh&}qŒ(h(]h)]h*]h+]h-]uh!hIh]qhS)qŽ}q(h Uh&}q(h(]h)]h*]h+]h-]uh!hŠh]q‘hX)q’}q“(h Uh&}q”(h+]q•Uid4q–ah*]h(]h)]h-]Urefidhuh!hŽh]q—h9XUsing image viewsq˜…q™}qš(h XUsing image viewsq›h!h’ubah$hcubah$hdubah$heubeubaubh)qœ}q(h Uh!hh"h#h$h%h&}qž(h(]h)]h*]h+]qŸhah-]q h auh/K h0hh]q¡(h2)q¢}q£(h hbh!hœh"h#h$h6h&}q¤(h+]h*]h(]h)]h-]Urefidq¥h]uh/K h0hh]q¦h9XPixel-level Operationsq§…q¨}q©(h hbh!h¢ubaubhS)qª}q«(h X[Here are some operations you can do with pixel values, pixel pointers and pixel references:q¬h!hœh"h#h$hdh&}q­(h(]h)]h*]h+]h-]uh/K h0hh]q®h9X[Here are some operations you can do with pixel values, pixel pointers and pixel references:q¯…q°}q±(h h¬h!hªubaubcdocutils.nodes literal_block q²)q³}q´(h X(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. 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 get_color(p1,green_t()) = get_color(p2,blue_t()); // channels can also be accessed by name const unsigned char* r; const unsigned char* g; const unsigned char* b; rgb8c_planar_ptr_t ptr(r,g,b); // constructing const planar pointer from const pointers to each plane rgb8c_planar_ref_t ref=*ptr; // just like built-in reference, dereferencing a planar pointer returns a planar reference p2=ref; p2=p1; p2=ptr[7]; p2=rgb8_pixel_t(1,2,3); // planar/interleaved references and values to RGB/BGR can be freely mixed //rgb8_planar_ref_t ref2; // compile error: References have no default constructors //ref2=*ptr; // compile error: Cannot construct non-const reference by dereferencing const pointer //ptr[3]=p1; // compile error: Cannot set the fourth pixel through a const pointer //p1 = pixel();// compile error: Incompatible channel depth //p1 = pixel();// compile error: Incompatible color space (even though it has the same number of channels) //p1 = pixel();// compile error: Incompatible color space (even though it contains red, green and blue channels)h!hœh"h#h$U literal_blockqµh&}q¶(Ulinenosq·‰Ulanguageq¸XcppU xml:spaceq¹Upreserveqºh+]h*]h(]Uhighlight_argsq»}h)]h-]uh/Kh0hh]q¼h9X(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. 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 get_color(p1,green_t()) = get_color(p2,blue_t()); // channels can also be accessed by name const unsigned char* r; const unsigned char* g; const unsigned char* b; rgb8c_planar_ptr_t ptr(r,g,b); // constructing const planar pointer from const pointers to each plane rgb8c_planar_ref_t ref=*ptr; // just like built-in reference, dereferencing a planar pointer returns a planar reference p2=ref; p2=p1; p2=ptr[7]; p2=rgb8_pixel_t(1,2,3); // planar/interleaved references and values to RGB/BGR can be freely mixed //rgb8_planar_ref_t ref2; // compile error: References have no default constructors //ref2=*ptr; // compile error: Cannot construct non-const reference by dereferencing const pointer //ptr[3]=p1; // compile error: Cannot set the fourth pixel through a const pointer //p1 = pixel();// compile error: Incompatible channel depth //p1 = pixel();// compile error: Incompatible color space (even though it has the same number of channels) //p1 = pixel();// compile error: Incompatible color space (even though it contains red, green and blue channels)q½…q¾}q¿(h Uh!h³ubaubhS)qÀ}qÁ(h X*Here is how to use pixels in generic code:qÂh!hœh"h#h$hdh&}qÃ(h(]h)]h*]h+]h-]uh/K'h0hh]qÄh9X*Here is how to use pixels in generic code:qÅ…qÆ}qÇ(h hÂh!hÀubaubh²)qÈ}qÉ(h XHtemplate void gray_to_rgb(const GrayPixel& src, RGBPixel& dst) { gil_function_requires >(); gil_function_requires >(); typedef typename color_space_type::type gray_cs_t; static_assert(boost::is_same::value, ""); typedef typename color_space_type::type rgb_cs_t; static_assert(boost::is_same::value, ""); typedef typename channel_type::type gray_channel_t; typedef typename channel_type::type rgb_channel_t; gray_channel_t gray = get_color(src,gray_color_t()); static_fill(dst, channel_convert(gray)); } // example use patterns: // converting gray l-value to RGB and storing at (5,5) in a 16-bit BGR interleaved image: bgr16_view_t b16(...); gray_to_rgb(gray8_pixel_t(33), b16(5,5)); // storing the first pixel of an 8-bit grayscale image as the 5-th pixel of 32-bit planar RGB image: rgb32f_planar_view_t rpv32; gray8_view_t gv8(...); gray_to_rgb(*gv8.begin(), rpv32[5]);h!hœh"h#h$hµh&}qÊ(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K)h0hh]qËh9XHtemplate void gray_to_rgb(const GrayPixel& src, RGBPixel& dst) { gil_function_requires >(); gil_function_requires >(); typedef typename color_space_type::type gray_cs_t; static_assert(boost::is_same::value, ""); typedef typename color_space_type::type rgb_cs_t; static_assert(boost::is_same::value, ""); typedef typename channel_type::type gray_channel_t; typedef typename channel_type::type rgb_channel_t; gray_channel_t gray = get_color(src,gray_color_t()); static_fill(dst, channel_convert(gray)); } // example use patterns: // converting gray l-value to RGB and storing at (5,5) in a 16-bit BGR interleaved image: bgr16_view_t b16(...); gray_to_rgb(gray8_pixel_t(33), b16(5,5)); // storing the first pixel of an 8-bit grayscale image as the 5-th pixel of 32-bit planar RGB image: rgb32f_planar_view_t rpv32; gray8_view_t gv8(...); gray_to_rgb(*gv8.begin(), rpv32[5]);qÌ…qÍ}qÎ(h Uh!hÈubaubhS)qÏ}qÐ(h X¾As the example shows, both the source and the destination can be references or values, planar or interleaved, as long as they model ``PixelConcept`` and ``MutablePixelConcept`` respectively.h!hœh"h#h$hdh&}qÑ(h(]h)]h*]h+]h-]uh/KIh0hh]qÒ(h9X„As the example shows, both the source and the destination can be references or values, planar or interleaved, as long as they model qÓ…qÔ}qÕ(h X„As the example shows, both the source and the destination can be references or values, planar or interleaved, as long as they model h!hÏubcdocutils.nodes literal qÖ)q×}qØ(h X``PixelConcept``h&}qÙ(h(]h)]h*]h+]h-]uh!hÏh]qÚh9X PixelConceptqÛ…qÜ}qÝ(h Uh!h×ubah$UliteralqÞubh9X and qß…qà}qá(h X and h!hÏubhÖ)qâ}qã(h X``MutablePixelConcept``h&}qä(h(]h)]h*]h+]h-]uh!hÏh]qåh9XMutablePixelConceptqæ…qç}qè(h Uh!hâubah$hÞubh9X respectively.qé…qê}që(h X respectively.h!hÏubeubeubh)qì}qí(h Uh!hh"h#h$h%h&}qî(h(]h)]h*]h+]qïhah-]qðh auh/KOh0hh]qñ(h2)qò}qó(h hwh!hìh"h#h$h6h&}qô(h+]h*]h(]h)]h-]h¥hruh/KOh0hh]qõh9XResizing image canvasqö…q÷}qø(h hwh!hòubaubhS)qù}qú(h X—Resizing an image canvas means adding a buffer of pixels around existing pixels. Size of canvas of an image can never be smaller than the image itself.qûh!hìh"h#h$hdh&}qü(h(]h)]h*]h+]h-]uh/KQh0hh]qýh9X—Resizing an image canvas means adding a buffer of pixels around existing pixels. Size of canvas of an image can never be smaller than the image itself.qþ…qÿ}r(h hûh!hùubaubhS)r}r(h XÅ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:rh!hìh"h#h$hdh&}r(h(]h)]h*]h+]h-]uh/KTh0hh]rh9XÅ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:r…r}r(h jh!jubaubh²)r }r (h Xrtemplate // Models ImageConcept (the returned image) 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()); }h!hìh"h#h$hµh&}r (h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/KXh0hh]r h9Xrtemplate // Models ImageConcept (the returned image) 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()); }r …r}r(h Uh!j ubaubhS)r}r(h XsWe allocated a larger image, then we used ``subimage_view`` to create a shallow image of its center area of top left corner at (k,k) and of identical size as ``src``, and finally we copied ``src`` into that center image. If the margin needs initialization, we could have done it with ``fill_pixels``. Here is how to simplify this code using the ``copy_pixels`` algorithm:h!hìh"h#h$hdh&}r(h(]h)]h*]h+]h-]uh/Kgh0hh]r(h9X*We allocated a larger image, then we used r…r}r(h X*We allocated a larger image, then we used h!jubhÖ)r}r(h X``subimage_view``h&}r(h(]h)]h*]h+]h-]uh!jh]rh9X subimage_viewr…r}r(h Uh!jubah$hÞubh9Xc to create a shallow image of its center area of top left corner at (k,k) and of identical size as r…r}r (h Xc to create a shallow image of its center area of top left corner at (k,k) and of identical size as h!jubhÖ)r!}r"(h X``src``h&}r#(h(]h)]h*]h+]h-]uh!jh]r$h9Xsrcr%…r&}r'(h Uh!j!ubah$hÞubh9X, and finally we copied r(…r)}r*(h X, and finally we copied h!jubhÖ)r+}r,(h X``src``h&}r-(h(]h)]h*]h+]h-]uh!jh]r.h9Xsrcr/…r0}r1(h Uh!j+ubah$hÞubh9XX into that center image. If the margin needs initialization, we could have done it with r2…r3}r4(h XX into that center image. If the margin needs initialization, we could have done it with h!jubhÖ)r5}r6(h X``fill_pixels``h&}r7(h(]h)]h*]h+]h-]uh!jh]r8h9X fill_pixelsr9…r:}r;(h Uh!j5ubah$hÞubh9X.. Here is how to simplify this code using the r<…r=}r>(h X.. Here is how to simplify this code using the h!jubhÖ)r?}r@(h X``copy_pixels``h&}rA(h(]h)]h*]h+]h-]uh!jh]rBh9X copy_pixelsrC…rD}rE(h Uh!j?ubah$hÞubh9X algorithm:rF…rG}rH(h X algorithm:h!jubeubh²)rI}rJ(h Xütemplate void create_with_margin(const SrcView& src, int k, DstImage& result) { result.recreate(src.width()+2*k, src.height()+2*k); copy_pixels(src, subimage_view(view(result), k,k,src.width(),src.height())); }h!hìh"h#h$hµh&}rK(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/Kmh0hh]rLh9Xütemplate void create_with_margin(const SrcView& src, int k, DstImage& result) { result.recreate(src.width()+2*k, src.height()+2*k); copy_pixels(src, subimage_view(view(result), k,k,src.width(),src.height())); }rM…rN}rO(h Uh!jIubaubhS)rP}rQ(h X)(Note also that ``image::recreate`` is more efficient than ``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 ``std::copy`` - when called on two identical interleaved images with no padding at the end of rows, it simply does a ``memmove``. For planar images it does ``memmove`` for each channel. If one of the images has padding, (as in our case) it will try to do ``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.h!hìh"h#h$hdh&}rR(h(]h)]h*]h+]h-]uh/Kvh0hh]rS(h9X(Note also that rT…rU}rV(h X(Note also that h!jPubhÖ)rW}rX(h X``image::recreate``h&}rY(h(]h)]h*]h+]h-]uh!jPh]rZh9Ximage::recreater[…r\}r](h Uh!jWubah$hÞubh9X is more efficient than r^…r_}r`(h X is more efficient than h!jPubhÖ)ra}rb(h X ``operator=``h&}rc(h(]h)]h*]h+]h-]uh!jPh]rdh9X operator=re…rf}rg(h Uh!jaubah$hÞubh9XÊ, 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 rh…ri}rj(h XÊ, 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 h!jPubhÖ)rk}rl(h X ``std::copy``h&}rm(h(]h)]h*]h+]h-]uh!jPh]rnh9X std::copyro…rp}rq(h Uh!jkubah$hÞubh9Xh - when called on two identical interleaved images with no padding at the end of rows, it simply does a rr…rs}rt(h Xh - when called on two identical interleaved images with no padding at the end of rows, it simply does a h!jPubhÖ)ru}rv(h X ``memmove``h&}rw(h(]h)]h*]h+]h-]uh!jPh]rxh9Xmemmovery…rz}r{(h Uh!juubah$hÞubh9X. For planar images it does r|…r}}r~(h X. For planar images it does h!jPubhÖ)r}r€(h X ``memmove``h&}r(h(]h)]h*]h+]h-]uh!jPh]r‚h9Xmemmoverƒ…r„}r…(h Uh!jubah$hÞubh9XX for each channel. If one of the images has padding, (as in our case) it will try to do r†…r‡}rˆ(h XX for each channel. If one of the images has padding, (as in our case) it will try to do h!jPubhÖ)r‰}rŠ(h X ``memmove``h&}r‹(h(]h)]h*]h+]h-]uh!jPh]rŒh9Xmemmover…rŽ}r(h Uh!j‰ubah$hÞubh9X  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.r…r‘}r’(h X  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.h!jPubeubeubh)r“}r”(h Uh!hh"h#h$h%h&}r•(h(]h)]h*]h+]r–hah-]r—hauh/Kƒh0hh]r˜(h2)r™}rš(h h‰h!j“h"h#h$h6h&}r›(h+]h*]h(]h)]h-]h¥h„uh/Kƒh0hh]rœh9X Histogramr…rž}rŸ(h h‰h!j™ubaubhS)r }r¡(h XÙ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:r¢h!j“h"h#h$hdh&}r£(h(]h)]h*]h+]h-]uh/K…h0hh]r¤h9XÙ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:r¥…r¦}r§(h j¢h!j ubaubh²)r¨}r©(h X¾template void grayimage_histogram(const GrayView& img, R& hist) { for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it) ++hist[*it]; }h!j“h"h#h$hµh&}rª(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K‰h0hh]r«h9X¾template void grayimage_histogram(const GrayView& img, R& hist) { for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it) ++hist[*it]; }r¬…r­}r®(h Uh!j¨ubaubhS)r¯}r°(h XaUsing ``boost::lambda`` and GIL's ``for_each_pixel`` algorithm, we can write this more compactly:h!j“h"h#h$hdh&}r±(h(]h)]h*]h+]h-]uh/K’h0hh]r²(h9XUsing r³…r´}rµ(h XUsing h!j¯ubhÖ)r¶}r·(h X``boost::lambda``h&}r¸(h(]h)]h*]h+]h-]uh!j¯h]r¹h9X boost::lambdarº…r»}r¼(h Uh!j¶ubah$hÞubh9X and GIL's r½…r¾}r¿(h X and GIL's h!j¯ubhÖ)rÀ}rÁ(h X``for_each_pixel``h&}rÂ(h(]h)]h*]h+]h-]uh!j¯h]rÃh9Xfor_each_pixelrÄ…rÅ}rÆ(h Uh!jÀubah$hÞubh9X- algorithm, we can write this more compactly:rÇ…rÈ}rÉ(h X- algorithm, we can write this more compactly:h!j¯ubeubh²)rÊ}rË(h X‡template void grayimage_histogram(const GrayView& v, R& hist) { for_each_pixel(v, ++var(hist)[_1]); }h!j“h"h#h$hµh&}rÌ(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K•h0hh]rÍh9X‡template void grayimage_histogram(const GrayView& v, R& hist) { for_each_pixel(v, ++var(hist)[_1]); }rÎ…rÏ}rÐ(h Uh!jÊubaubhS)rÑ}rÒ(h XÏWhere ``for_each_pixel`` invokes ``std::for_each`` and ``var`` and ``_1`` are ``boost::lambda`` constructs. To compute the luminosity histogram, we call the above method using the grayscale view of an image:h!j“h"h#h$hdh&}rÓ(h(]h)]h*]h+]h-]uh/Kh0hh]rÔ(h9XWhere rÕ…rÖ}r×(h XWhere h!jÑubhÖ)rØ}rÙ(h X``for_each_pixel``h&}rÚ(h(]h)]h*]h+]h-]uh!jÑh]rÛh9Xfor_each_pixelrÜ…rÝ}rÞ(h Uh!jØubah$hÞubh9X invokes rß…rà}rá(h X invokes h!jÑubhÖ)râ}rã(h X``std::for_each``h&}rä(h(]h)]h*]h+]h-]uh!jÑh]råh9X std::for_eachræ…rç}rè(h Uh!jâubah$hÞubh9X and ré…rê}rë(h X and h!jÑubhÖ)rì}rí(h X``var``h&}rî(h(]h)]h*]h+]h-]uh!jÑh]rïh9Xvarrð…rñ}rò(h Uh!jìubah$hÞubh9X and ró…rô}rõ(h X and h!jÑubhÖ)rö}r÷(h X``_1``h&}rø(h(]h)]h*]h+]h-]uh!jÑh]rùh9X_1rú…rû}rü(h Uh!jöubah$hÞubh9X are rý…rþ}rÿ(h X are h!jÑubhÖ)r}r(h X``boost::lambda``h&}r(h(]h)]h*]h+]h-]uh!jÑh]rh9X boost::lambdar…r}r(h Uh!jubah$hÞubh9Xp constructs. To compute the luminosity histogram, we call the above method using the grayscale view of an image:r…r}r (h Xp constructs. To compute the luminosity histogram, we call the above method using the grayscale view of an image:h!jÑubeubh²)r }r (h Xžtemplate void luminosity_histogram(const View& v, R& hist) { grayimage_histogram(color_converted_view(v),hist); }h!j“h"h#h$hµh&}r (h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K¡h0hh]r h9Xžtemplate void luminosity_histogram(const View& v, R& hist) { grayimage_histogram(color_converted_view(v),hist); }r…r}r(h Uh!j ubaubhS)r}r(h XThis is how to invoke it:rh!j“h"h#h$hdh&}r(h(]h)]h*]h+]h-]uh/K©h0hh]rh9XThis is how to invoke it:r…r}r(h jh!jubaubh²)r}r(h XXunsigned char hist[256]; std::fill(hist,hist+256,0); luminosity_histogram(my_view,hist);h!j“h"h#h$hµh&}r(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K«h0hh]rh9XXunsigned char hist[256]; std::fill(hist,hist+256,0); luminosity_histogram(my_view,hist);r…r}r(h Uh!jubaubhS)r }r!(h XjIf we want to view the histogram of the second channel of the image in the top left 100x100 area, we call:r"h!j“h"h#h$hdh&}r#(h(]h)]h*]h+]h-]uh/K±h0hh]r$h9XjIf we want to view the histogram of the second channel of the image in the top left 100x100 area, we call:r%…r&}r'(h j"h!j ubaubh²)r(}r)(h XMgrayimage_histogram(nth_channel_view(subimage_view(img,0,0,100,100),1),hist);h!j“h"h#h$hµh&}r*(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/K´h0hh]r+h9XMgrayimage_histogram(nth_channel_view(subimage_view(img,0,0,100,100),1),hist);r,…r-}r.(h Uh!j(ubaubhS)r/}r0(h XÓNo pixels are copied and no extra memory is allocated - the code operates directly on the source pixels, which could be in any supported color space and channel depth. They could be either planar or interleaved.r1h!j“h"h#h$hdh&}r2(h(]h)]h*]h+]h-]uh/K¸h0hh]r3h9XÓNo pixels are copied and no extra memory is allocated - the code operates directly on the source pixels, which could be in any supported color space and channel depth. They could be either planar or interleaved.r4…r5}r6(h j1h!j/ubaubeubh)r7}r8(h Uh!hh"h#h$h%h&}r9(h(]h)]h*]h+]r:hah-]r;hauh/K½h0hh]r<(h2)r=}r>(h h›h!j7h"h#h$h6h&}r?(h+]h*]h(]h)]h-]h¥h–uh/K½h0hh]r@h9XUsing image viewsrA…rB}rC(h h›h!j=ubaubhS)rD}rE(h X>The following code illustrates the power of using image views:rFh!j7h"h#h$hdh&}rG(h(]h)]h*]h+]h-]uh/K¿h0hh]rHh9X>The following code illustrates the power of using image views:rI…rJ}rK(h jFh!jDubaubh²)rL}rM(h Xjpeg_read_image("monkey.jpg", img); step1=view(img); step2=subimage_view(step1, 200,300, 150,150); step3=color_converted_view(step2); step4=rotated180_view(step3); step5=subsampled_view(step4, 2,1); jpeg_write_view("monkey_transform.jpg", step5);h!j7h"h#h$hµh&}rN(h·‰h¸Xcpph¹hºh+]h*]h(]h»}h)]h-]uh/KÁh0hh]rOh9Xjpeg_read_image("monkey.jpg", img); step1=view(img); step2=subimage_view(step1, 200,300, 150,150); step3=color_converted_view(step2); step4=rotated180_view(step3); step5=subsampled_view(step4, 2,1); jpeg_write_view("monkey_transform.jpg", step5);rP…rQ}rR(h Uh!jLubaubhS)rS}rT(h X'The intermediate images are shown here:rUh!j7h"h#h$hdh&}rV(h(]h)]h*]h+]h-]uh/KËh0hh]rWh9X'The intermediate images are shown here:rX…rY}rZ(h jUh!jSubaubcdocutils.nodes image r[)r\}r](h X&.. image:: ../images/monkey_steps.jpg h!j7h"h#h$Uimager^h&}r_(UuriX!design/../images/monkey_steps.jpgr`h+]h*]h(]h)]U candidatesra}rbU*j`sh-]uh/KÎh0hh]ubhS)rc}rd(h XªNotice that no pixels are ever copied. All the work is done inside ``jpeg_write_view``. If we call our ``luminosity_histogram`` with ``step5`` it will do the right thing.h!j7h"h#h$hdh&}re(h(]h)]h*]h+]h-]uh/KÏh0hh]rf(h9XCNotice that no pixels are ever copied. All the work is done inside rg…rh}ri(h XCNotice that no pixels are ever copied. All the work is done inside h!jcubhÖ)rj}rk(h X``jpeg_write_view``h&}rl(h(]h)]h*]h+]h-]uh!jch]rmh9Xjpeg_write_viewrn…ro}rp(h Uh!jjubah$hÞubh9X. If we call our rq…rr}rs(h X. If we call our h!jcubhÖ)rt}ru(h X``luminosity_histogram``h&}rv(h(]h)]h*]h+]h-]uh!jch]rwh9Xluminosity_histogramrx…ry}rz(h Uh!jtubah$hÞubh9X with r{…r|}r}(h X with h!jcubhÖ)r~}r(h X ``step5``h&}r€(h(]h)]h*]h+]h-]uh!jch]rh9Xstep5r‚…rƒ}r„(h Uh!j~ubah$hÞubh9X it will do the right thing.r……r†}r‡(h X it will do the right thing.h!jcubeubeubeubah UU transformerrˆNU footnote_refsr‰}rŠUrefnamesr‹}rŒUsymbol_footnotesr]rŽUautofootnote_refsr]rUsymbol_footnote_refsr‘]r’U citationsr“]r”h0hU current_liner•NUtransform_messagesr–]r—Ureporterr˜NUid_startr™KU autofootnotesrš]r›U citation_refsrœ}rUindirect_targetsrž]rŸUsettingsr (cdocutils.frontend Values r¡or¢}r£(Ufootnote_backlinksr¤KUrecord_dependenciesr¥NU rfc_base_urlr¦Uhttps://tools.ietf.org/html/r§U tracebackr¨ˆUpep_referencesr©NUstrip_commentsrªNU toc_backlinksr«Uentryr¬U language_coder­Uenr®U datestampr¯NU report_levelr°KU _destinationr±NU halt_levelr²KU strip_classesr³Nh6NUerror_encoding_error_handlerr´UbackslashreplacerµUdebugr¶NUembed_stylesheetr·‰Uoutput_encoding_error_handlerr¸Ustrictr¹U sectnum_xformrºKUdump_transformsr»NU docinfo_xformr¼KUwarning_streamr½NUpep_file_url_templater¾Upep-%04dr¿Uexit_status_levelrÀKUconfigrÁNUstrict_visitorrÂNUcloak_email_addressesrÈUtrim_footnote_reference_spacerĉUenvrÅNUdump_pseudo_xmlrÆNUexpose_internalsrÇNUsectsubtitle_xformrȉU source_linkrÉNUrfc_referencesrÊNUoutput_encodingrËUutf-8rÌU source_urlrÍNUinput_encodingrÎU utf-8-sigrÏU_disable_configrÐNU id_prefixrÑUU tab_widthrÒKUerror_encodingrÓUasciirÔU_sourcerÕh#Ugettext_compactrÖˆU generatorr×NUdump_internalsrØNU smart_quotesrÙ‰U pep_base_urlrÚU https://www.python.org/dev/peps/rÛUsyntax_highlightrÜUlongrÝUinput_encoding_error_handlerrÞj¹Uauto_id_prefixrßUidràUdoctitle_xformrá‰Ustrip_elements_with_classesrâNU _config_filesrã]Ufile_insertion_enabledräˆU raw_enabledråKU dump_settingsræNubUsymbol_footnote_startrçKUidsrè}ré(hh>h–h’hrhnh„h€hj“hj7hhhhìh]hYhhœuUsubstitution_namesrê}rëh$h0h&}rì(h(]h+]h*]Usourceh#h)]h-]uU footnotesrí]rîUrefidsrï}rðub.