Чтение монохромных растровых пикселей - PullRequest
3 голосов
/ 02 марта 2009

Я не знаю лучшего названия, но опишу проблему.

Используемое нами оборудование может отображать изображения. Может отображать черно-белое изображение с разрешением 64 х 256.

Проблема в формате изображения, которое мы должны отправить на устройство. Это не стандартный растровый формат, а просто массив байты, представляющие каждый пиксель изображения.

0 = черный, 1 = белый.

Таким образом, если бы у нас было изображение размером: 4 x 4, массив байтов мог бы выглядеть примерно так:

1000 0100 0010 0001

И изображение будет выглядеть так:

Растровое изображение http://www.mediafire.com/imgbnc.php/6ee6a28148d0170708cb10ec7ce6512e4g.jpg

Проблема в том, что нам нужно создать это изображение, создав монохромное растровое изображение. в C #, а затем преобразовать его в формат файла, понятный для устройства.

Например, можно отобразить текст на устройстве. Для этого он необходимо создать растровое изображение и записать в него текст:

var bitmap = new Bitmap(256, 64);

using (var graphics = Graphics.FromImage(bitmap))
{
    graphics.DrawString("Hello World", new Font("Courier", 10, FontStyle.Regular), new SolidBrush(Color.White), 1, 1);
}

Здесь есть 2 проблемы:

  1. Сгенерированное растровое изображение не является монохромным
  2. Сгенерированное растровое изображение имеет другой двоичный формат

Так что мне нужен способ:

  1. Создание монохромного растрового изображения в .NET
  2. Считывание отдельных цветов пикселей для каждого пикселя в растровом изображении

Я обнаружил, что вы можете установить глубину пикселя в 16, 24 или 32 бита, но не нашел монохромный, и я не знаю, как прочитать данные пикселей.

Предложения приветствуются.

ОБНОВЛЕНИЕ: Я не могу использовать Win32 PInvokes ... должен быть нейтральным на платформе!

СЛЕДУЙТЕ ЗА: Следующий код работает для меня сейчас. (На всякий случай, если это кому-нибудь нужно)

private static byte[] GetLedBytes(Bitmap bitmap)
{
    int threshold = 127;
    int index = 0;
    int dimensions = bitmap.Height * bitmap.Width;

    BitArray bits = new BitArray(dimensions);

    //Vertically
    for (int y = 0; y < bitmap.Height; y++)
    {
        //Horizontally
        for (int x = 0; x < bitmap.Width; x++)
        {
            Color c = bitmap.GetPixel(x, y);
            int luminance = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);
            bits[index] = (luminance > threshold);
            index++;
        }
    }

    byte[] data = new byte[dimensions / 8];
    bits.CopyTo(data, 0);
    return data;
}

Ответы [ 7 ]

6 голосов
/ 02 марта 2009

Я бы вычислил яркость каждого пикселя, а затем сравнил бы его с некоторым пороговым значением.

y=0.3*R+0.59G*G+0.11*B

Скажите, что пороговое значение равно 127:

const int threshold = 127;
Bitmap bm = { some source bitmap };

byte[,] buffer = new byte[64,256];

for(int y=0;y<bm.Height;y++)
{
  for(int x=0;x<bm.Width;x++)
  {
   Color c=source.GetPixel(x,y);
   int luminance = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11);
   buffer[x,y] = (luminance  > 127) ? 1 : 0;
  }
}
1 голос
/ 07 апреля 2010

спасибо за код выше - я пытаюсь преобразовать монохромное изображение в 2d массив, где 1-черный 0-белый, однако у меня возникли некоторые проблемы - я использовал ваш код для загрузки изображения 8x8 bmp вывод его содержимого в текстовое поле с помощью

myGrid =GetLedBytes(myBmp);
     for (int x = 1; x < 8; x++)
     {
         textBox1.Text = textBox1.Text + Convert.ToString(myGrid[x])+ "  ";
     }

однако я получаю это в результате в текстовом поле:

225  231  231  231  231  129  255  

как мне получить его, чтобы 0 и 1?

1 голос
/ 02 марта 2009

В растровом изображении есть метод GetPixel , который вы можете использовать. Это позволит вам рисовать растровое изображение, а затем конвертировать его в нужный вам формат.

Растровые изображения в формах Windows (т. Е. Доступные через Graphics.FromImage) имеют размер 24 бит / с (возможно, 32? Это слишком рано, и я, честно говоря, забыл). Тем не менее, GetPixel возвращает объект Color, поэтому битовая глубина растрового изображения не имеет значения. Я предлагаю вам написать свой код так:

MyBitmapFormat ToMyBitmap(Bitmap b)
{
    MyBitmapFormat mine = new MyBitmapFormat(b.Width, b.Height);

    for (int y=0; y < b.Height; y++) {
        for (int x=0; x < b.Width; x++) {
            mine.SetPixel(x, y, ColorIsBlackish(b.GetPixel(x, y)));
        }
    }
}

bool ColorIsBlackish(Color c)
{
    return Luminance(c) < 128; // 128 is midline
}

int Luminance(c)
{
    return (int)(0.299 * Color.Red + 0.587 * Color.Green + 0.114 * Color.Blue);
}

Этот процесс называется простым установлением порога. Это мозговой покой, но он будет работать как первый срез.

1 голос
/ 02 марта 2009

Вы можете попытаться указать формат пикселя в конструкторе:

var bitmap = new Bitmap(256, 64, PixelFormat.Format1bppIndexed);

Когда я рисовал монохромные растровые изображения на других платформах, у меня иногда было чтобы отключить сглаживание, иначе отображаемый текст не будет отображаться:

graphics.SmoothingMode=SmoothingMode.None;

YMMV.

1 голос
/ 02 марта 2009

Вы не должны использовать метод GetPixel вашего растрового изображения для преобразования всего растрового изображения из одного формата в другой! Это будет неэффективно. Вместо этого вы должны использовать метод LockBits , чтобы получить доступ к копии буфера изображения и преобразовать ее в нужный формат. Я не совсем уверен насчет преобразования его в монохромный, но в перечислении PixelFormat есть значение Format1bppIndexed, которое может вам помочь.

1 голос
/ 02 марта 2009

Я не знаю C #. Есть много способов сделать это. Вот простой способ.

  1. Создайте пустое черное растровое изображение размера, соответствующего требованиям вашего устройства. Нарисуйте на нем все, что вы хотите нарисовать, например, текст, цифры и т. Д.

  2. Теперь пороговое значение изображения, т.е. установите пиксель изображения ниже значения интенсивности на ноль, иначе установите его на. например установите все значения интенсивности> от 0 до 1.

  3. Теперь преобразуйте в формат, требуемый вашим устройством. Создайте байтовый массив размером (64 * 256) / 8. Установите соответствующие биты равными 1, где соответствующие значения пикселей в более раннем растровом изображении равны 1, в противном случае установите их равными 0.

Редактировать: Шаг 3. Используйте битовые операторы для установки битов.

0 голосов
/ 02 марта 2009

В этом разделе есть некоторый код, который создает моно растровое изображение. Интересует образец SaveImage.

...