title: YUV420 to RGB conversion
body: <p>I converted an RGB matrix to YUV matrix using this formula:</p>
  
  <pre><code>Y  =      (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
  Cr = V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
  Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
  </code></pre>
  
  <p>I then did a 4:2:0 chroma subsample on the matrix. I think I did this correctly, I took 2x2 submatrices from the YUV matrix, ordered the values from least to greatest, and took the average between the 2 values in the middle.</p>
  
  <p>I then used this formula, from Wikipedia, to access the Y, U, and V planes:</p>
  
  <pre><code>size.total = size.width * size.height;
  y = yuv[position.y * size.width + position.x];
  u = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total];
  v = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total + (size.total / 4)];
  </code></pre>
  
  <p>I'm using OpenCV so I tried to interpret this as best I can:</p>
  
  <pre><code>y = src.data[(i*channels)+(j*step)];
  u = src.data[(j%4)*step + ((i%2)*channels+1) + max];
  v = src.data[(j%4)*step + ((i%2)*channels+2) + max + (max%4)];
  </code></pre>
  
  <p>src is the YUV subsampled matrix. Did I interpret that formula correctly?</p>
  
  <p>Here is how I converted the colours back to RGB:</p>
  
  <pre><code>bgr.data[(i*channels)+(j*step)] = (1.164 * (y - 16)) + (2.018 * (u - 128)); // B
  bgr.data[(i*channels+1)+(j*step)] = (1.164 * (y - 16)) - (0.813 * (v - 128)) - (0.391 * (u - 128)); // G
  bgr.data[(i*channels+2)+(j*step)] = (1.164 * (y - 16)) + (1.596 * (v - 128));   // R
  </code></pre>
  
  <p>The problem is my image does not return to its original colours.</p>
  
  <p>Here are the images for reference:
  <a href="http://i.stack.imgur.com/vQkpT.jpg" rel="nofollow">http://i.stack.imgur.com/vQkpT.jpg</a> (Subsampled)
  <a href="http://i.stack.imgur.com/Oucc5.jpg" rel="nofollow">http://i.stack.imgur.com/Oucc5.jpg</a> (Output)</p>
  
  <p>I see that I should be converting from YUV444 to RGB now but I don't quite I understand what the clip function does in the sample I found on Wiki.</p>
  
  <pre><code>C = Y' − 16
  D = U − 128
  E = V − 128
  
  R = clip(( 298 * C           + 409 * E + 128) &gt;&gt; 8)
  G = clip(( 298 * C - 100 * D - 208 * E + 128) &gt;&gt; 8)
  B = clip(( 298 * C + 516 * D           + 128) &gt;&gt; 8)
  </code></pre>
  
  <p>Does the >> mean I should shift bits?</p>
  
  <p>I'd appreciate any help/comments! Thanks</p>
  
  <p><strong>Update</strong></p>
  
  <p>Tried doing the YUV444 conversion but it just made my image appear in shades of green.</p>
  
  <pre><code>        y = src.data[(i*channels)+(j*step)];
          u = src.data[(j%4)*step + ((i%2)*channels+1) + max];
          v = src.data[(j%4)*step + ((i%2)*channels+2) + max + (max%4)];
  
          c = y - 16;
          d = u - 128;
          e = v - 128;
  
          bgr.data[(i*channels+2)+(j*step)] = clip((298*c + 409*e + 128)/256);
          bgr.data[(i*channels+1)+(j*step)] = clip((298*c - 100*d - 208*e + 128)/256);
          bgr.data[(i*channels)+(j*step)] = clip((298*c + 516*d + 128)/256);
  </code></pre>
  
  <p>And my clip function:
      int clip(double value)
      {
          return (value > 255) ? 255 : (value &lt; 0) ? 0 : value;
      }</p>