Считывание цветов пикселей монохромного растрового изображения
Вопрос
Я не знаю лучшего названия, но я опишу проблему.
Используемое нами оборудование обладает способностью отображать изображения.Он может отображать черно-белое изображение с разрешением 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 проблемы:
- Сгенерированное растровое изображение не является монохромным
- Сгенерированное растровое изображение имеет другой двоичный формат
Поэтому мне нужен способ:
- Создайте монохромное растровое изображение в .NET
- Считайте отдельные цвета пикселей для каждого пикселя в растровом изображении
Я обнаружил, что вы можете установить глубину пикселя равной 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 #.Возможно, есть много способов сделать это.Вот простой способ.
Создайте пустое черное растровое изображение размером, соответствующим требованиям вашего устройства.Нарисуйте на нем все, что вы хотите нарисовать, например текст, цифры и т.д.
Теперь пороговое значение изображения, т. е.установите пиксель изображения ниже значения интенсивности равным нулю, иначе установите его равным.например ,установите все значения интенсивности от 0 до 1.
Теперь конвертируйте в формат, требуемый вашим устройством.Создайте массив байт размером (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?
Этот парень содержит некоторый код, который создает монотонное растровое изображение.Интерес представляет образец сохраненного изображения.