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

StackOverflow https://stackoverflow.com/questions/601963

Вопрос

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

Используемое нами оборудование обладает способностью отображать изображения.Он может отображать черно-белое изображение с разрешением 64 x 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;
}
Это было полезно?

Решение

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

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;
  }
}

Другие советы

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

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

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

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

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

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

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

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

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

graphics.SmoothingMode=SmoothingMode.None;

ИММВ.

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

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

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);
}

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

спасибо за приведенный выше код - я пытаюсь преобразовать монохромное изображение в 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?

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top