title: How does one convert 16-bit RGB565 to 24-bit RGB888?
body: <p>I’ve got my hands on a 16-bit rgb565 image (specifically, an Android framebuffer dump), and I would like to convert it to 24-bit rgb888 for viewing on a normal monitor.</p>
  
  <p>The question is, how does one convert a 5- or 6-bit channel to 8 bits? The obvious answer is to shift it. I started out by writing this:</p>
  
  <pre><code>puts("P6 320 480 255");
  uint16_t buf;
  while (read(0, &amp;buf, sizeof buf)) {
      unsigned char red = (buf &amp; 0xf800) &gt;&gt; 11;
      unsigned char green = (buf &amp; 0x07e0) &gt;&gt; 5;
      unsigned char blue = buf &amp; 0x001f;
      putchar(red &lt;&lt; 3);
      putchar(green &lt;&lt; 2);
      putchar(blue &lt;&lt; 3);
  }
  </code></pre>
  
  <p>However, this doesn’t have one property I would like, which is for <code>0xffff</code> to map to <code>0xffffff</code>, instead of <code>0xf8fcf8</code>. I need to expand the value in some way, but I’m not sure how that should work.</p>
  
  <p>The Android SDK comes with a tool called ddms (Dalvik Debug Monitor) that takes screen captures. As far as I can tell from <a href="https://android.googlesource.com/platform/sdk/+/master/ddms/libs/ddmlib/src/com/android/ddmlib/RawImage.java" rel="noreferrer" title="android / platform/sdk / master / . / ddms / libs / ddmlib / src / com / android / ddmlib / RawImage.java">reading the code</a>, it implements the same logic; yet its screenshots are coming out different, and white is mapping to white.</p>
  
  <p>Here’s the <a href="http://jleedev.sdf.org/rgb/fb0.bz2" rel="noreferrer">raw framebuffer</a>, the <a href="http://jleedev.sdf.org/rgb/dsc.png" rel="noreferrer">smart conversion</a> by ddms, and the <a href="http://jleedev.sdf.org/rgb/fb1.png" rel="noreferrer">dumb conversion</a> by the above algorithm. Note that the latter is slightly darker and greener.</p>
  
  <p>(By the way, this conversion <a href="http://my.opera.com/otaku_2r/blog/grab-a-frame-in-android-frame-buffer" rel="noreferrer">is implemented in ffmpeg</a>, but it’s just performing the dumb conversion listed above, leaving the LSBs at all zero.)</p>
  
  <p>I guess I have two questions:</p>
  
  <ul>
  <li>What’s the most sensible way to convert rgb565 to rgb888?</li>
  <li>How is DDMS converting its screenshots?</li>
  </ul>