title: Is there a better way of handling bitmap data depending on compression + bitcount?
body: <p>I've been studying the Bitmap (.bmp) file format for a while now, trying to figure out how to structure the read function. The general idea is to support all the common compression types, be safe and still quick to load into a (custom) general in-memory image for further processing in a machine vision library.</p>
  
  <p>With performance in mind, I figured it would be best to write an as efficient loop as possible for each bitcount + compression type constellation. Here's a snippet of how that looks for <code>BI_RGB</code>:</p>
  
  <pre><code>if (bmpi.biCompression == BI_RGB){
      if (bmpi.biBitCount &gt;= 24){
          // Here, every byte is each channel's value (assuming order is GBR(A))
          for (y = start_y; y != end_y; y += direction){
              row = y * stride;
              for (x = 0; x &lt; stride; x += bpp){
                  index = row + x;
                  *(res-&gt;data++) = read_data[index + 2]; // R
                  *(res-&gt;data++) = read_data[index + 1]; // G
                  *(res-&gt;data++) = read_data[index];     // B
              }
          }
      }
      else if (bmpi.biBitCount == 16){
          // Without a bitfield mask, it's assumed 555 (instead of the common 565) with the last bit discarded
          for (y = start_y; y != end_y; y += direction){
              row = y * stride;
              for (x = 0; x &lt; stride; x += bpp){
                  val = (WORD)&amp;read_data[row + x];
                  *(res-&gt;data++) = map16to255[((val &gt;&gt; 10) &amp; 31)]; // R
                  *(res-&gt;data++) = map16to255[((val &gt;&gt; 5) &amp; 31)];  // G
                  *(res-&gt;data++) = map16to255[(val &amp; 31)];         // B
              }
          }
      }
      else if (bmpi.biBitCount == 8){
          for (y = start_y; y != end_y; y += direction){
              row = y * stride;
              for (x = 0; x &lt; stride; x += bpp){
                  memcpy(res-&gt;data, &amp;colors[read_data[row + x]], 3); // Copy RGB from color table
                  res-&gt;data += 3; // Increment
              }
          }
      }
      else if (bmpi.biBitCount == 4){
          // 2 pixels per byte
          for (y = start_y; y != end_y; y += direction){
              row = y * stride;
              for (x = 0; x &lt; stride; x += bpp){
                  index = row + x;
                  memcpy(res-&gt;data, &amp;colors[(read_data[index] &amp; 15)], 3);
                  res-&gt;data += 3;
                  memcpy(res-&gt;data, &amp;colors[(read_data[index] &gt;&gt; 4)], 3);
                  res-&gt;data += 3;
              }
          }
      }
      else{
          // 8 pixels per byte
          for (y = start_y; y != end_y; y += direction){
              row = y * stride;
              for (x = 0; x &lt; stride; x += bpp){
                  index = row + x;
                  for (i = 0; i &lt; 8; i++){
                      memcpy(res-&gt;data, &amp;colors[((read_data[index] &gt;&gt; i) &amp; 1)], 3);
                      res-&gt;data += 3;
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>It doesn't look pretty, to be honest.
  Then I thought about assigning a function pointer and just write one loop but worry it would make it slower somehow. At least it would add a layer of obfuscation (of what is going on). I'd rather have bloated code if it clearly shows what is happening and what the intention is though</p>
  
  <pre><code>typedef void(*pxl_proc) (int index, BYTEP read_data, BYTEP in_data, PRGBQUAD colors);    
  //...
  pxl_proc func = _24_rgb;
  for (y = start_y; y != end_y; y += direction){
      row = y * stride;
      for (x = 0; x &lt; stride; x += bpp){
          func(row + x, read_data, res-&gt;data, colors);
      }
  }
  </code></pre>
  
  <p>I get the sense that this approach is unnecessarily specific and that there's a general way to process the bitmap while still being as quick, or quicker.</p>
  
  <p>How should I be doing this? Is this "good enough" for a professional library?</p>