Re: Change Channel names

Peter Hillman <[email protected]> Tue, 15 Dec 2015 20:03:39 +1300
Newsgroups gmane.comp.video.openexr.user
Message-ID <[email protected]>
--===============5671068383254460130==
Content-Type: multipart/alternative;
	boundary="------------090705020307060409050401"

--------------090705020307060409050401
Content-Type: text/plain; charset="utf-8"; format=flowed
Content-Transfer-Encoding: 7bit

You could maybe extend the Image class using something like this pseudocode.
The ImageChannel class returns aslice() object that stores the image 
layout: you can use that to access the pixels.
And by pseudocode I mean "untested C++":

template <classT>
void
TypedImageChannel<T>::operator+=(const TypedImageChannel<T> &other)
{

    assert(image() == other.image());

    IMF::Slice outSlice = slice();
    IMF::Slice inSlice = other.slice();

    assert(outSlice.xSampling == 1);
    assert(outSlice.ySampling == 1);
    assert(inSlice.xSampling == 1);
    assert(inSlice.ySampling == 1);

    for ( int y = image().dataWindow().min.y ; y <= 
image().dataWindow().max.y ; ++y)
    {
       for( int x = image().dataWindow().min.x ; x <= 
image().dataWindow().max.x; ++x)
       {
          * (T*) (outSlice.base + y*outSlice.yStride + 
x*outSlice.xStride) += * (T*) (inSlice.base + y*inSlice.yStride + 
x*inSlice.xStride);
       }
    }
}

You should then be able to merge channels by doing
image.typedChannel<half>(outChanName)+=image.typedChannel<half>(inChanName);
for each channel inChanName you want to add into outChanName before you 
write out the image again, and assuming your channels are stored as half 
floats.
I'm not sure if that's exactly what you need, but the nested 'for' loops 
should give you an idea how to iterate over the pixels.

If you expect the tool to get more complex than this it may be worth 
using a generic image processing library which supports OpenEXR instead.




