Boost C++ Libraries: Ticket #2211: Can not create image of Regular type https://svn.boost.org/trac10/ticket/2211 <p> The GIL docs say images, views, and locator's can be created from any type that satisfies the GIL concept 'Regular' </p> <p> quoted from boost/gil/image.hpp: </p> <div class="wiki-code"><div class="code"><pre><span class="c1">/// Note that its element type does not have to be a pixel. \p image can be instantiated with any Regular element,</span> <span class="c1">/// in which case it models the weaker RandomAccess2DImageConcept and does not model PixelBasedConcept</span> </pre></div></div><p> Unfortunately this does not seem to be true, even the simple test attached fails to compile. </p> <p> Depending upon whether I define the image to be planar or not, I get errors with different metafunctions: for <a class="missing wiki">IsPlanar</a> == true: </p> <blockquote> <p> the error is in the view_type_pixel metafunction, which invokes channel_type. </p> </blockquote> <p> if <a class="missing wiki">IsPlanar</a> == false: </p> <blockquote> <p> the error is in the is_planar metafunction. </p> </blockquote> <p> --John </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/2211 Trac 1.4.3 john.femiani@… Mon, 18 Aug 2008 05:08:23 GMT attachment set https://svn.boost.org/trac10/ticket/2211 https://svn.boost.org/trac10/ticket/2211 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_gil_image_of_regular_type.cpp</span> </li> </ul> <p> A Boost.Test testcase that fails to compile when it should succed AFIK. </p> Ticket john.femiani@… Mon, 18 Aug 2008 10:42:34 GMT <link>https://svn.boost.org/trac10/ticket/2211#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/2211#comment:1</guid> <description> <p> The issue is twofold: </p> <ol><li>A regular type (like a single-chennel pixel) can be considered planer or interleaved. When the image type is planar, GIL tends to use the <code>num_channels</code> metafunction (valid only for PixelBased), so it is easier just to say Regular types are <strong>not</strong> planar. </li></ol><ol start="2"><li>The <code>is_planar</code> metafunction had no default value. I think it is safe to say that the <code>is_planar</code> metafunction is short for <code>is_planar_pixel</code>, and so if the type is not a pixel it should return <code>false_</code>. In fact, I think it is reasonable to let it have a default value of <code>false_</code>. </li></ol><ol start="3"><li>Some of the code first checks if the image is planar and then uses PixelBased operations if it is planar, but the code was laid out so that both branches of the <code>if (!IsPLanar)</code> condition had to compiles. I reorganized that code slightly. </li></ol><p> Since I have had bad luck attaching patches on this Trac site (Trac thinks they ar spam!), the patch that made my test compile is attached (no clue if I broke anything else, I just have the headers here). </p> <div class="wiki-code"> <div class="diff"> <ul class="entries"> <li class="entry"> <h2> <a>image.hpp</a> </h2> <table class="trac-diff inline" cellspacing="0"> <colgroup> <col class="lineno"/><col class="lineno"/><col class="content"/> </colgroup> <thead> <tr> <th title="File image.hpp (revision 48190)"> </th> <th title="File image.hpp (working copy)"> </th> <td> <em></em> &nbsp; </td> </tr> </thead> <tbody class="unmod"> <tr> <th>193</th><th>193</th><td class="l"><span>&nbsp; &nbsp; &nbsp; &nbsp; if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions));</span></td> </tr> <tr> <th>194</th><th>194</th><td class="l"><span>&nbsp; &nbsp; }</span></td> </tr> <tr> <th>195</th><th>195</th><td class="l"><span></span></td> </tr> </tbody> <tbody class="add"> <tr class="first"> <th>&nbsp;</th><th>196</th><td class="r"><ins>&nbsp; &nbsp; struct _channels_in_image :</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>197</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; mpl::eval_if&lt;is_pixel&lt;value_type&gt;,</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>198</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; num_channels&lt;view_t&gt;,</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>199</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mpl::int_&lt;1&gt;</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>200</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &gt;::type</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>201</th><td class="r"><ins>&nbsp; &nbsp; {};</ins></td> </tr> <tr class="last"> <th>&nbsp;</th><th>202</th><td class="r"><ins></ins></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>196</th><th>203</th><td class="l"><span>&nbsp; &nbsp; std::size_t total_allocated_size_in_bytes(const point_t&amp; dimensions) const {</span></td> </tr> <tr> <th>197</th><th>204</th><td class="l"><span>&nbsp; &nbsp; &nbsp; &nbsp; std::size_t size_in_units = get_row_size_in_memunits(dimensions.x)*dimensions.y;</span></td> </tr> </tbody> <tbody class="rem"> <tr class="first"> <th>198</th><th>&nbsp;</th><td class="l"><del>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (IsPlanar)</del></td> </tr> <tr class="last"> <th>199</th><th>&nbsp;</th><td class="l"><del>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size_in_units = size_in_units*num_channels&lt;view_t&gt;::value;</del></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>200</th><th>205</th><td class="l"><span></span></td> </tr> </tbody> <tbody class="add"> <tr class="first"> <th>&nbsp;</th><th>206</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; typedef typename view_t::x_iterator x_iterator;</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>207</th><td class="r"><ins></ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>208</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; if (IsPlanar)</ins></td> </tr> <tr class=""> <th>&nbsp;</th><th>209</th><td class="r"><ins>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size_in_units = size_in_units*_channels_in_image::value;</ins></td> </tr> <tr class="last"> <th>&nbsp;</th><th>210</th><td class="r"><ins></ins></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>201</th><th>211</th><td class="l"><span>&nbsp; &nbsp; &nbsp; &nbsp; // return the size rounded up to the nearest byte</span></td> </tr> </tbody> <tbody class="mod"> <tr class="first"> <th>202</th><th>&nbsp;</th><td class="l"><span>&nbsp; &nbsp; &nbsp; &nbsp; return (size_in_units + byte_to_memunit&lt;typename view_t::x_iterator&gt;::value - 1) / byte_to_memunit&lt;typename view_t::x_iterator&gt;::value</span></td> </tr> <tr> <th>203</th><th>&nbsp;</th><td class="l"><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + (_align_in_bytes&gt;0 ? _align_in_bytes-1:0);&nbsp; &nbsp; // add extra padding in case we need to align the first image pixel</span></td> </tr> <tr> <th>&nbsp;</th><th>212</th><td class="r"><span>&nbsp; &nbsp; &nbsp; &nbsp; return (size_in_units + byte_to_memunit&lt;x_iterator&gt;::value - 1) / byte_to_memunit&lt;x_iterator&gt;::value</span></td> </tr> <tr> <th>&nbsp;</th><th>213</th><td class="r"><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + (_align_in_bytes&gt;0 ? _align_in_bytes-1:0);</span></td> </tr> <tr class="last"> <th>&nbsp;</th><th>214</th><td class="r"><span>&nbsp; &nbsp; &nbsp; &nbsp; // add extra padding in case we need to align the first image pixel</span></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>204</th><th>215</th><td class="l"><span>&nbsp; &nbsp; }</span></td> </tr> <tr> <th>205</th><th>216</th><td class="l"><span></span></td> </tr> <tr> <th>206</th><th>217</th><td class="l"><span>&nbsp; &nbsp; std::size_t get_row_size_in_memunits(x_coord_t width) const {&nbsp; &nbsp;// number of units per row</span></td> </tr> </tbody> </table> </li> <li class="entry"> <h2> <a>pixel.hpp</a> </h2> <table class="trac-diff inline" cellspacing="0"> <colgroup> <col class="lineno"/><col class="lineno"/><col class="content"/> </colgroup> <thead> <tr> <th title="File pixel.hpp (revision 48190)"> </th> <th title="File pixel.hpp (working copy)"> </th> <td> <em></em> &nbsp; </td> </tr> </thead> <tbody class="unmod"> <tr> <th>42</th><th>42</th><td class="l"><span>template &lt;typename PixelBased&gt; struct color_space_type;</span></td> </tr> <tr> <th>43</th><th>43</th><td class="l"><span>template &lt;typename PixelBased&gt; struct channel_mapping_type;</span></td> </tr> <tr> <th>44</th><th>44</th><td class="l"><span>template &lt;typename PixelBased&gt; struct channel_type;</span></td> </tr> </tbody> <tbody class="mod"> <tr class="first"> <th>45</th><th>&nbsp;</th><td class="l"><span>template &lt;typename PixelBased&gt; struct is_planar<del>;</del></span></td> </tr> <tr class="last"> <th>&nbsp;</th><th>45</th><td class="r"><span>template &lt;typename PixelBased&gt; struct is_planar<ins>&nbsp;: mpl::false_{}; //False by default</ins></span></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>46</th><th>46</th><td class="l"><span></span></td> </tr> <tr> <th>47</th><th>47</th><td class="l"><span>template &lt;typename PixelBased&gt; struct color_space_type&lt;const PixelBased&gt; : public color_space_type&lt;PixelBased&gt; {};</span></td> </tr> <tr> <th>48</th><th>48</th><td class="l"><span>template &lt;typename PixelBased&gt; struct channel_mapping_type&lt;const PixelBased&gt; : public channel_mapping_type&lt;PixelBased&gt; {};</span></td> </tr> </tbody> </table> </li> </ul> </div></div> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Tue, 19 Aug 2008 09:24:42 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/2211#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/2211#comment:2</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/2211#comment:1" title="Comment 1">john.femiani@asu.edu</a>: </p> <blockquote class="citation"> <ol><li>A regular type (like a single-chennel pixel) can be considered planer or interleaved. When the image type is planar, GIL tends to use the <code>num_channels</code> metafunction (valid only for PixelBased), so it is easier just to say Regular types are <strong>not</strong> planar. </li></ol></blockquote> <p> In order to make this clear, I suggest the following additional patch, to be applied after the first: </p> <div class="wiki-code"> <div class="diff"> <ul class="entries"> <li class="entry"> <h2> <a>image.hpp</a> </h2> <table class="trac-diff inline" cellspacing="0"> <colgroup> <col class="lineno"/><col class="lineno"/><col class="content"/> </colgroup> <thead> <tr> <th title="File image.hpp (revision 48190)"> </th> <th title="File image.hpp (working copy)"> </th> <td> <em></em> &nbsp; </td> </tr> </thead> <tbody class="unmod"> <tr> <th>48</th><th>48</th><td class="l"><span>////////////////////////////////////////////////////////////////////////////////////////</span></td> </tr> <tr> <th>49</th><th>49</th><td class="l"><span></span></td> </tr> </tbody> <tbody class="mod"> <tr class="first"> <th>50</th><th>&nbsp;</th><td class="l"><span>template &lt;typename Pixel, bool IsPlanar, typename Alloc=std::allocator&lt;unsigned char&gt; &gt;&nbsp; &nbsp; </span></td> </tr> <tr> <th>&nbsp;</th><th>50</th><td class="r"><span>template &lt;typename Pixel,</span></td> </tr> <tr> <th>&nbsp;</th><th>51</th><td class="r"><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bool IsPlanar=false,</span></td> </tr> <tr class="last"> <th>&nbsp;</th><th>52</th><td class="r"><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typename Alloc=std::allocator&lt;unsigned char&gt; &gt;</span></td> </tr> </tbody> <tbody class="unmod"> <tr> <th>51</th><th>53</th><td class="l"><span>class image {</span></td> </tr> <tr> <th>52</th><th>54</th><td class="l"><span>public:</span></td> </tr> <tr> <th>53</th><th>55</th><td class="l"><span>&nbsp; &nbsp; typedef typename Alloc::template rebind&lt;unsigned char&gt;::other allocator_type;</span></td> </tr> </tbody> </table> </li> </ul> </div></div><p> This provides a default value for the IsPlanar template argument, so it can b left out if the image is a single channel pixel, so it does not create semantic 'noise'. </p> <p> For example: </p> <div class="wiki-code"><div class="code"><pre> <span class="n">gil</span><span class="o">::</span><span class="n">image</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">the_img</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span> <span class="n">gil</span><span class="o">::</span><span class="n">image</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;::</span><span class="n">view_t</span> <span class="n">the_view</span> <span class="o">=</span> <span class="n">view</span><span class="p">(</span><span class="n">img</span><span class="p">);</span> <span class="c1">//NOTE: Why arent views constructible from images?</span> </pre></div></div><p> --John </p> </description> <category>Ticket</category> </item> <item> <dc:creator>chhenning</dc:creator> <pubDate>Thu, 05 Aug 2010 18:55:31 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/2211#comment:3 https://svn.boost.org/trac10/ticket/2211#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Patch has been applied. Closing this ticket. </p> Ticket