using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace icEveryCode
{
  public class icUtils
  {
    /// <summary>
    /// Преобразование изображения в массив яркостей
    /// </summary>
    /// <param name="image">Изображение</param>
    /// <param name="array"></param>
    static public void BitmapToArray (Bitmap image, byte[ ] array)
    {
      int colCount = image.Width;
      int rowCount = image.Height;
      if ( array.Length <= colCount * rowCount )
      {
        new Exception( "Размер массива слишком мал." );
      }
      PixelFormat PF = image.PixelFormat;
      

      Rectangle rect = new Rectangle( 0, 0, colCount, rowCount );
      // Lock the bitmap's bits.
      BitmapData bmpData = image.LockBits( rect, ImageLockMode.ReadWrite, PF );
      try
      {
        byte[ ] P = new byte[ 256 ];
        switch ( PF )
        {
          case PixelFormat.Format8bppIndexed:
          case PixelFormat.Format4bppIndexed:
          case PixelFormat.Format1bppIndexed:
            {
              ColorPalette Palette = null;
              Palette = image.Palette;
              for ( int i = 0; i < Palette.Entries.Length; i++ )
              {
                Color C = Palette.Entries[ i ];
                P[ i ] = (byte)( ( C.R * 30 + C.G * 59 + C.B * 11 ) / 100 );
              }
              break;
            }
          case PixelFormat.Format24bppRgb:
          case PixelFormat.Format32bppArgb:
          case PixelFormat.Format32bppRgb:
            break;
          default:
            throw new Exception( "цветовая схема " + image.PixelFormat.ToString( ) + " не поддерживается!" );
        }

        int bytePerPixel = bmpData.Stride / bmpData.Width;
        unsafe
        {
          fixed ( byte* FArray = &array[ 0 ] )
          {
            for ( int row = 0; row < rowCount; row++ )
            {
              byte* line = (byte*)bmpData.Scan0 + bmpData.Stride * row;
              for ( int col = 0; col < colCount; col++ )
              {
                byte B;
                switch ( PF )
                {
                  case PixelFormat.Format24bppRgb:
                    B = (byte)( ( line[ col * 3 + 2 ] * 30 + line[ col * 3 + 1 ] * 59 + line[ col * 3 ] * 11 ) / 100 );
                    break;
                  case PixelFormat.Format32bppArgb:
                  case PixelFormat.Format32bppRgb:
                    B = (byte)( ( line[ col * 4 + 2 ] * 30 + line[ col * 4 + 1 ] * 59 + line[ col * 4 ] * 11 ) / 100 );
                    break;
                  case PixelFormat.Format8bppIndexed:
                    B = P[ line[ col ] ];
                    break;
                  case PixelFormat.Format4bppIndexed:
                    if ( ( col & 1 ) == 1 )
                      B = P[ line[ col / 2 ] & 0x0F ];
                    else
                      B = P[ line[ col / 2 ] & 0xF0 >> 4 ];
                    break;
                  case PixelFormat.Format1bppIndexed:
                    int nBit = 7 - col & 7;
                    int nByte = col / 8;
                    B = P[ ( line[ nByte ] >> nBit ) & 1 ];
                    break;
                  default:
                    throw new Exception( "цветовая схема " + image.PixelFormat.ToString( ) + " не поддерживается!" );
                }
                FArray[ colCount * row + col ] = B;
              }
            }
          }
        }
      }
      finally
      {
        // Unlock the bitmap's bits.

        image.UnlockBits( bmpData );
      }

    }
  }
}
