2009-03-02 4 views
3

Я не знаю лучшего названия, но я опишу проблему.Чтение монохромных цветов растровых изображений

Аппаратное обеспечение, которое мы используем, имеет возможность отображения изображений. Он может отображать черно-белое изображение с разрешением 64 x 256.

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

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

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

и изображение будет выглядеть следующим образом:

Bitmap 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 бит, но не нашли монохромный, и я понятия не имею, как читать данные пикселя.

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

UPDATE: Я не могу использовать Win32 PInvokes ... должен быть нейтральным платформой!

FOLLOW UP: Следующий код работает для меня сейчас. (Только в случае, если кто-нибудь это нужно)

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

ответ

6

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

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

Say пороговое значение 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

Точка для этого! Но если вы используете Bitmap.LockBits вместо Bitmap.GetPixel, вы получаете превосходную производительность! –

+0

Thnx! С небольшими корректировками этот код работает как шарм :-) – TimothyP

+0

danbystrom: Вы правы, хотели, чтобы код образца был чистым и без указателей. – arul

0

This chap имеет некоторый код, который создает моно растрового изображения. Образец SaveImage является интересным.

+0

Ссылка мертва – danmiser

1

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

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

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

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

Edit: Шаг 3. С помощью Битовые операторы, чтобы установить биты.

+0

Проблема в том, что я понятия не имею, как читать значения пикселей растрового изображения – TimothyP

+0

Ну, вам нужно проверить API. Должен быть такой метод, как getPixel(), getIntensity() или, может быть, даже простая ссылка на массив. – Xolve

1

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

1

Вы можете попробовать поставить PixelFormat в конструкторе:

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

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

graphics.SmoothingMode=SmoothingMode.None; 

YMMV.

+0

Вы не можете вызвать Graphics.FromImage на что-нибудь меньшее, чем 32bpp – plinth

1

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

Растровые изображения в формах 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); 
} 

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

1

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

+0

Если вы используете pixel.GetColor, вы можете получить значения R G B из пикселя вправо? Поэтому, поскольку вы делаете черно-белое все, что вам нужно сделать, это проверить R G a B == 0, что означает черный. Все остальные коды не нужны. – TimothyP

Смежные вопросы