title: OpenCV decode CV_32FC1 into png
body: <p>I would like to convert a OpenCV CV_32FC1 Mat into a png to save it and later use it in a Unity Shader.
  I would like to decode it so that the first channel contains the highest 8 bits, the second channel the next 8 bits and the third channel the next 8 bits.</p>
  
  <p>Edit> I actually mean the highest bits of the mantissa. Otherwise discarding 8 Bit (since I need 3 channels for imwrite) would destroy the float-representation.</p>
  
  <p>I already have this working the other way around with this function:</p>
  
  <pre><code>Mat prepareLUT(char* filename){
      Mat first;
      first = imread(filename, CV_LOAD_IMAGE_COLOR);
      Mat floatmat;
      first.convertTo(floatmat, CV_32F);
      std::vector&lt;Mat&gt; channels(3);
      split(floatmat, channels);
      Mat res(Size(960,1080), CV_32FC1);
      res = channels[2]/255 + channels[1]/(255.0*255.0) + channels[0]/(255.0*255.0*255.0);
      return res;
  }
  </code></pre>
  
  <p>but I am unable to do this the other way around.</p>
  
  <p>My first idea was the following:</p>
  
  <pre><code>void saveLUT(Mat in, char const* filename){
      Mat m1 = Mat(imageSize, CV_8UC1);
      Mat m2 = Mat(imageSize, CV_8UC1);
      Mat m3 = Mat(imageSize, CV_8UC1);
  
      m1 = (in*(0xFF*0xFF*0xFF-1));
      m2 = (in*(0xFF*0xFF-1));
      m3 = (in*(0xFF-1));
  
      std::vector&lt;Mat&gt; channels;
      channels.push_back(m1);
      channels.push_back(m2);
      channels.push_back(m3);
      Mat out;
      merge(channels, out);
      imwrite(filename, out);
  }
  </code></pre>
  
  <p>I thought all the bits left and right of my 8 Bit range would be cut-off, giving me the right Mat, but it always outputs some gray image.</p>
  
  <p>The second approach was to work with float mats, then convert them to Char Mats to cut-off the trailing numbers:</p>
  
  <pre><code>void saveLUT(Mat in, char const* filename){
      Mat m1f(imageSize, CV_32FC1);
      Mat m2f(imageSize, CV_32FC1);
      Mat m3f(imageSize, CV_32FC1);
  
      Mat m1, m2, m3;
  
      m3f = in*255;
      m3f.convertTo(m3, CV_8UC1);
      m3.convertTo(m3f, CV_32FC1);
  
      m2f = (in*255-m3f)*255;
      m2f.convertTo(m2, CV_8UC1);
      m2.convertTo(m2f, CV_32FC1);
  
      m1f = ((in*255-m3f)*255-m2f)*255;
      m1f.convertTo(m1, CV_8UC1);
  
      std::vector&lt;Mat&gt; channels;
      channels.push_back(m1);
      channels.push_back(m2);
      channels.push_back(m3);
      Mat out;
      merge(channels, out);
      imwrite(filename, out);
  }
  </code></pre>
  
  <p>This way I always subtract the numbers that are too high by subtracting the result for the previous channel before multiplying, but this still gives me a gray result as the one below.
  <a href="https://i.stack.imgur.com/xOgSI.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xOgSI.png" alt="Sample result"></a>
  Any Idea how to tacle this?</p>