Super-sharpening(?) the image

I may have forgotten to mention it, but my expertise is not in image processing.  The people who know better will likely tsk mightily at this and upcoming posts. My apologies. =)

Last time got me a b&w-converted version of a picture, but didn’t do much with it.  Next up, I need a sequence of integer values from each row in the image for more processing.  Eventually I want to convert those numbers to simple on-and-off values for processing.  For starters, it seems like I should be able to convert each RGB pixel value into its 0-255 greyscale equivalent.  Once I’ve got a byte, my simple theory is that squaring that 8-bit grayscale will produce a 16-bit ushort to process.

Thus:

  1. Access the bits of the image
  2. Convert each pixel to greyscale
  3. Push “light” pixels towards some high-value, push “dark” pixels down towards some low-value
  4. Wrap that up in some sort of enumerator.

With a little yield fun, I ended up with an enumerator that produces ushort[] from each row in the image. 

  • Why ushorts? 255*255 = 65025, which is less than 65535. 
  • Why not put the RowData function into the enumerator with the yield?  Because C# doesn’t allow unsafe code blocks in iterators.  Wierd.
  • I’ll need to put the Bitmap acquisition and the LockData outsidethe enumerator, but that’s OK.
 public class ImageRowEnumerator : IEnumerable<ushort[]> {
    BitmapData _bmpData;
    int _rowSkip;

    public ImageRowEnumerator(BitmapData b, int skip) {
        _bmpData = b;
        _rowSkip = skip;
    }

    public IEnumerator<ushort[]> GetEnumerator() {
        for (int row = 0; row < _bmpData.Height; row += _rowSkip)
            yield return RowData(_bmpData, row);
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }

    unsafe ushort[] RowData(BitmapData bmpData, int row) {
        ushort[] row_data = new ushort[_bmpData.Width];
        byte* pData = (byte*)bmpData.Scan0 + (bmpData.Stride * row);
        for (int col = 0; col < _bmpData.Width; col++, pData += 3) {
            ushort color = (ushort)((pData[0] * .3f) + (pData[1] * .59f) + (pData[2] * .11f));
            row_data[col] = (ushort)(color * color);
        }
        return row_data;
    }
}

Next time, converting from the ushort values to on/off.  It’s not just checking for 50%.