On 14/12/15 23:47, Aaron Carlisle wrote:
>
> You're awesome! Ill work with this today, and see where I get.
>
> In addition to changing the channel names I also wanted to be able to 
> combine the channel data from the rgb channels from each layer into 
> one. In python I just created a dictionary, grouped the rgb channels 
> and used array to convert them. So (customlayer.red 
> <http://customlayer.red>, customlayer.blue <http://customlayer.blue>, 
> customlayer.green <http://customlayer.green>) became 
> (newlayername.customchannelname(combined pixel data from red, green, 
> blue)). In C++ it doesn't seem seem as simple. Do you have any 
> suggestions for doing the same in C++?
>
> Thanks again!!
>
> On Dec 13, 2015, at 8:48 PM, Peter Hillman <[email protected] 
> <mailto:[email protected]>> wrote:
>
>     You cannot modify a channel name because the ChannelList object
>     keeps them sorted. If you wish to rename a channel within a list,
>     you must delete it and reinsert it with the new name, or else
>     assemble a completely new ChannelList containing the channels the
>     way you want.
>
>     You may find the source of the multiview utility instructive:
>     https://github.com/openexr/openexr/blob/master/OpenEXR/exrmultiview/makeMultiView.cpp
>
>     That reads in channels from the input(s) and writes them out with
>     different names.
>     You could drop a channel from the output file by making these two
>     lines conditional:
>     header. channels (). insert (outChanName, inChannel);
>     and
>     outFb. insert (outChanName,image. channel (outChanName). slice ());
>
>
>
>     On 12/12/15 08:02, Aaron Carlisle wrote:
>>     In the ChannelList::Iterator and ChannelList::ConsIterator name()
>>     is being defined as a const char * name () const, which means I
>>     can't change the name. Is there anyway around this? I just want
>>     to be able to change the channel name. I tried converting name
>>     into a string then back into a const char * which works, but I
>>     have significant data loss and the pixels no longer show up in
>>     the image.
>>
>>
>>     _______________________________________________
>>     Openexr-user mailing list
>>     [email protected]
>>     https://lists.nongnu.org/mailman/listinfo/openexr-user
>
>       
>     ------------------------------------------------------------------------
>
>     Openexr-user mailing list
>     [email protected]
>     https://lists.nongnu.org/mailman/listinfo/openexr-user
>

--------------090705020307060409050401
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: 8bit

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    You could maybe extend the <tt>Image</tt> class using something
    like this pseudocode.<br>
    The <tt>ImageChannel</tt> class returns a<tt> slice()</tt> object
    that stores the image layout: you can use that to access the pixels.<br>
    And by pseudocode I mean "untested C++":<br>
    <br>
    <tt><span class="pl-k">template </span></tt><tt>&lt;</tt><tt><span
        class="pl-k">class</span></tt><tt> </tt><tt><span class="pl-en">T</span></tt><tt>&gt;</tt><tt><span
        class="pl-k"><br>
        void<br>
        T</span></tt><tt>ypedImageChannel&lt;T&gt;::operator+=(</tt><tt><span
        class="pl-k">const T</span></tt><tt>ypedImageChannel&lt;T&gt;
      &amp;other)</tt><tt><br>
    </tt><tt>{</tt><tt><br>
    </tt><tt><br>
    </tt><tt>   assert(image() == other.image());</tt><tt><br>
    </tt><tt>   </tt><tt><br>
    </tt><tt>   IMF::Slice outSlice = slice();</tt><tt><br>
    </tt><tt>   IMF::Slice inSlice = other.slice();</tt><tt><br>
    </tt><tt><br>
    </tt><tt>   assert(outSlice.xSampling == 1);</tt><tt><br>
    </tt><tt>   assert(outSlice.ySampling == 1);</tt><tt><br>
    </tt><tt>    assert(inSlice.xSampling == 1);</tt><tt><br>
    </tt><tt>    assert(inSlice.ySampling == 1);</tt><tt><br>
    </tt><tt><br>
    </tt><tt>   for ( int y = image().dataWindow().min.y ; y &lt;=
      image().dataWindow().max.y ; ++y)</tt><tt><br>
    </tt><tt>   {</tt><tt><br>
    </tt><tt>      for( int x = image().dataWindow().min.x ; x &lt;=
      image().dataWindow().max.x; ++x)</tt><tt><br>
    </tt><tt>      {</tt><tt><br>
    </tt><tt>         * (T*) (outSlice.base + y*outSlice.yStride +
      x*outSlice.xStride) += * (T*) (inSlice.base + y*inSlice.yStride +
      x*inSlice.xStride);</tt><tt><br>
    </tt><tt>      }</tt><tt><br>
    </tt><tt>   }</tt><tt><br>
    </tt><tt>}</tt><tt><br>
    </tt><br>
    You should then be able to merge channels by doing<br>
    <tt>image.typedChannel&lt;half&gt;(outChanName)+=image</tt><tt><tt>.typedChannel&lt;half&gt;</tt>(inChanName);</tt><br>
    for each channel inChanName you want to add into outChanName before
    you write out the image again, and assuming your channels are stored
    as half floats.<br>
    I'm not sure if that's exactly what you need, but the nested 'for'
    loops should give you an idea how to iterate over the pixels.<br>
    <br>
    If you expect the tool to get more complex than this it may be worth
    using a generic image processing library which supports OpenEXR
    instead.<br>
    <br>
    <br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 14/12/15 23:47, Aaron Carlisle
      wrote:<br>
    </div>
    <blockquote
      cite="mid:[email protected]"
      type="cite">
      <p dir="ltr">You're awesome! Ill work with this today, and see
        where I get. </p>
      <p dir="ltr">In addition to changing the channel names I also
        wanted to be able to combine the channel data from the rgb
        channels from each layer into one. In python I just created a
        dictionary, grouped the rgb channels and used array to convert
        them. So (<a moz-do-not-send="true"
          href="http://customlayer.red">customlayer.red</a>, <a
          moz-do-not-send="true" href="http://customlayer.blue">customlayer.blue</a>,
        <a moz-do-not-send="true" href="http://customlayer.green">customlayer.green</a>)
        became (newlayername.customchannelname(combined pixel data from
        red, green, blue)). In C++ it doesn't seem seem as simple. Do
        you have any suggestions for doing the same in C++?</p>
      <p dir="ltr">Thanks again!!<br>
        <br>
      </p>
      <div class="gmail_quote">On Dec 13, 2015, at 8:48 PM, Peter
        Hillman &lt;<a moz-do-not-send="true"
          href="mailto:[email protected]" target="_blank">[email protected]</a>&gt;

        wrote:
        <blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
          0.8ex; border-left: 1px solid rgb(204, 204, 204);
          padding-left: 1ex;"> You cannot modify a channel name because
          the ChannelList object keeps them sorted. If you wish to
          rename a channel within a list, you must delete it and
          reinsert it with the new name, or else assemble a completely
          new ChannelList containing the channels the way you want. <br>
          <br>
          You may find the source of the multiview utility instructive:
          <br>
          <tt><a moz-do-not-send="true" class="moz-txt-link-freetext"
href="https://github.com/openexr/openexr/blob/master/OpenEXR/exrmultiview/makeMultiView.cpp">https://github.com/openexr/openexr/blob/master/OpenEXR/exrmultiview/makeMultiView.cpp</a></tt>
          <br>
          That reads in channels from the input(s) and writes them out
          with different names. <br>
          You could drop a channel from the output file by making these
          two lines conditional: <br>
          <tt>header.</tt> <tt><span class="pl-c1">channels</span></tt>
          <tt>().</tt> <tt><span class="pl-c1">insert</span></tt> <tt>
            (outChanName, inChannel); </tt> <br>
          and <br>
          <tt>outFb.</tt> <tt><span class="pl-c1">insert</span></tt> <tt>
            (outChanName,image.</tt> <tt><span class="pl-c1">channel</span></tt>
          <tt>(outChanName).</tt> <tt><span class="pl-c1">slice</span></tt>
          <tt>());</tt> <br>
          <br>
          <br>
          <br>
          <div class="moz-cite-prefix"> On 12/12/15 08:02, Aaron
            Carlisle wrote: <br>
          </div>
          <blockquote
cite="mid:CADwEHsO24VMfQcUausakqRtO7uQPm-kshDDoFjLe+hwaxXu0xg@mail.gmail.com"
            type="cite">
            <div dir="ltr"> In the ChannelList::Iterator and
              ChannelList::ConsIterator name() is being defined as a
              const char * name () const, which means I can't change the
              name. Is there anyway around this? I just want to be able
              to change the channel name. I tried converting name into a
              string then back into a const char * which works, but I
              have significant data loss and the pixels no longer show
              up in the image. </div>
            <br>
            <fieldset class="mimeAttachmentHeader"></fieldset>
            <br>
            <pre wrap="">_______________________________________________
Openexr-user mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:[email protected]">[email protected]</a>
<a moz-do-not-send="true" class="moz-txt-link-freetext" href="https://lists.nongnu.org/mailman/listinfo/openexr-user">https://lists.nongnu.org/mailman/listinfo/openexr-user</a>
</pre>
          </blockquote>
          <br>
          <pre class="blue"> <hr>
Openexr-user mailing list
<a class="moz-txt-link-abbreviated" href="mailto:[email protected]">[email protected]</a>
<a moz-do-not-send="true" href="https://lists.nongnu.org/mailman/listinfo/openexr-user">https://lists.nongnu.org/mailman/listinfo/openexr-user</a>
</pre></blockquote></div>


</blockquote>
</body></html>
--------------090705020307060409050401--


--===============5671068383254460130==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Openexr-user mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/openexr-user

--===============5671068383254460130==--