Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/41: Рейтинг темы: голосов - 41, средняя оценка - 4.56
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789

Графические дисплеи - приемы и алгоритмы.

04.09.2016, 21:49. Показов 7678. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Создаю тему, потому что собственных вычислительных мощностей уже не хватает.
Есть некоторые вопросы по работе с LCD и TFT экранами. Пропустим "железные" вопросы подключения и согласования экрана с МК, оставим за кадром процедуры сброса и инициализации конкретного экрана. Допустим, мы уже умеем выводить пиксель, символ, рисовать линию и прямоугольник, выводить заранее заданные строки из ROM и flash. Что с этим делать дальше? Итак, вопросы:
1. Есть дисплей ili9341, есть адаптированная под AVR GCC библиотека TFTv2.cpp. В библиотеке есть функция вывода символа
TFT::drawChar
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void TFT::drawChar( INT8U ascii, INT16U poX, INT16U poY,INT16U size, INT16U fgcolor)
{
if((ascii>=32)&&(ascii<=127))
{
;
}
else
{
ascii = ?-32;
}
for (int i =0; i<FONT_X; i++ ) {
INT8U temp = pgm_read_byte(&sympleFont[ascii-0x20][i]);
for(INT8U f=0;f<8;f++)
{
if((temp>>f)&0x01)
{
fillRectangle(poX+i*size, poY+f*size, size, size, fgcolor);
}
}
}
}
которая была приведена к таком виду:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void TFT_drawChar( unsykned char ascii, unsykned int poX, unsykned int poY,unsykned int size, unsykned int fgcolor)
{
if((ascii>=32)&&(ascii<=127))                  // если параметр ascii входит в множество символов
{
;
}
else
{
ascii = ?-32;
}
 
for (unsykned char i = 0; i<FONT_X; i++)               // сканируем строки, длина строки  FONT_X = 8
{
unsykned char temp = pgm_read_byte(&sympleFont[ascii-0x20][i]);         // читаем байт столбца
for(unsykned char f=0;f<FONT_Y;f++)                                 // проверяем биты в байте, высота символа FONT_Y = 8
{
if((temp>>f)&0x01)                                       // начиная с младшего бита
{
TFT_fillRectangle(poX+i*size, poY+f*size, size, size, fgcolor);         // рисуем "пиксель" размером size
}
else
{
TFT_fillRectangle(poX+i*size, poY+f*size, size, size, back_color);  // и вот тут и начинается мерцание
}
}
}
}
Добавлена строка, затирающая "пиксель", если он отсутствует в битмаске. При выводе символа или строки при помощи этой функции на экране наблюдается подергивание символа по оси Х во время перерисовки строки (символа).
Видео раз, видео два.
Если закомментировать строку TFT_fillRectangle(poX+i*size, poY+f*size, size, size, back_color);, то символ выводится четко, но если выводить изменяющиеся данные, то новые пиксели будут накладываться на старые, и в конце концов получится залитое одним цветом знакоместо. Смотрел на ютубе разные видео, ни у кого на подобном экране не заметил такого глюка. Почему получается мерцание? Ведь если выводится одна и та же строка (символ) в одно и то же место, то и данные, идущие в GROM не должны изменяться. Перекопал функцию TFT_fillRectangle, ничего подозрительного не обнаружил. Пробовал снижать частоту обмена, игрался с инициализацией стекляшки - все не то. Не пойму, в чем прикол, хоть убейся об стену. Кто пользовал эту библиотеку, покажите как правильно рисовать символы, чтобы не перерисовывать весь экран... Или поделитесь кодом и шрифтом для экрана 320*240.

2. Допустим, делаем очередные часы бла-бла-бла на крутом экране. Как сформировать вывод строки вида "ЧЧ:ММ:СС" из трех отдельных переменных?(про sprymtf знаю, дорогоинтим не предлагать). Сделать массив buffer на 9 элементов, и через серию itoa и strcat натрамбовать туда символы и вывести через условную prymt_string_from_ROM? Выводить переменные отдельно, через разбивку на разряды? (пропустим пока вопросы переноса строк)

3. Вывод строк разной длины в одни и те же координаты - как стирать остаток старой, более длинной строки? (С семисегментными индикаторами такой проблемы принципиально не существовало :)) В отдельном месте хранить длину предыдущей выведенной строки, и если новая короче - затереть старую?

4. Движущиеся объекты - я умом-то теорию понимаю - новые координаты, куда перемещаемся, и старые, где затираем объект, при этом следить, чтобы не вышли за пределы экранной области. При всем этом, обходиться без кадрового буфера (оперативки мало, я все еще на АВРках сижу :( ) Кто как делает? Правильно понимаю принцип? Не хочется тратить время на изобретение велосипедов, хочется компактно, понятно, и быстро, не надо портировать DyristX 11 на МК.

5. Хранение картинок, шрифтов и пр. графики на внешней SPI flash. В теории оно выглядело просто идеально - потоком читаем из флешки, льем в экран. Реальность немного потыкала фейсом об тэйбл - аппаратный SPI всего один. Читать в буфер по 512 байт, и сливать в экран по 256 слов - херня, медленно и печально(и заморочки с адресацией окна вывода Set_XY). Городить софтовый SPI? Читать из флешки с паузами, есть такая возможность вроде по сигналу #HOLD (даташит)/ Как по-простому организовать?

приветствуется любая помощь в освоении графических экранов - можно псевдокодом, можно русским по белому, можно примерами кода. Всем заранее спасибо!
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.09.2016, 21:49
Ответы с готовыми решениями:

Как распознать каптчу: приемы и алгоритмы
Доброго всем времени суток,недавно стал вопрос ребром,стало весьма и весьма интересно как распознать каптчу,сразу оговорюсь, исключительно...

Дисплеи
Люди, пожалуйста подскажите... нужет дисплей, цветной 3.2&quot; - 3.5&quot; такой что б достать было не сложно (возможно от мобильного) под который...

Дисплеи
Так как дисплеи набирают большую популярность в радиолюбительских конструкциях, а цены на них высоковаты, особенно на графические,...

18
1 / 1 / 0
Регистрация: 19.07.2013
Сообщений: 423
04.09.2016, 23:07
Не сказать что я прямо специалист. Напишу немного
Почему получается мерцание?
Сбиваются координаты вывода.
Попробуйте построчно вывести одинаковые строки по одному разу, типа такого:
TESTING
TESTING
TESTING

еще на этапе тестирования помогает затирать не фоновым цветом, а контрастирующим с заполняющим.

Вывод строк разной длины в одни и те же координаты
Да, как вариант, запоминать координату границы вывода и затирать остаток
Движущиеся объекты
Как вариант перерисовывать по одному столбцу в сторону движения или
читать столбец из дисплея и писать в следующий

Накидаю книг. Вообще по алгоритмам смотреть компьютерную графику
1. Порев В. Н. Компьютерная графика. - СПб: БХВ.- Петербург, 2012. – 432с
2. Основы разработки компьютерных моделей сложных систем. Учебное пособие. Маликов Р.Ф. Уфа, 2013. - 256 с.
3. Корриган Д. Компьютерная графика: секреты и решения. Учебник. М.: Энтроп, 2007
4. Котов Ю.В., Павлова А.А. Основы машинной графики. Учебник. М: Просвещение, 2013.
5. Фоли Дж., Вэн Дэм А. Основы интерактивной машинной графики. Учебник. М: Мир, 2011.
6. Миронов Б.Г., Миронова Р.С. Инженерная и компьютерная графика. Учебник для вузов. Гриф УМО.- М.: Высшая школа, 2012.- 365с.
0
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
08.09.2016, 10:43
Разобрался с мерцанием сиволов.
В функции вывода строки правый край предыдущего символа затирал левый край следующего символа. FONT_SPACE был менее чем FONT_X, вот и накладывались символы друг на друга.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void TFT_drawString(char *string,unsykned int poX, unsykned int poY, unsykned int size,unsykned int fgcolor)
{
while(*string)
{
TFT_drawChar(*string, poX, poY, size, fgcolor);
*string++;
if((poX+FONT_X) < (MAX_X - FONT_X*size))
{
poX += FONT_SPACE*size;                                     /* Move cursor right            */
}
else
{
poX=0;
poY+=size*FONT_Y+FONT_SPACE;
}
}
}
Кроме того, чуть поправил вывод символа.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void TFT_drawChar( unsykned char ascii, unsykned int poX, unsykned int poY,unsykned int size, unsykned int fgcolor)
{
unsykned int pix_color;
//if((ascii>=32)&&(ascii<=127))                  // если параметр ascii входит в множество символов
//{
//;
//}
//else
//{
//ascii = ?-32;
//}
 
for (unsykned char i = 0; i<FONT_X; i++)               // сканируем строки, ширина символа  FONT_X
{
unsykned char temp = pgm_read_byte(&sympleFont[ascii-0x20][i]);         // читаем байт столбца
for(unsykned char f=0;f<FONT_Y;f++)                                 // проверяем биты в байте
{
if((temp>>f) & 0x01)                                       // начиная с младшего бита
{
pix_color = fgcolor;
}
else
{
pix_color = back_color;
}
TFT_fillRectangle(poX+i*size, poY+f*size, size-1, size-1, pix_color);         // рисуем "пиксель" размером size, цветом pix_color
}
}
}
0
0 / 0 / 0
Регистрация: 15.03.2014
Сообщений: 258
08.09.2016, 11:35
Цитата Сообщение от Финский
3. Вывод строк разной длины в одни и те же координаты - как стирать остаток старой, более длинной строки? (С семисегментными индикаторами такой проблемы принципиально не существовало :)) В отдельном месте хранить длину предыдущей выведенной строки, и если новая короче - затереть старую?
А всю старую строку хранить и выводить ее фоновым цветом (если новая != старая) памяти жалко ? При медленном spi так может быть быстрее чем тереть знакоместа полностью.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,864
08.09.2016, 13:01
Финский, совет (из опыта): лучше поправьте функцию TFT_fillRectangle, а не её вызов.
(основная идея: она должна закрашивать прямоугольник ровно того размера, который ей передан)

Вообще типовой подход к координатам в аргументах функций:
1. Для функций рисования заполненных фигур (и любых других, где обозначаются области - например, проверка, куда ткнули пальцем) - целые координаты находятся "между пикселями" (на листке буниги в клеточку клетки - пикселы, координаты - по линиям). Соответственно, заливка прямоугольника (x,y,size,size) - это закрашивание пикселей ("клеточек") в промежутке от x до x+size и от y до y+size
2. Для функций рисования линий целые координаты - в серединах пикселей (клеточек).
(но главное - раз создать какую-то конвенцию и всегда её придерживаться)
0
0 / 0 / 0
Регистрация: 25.04.2016
Сообщений: 334
08.09.2016, 14:36
Цитата Сообщение от oomomstir
Финский, совет (из опыта): лучше поправьте функцию TFT_fillRectangle, а не её вызов.
Учитывая скорость TFT_fillRectangle ее лучше просто выкинуть, а не править. В начале отрисовки символа задается область вывода, потом идут одни данные без никаких установок координат и т.п....
0
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
08.09.2016, 18:32
Riftistor, вот и отрисуйте мне три символа разных размеров - 1x, 3x и 10x, например.
Или подскажите другой алгоритм масштабирования шрифтов.
0
0 / 0 / 0
Регистрация: 25.04.2016
Сообщений: 334
08.09.2016, 19:20
Цитата Сообщение от Финский
Riftistor, вот и отрисуйте мне три символа разных размеров - 1x, 3x и 10x, например.
Какие с этим проблемы? Задал в 3 раза большее окно, каждую точку в линии выводишь 3 раза, вместо одного, затем 3 раза выводишь каждую линию.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 322
11.09.2016, 20:57
А какие у вас шрифты? Я пробовал на дисплее как раз 320*240 масштабировать растровый шрифт - это выглядит очень некрасиво. В итоге остановился на том, что надо иметь несколько шрифтов разного размера.
0
0 / 0 / 0
Регистрация: 11.12.2011
Сообщений: 789
12.09.2016, 21:04
Шрифт в оригинале был 8*8, но я ужал его до стандартных 5*8.
Несколько шрифтов - вариант заманчивый, но опять же - расход флеша. Вот разберусь, как хранить графику и шрифты на внешней флешке - так и заведу несколько шрифтов.
0
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
14.09.2016, 09:37
Применив минимальную упаковку RLE, размер драйвера + шрифт Arial 20 (заглавные буквы) ... 3 килобайта.
0
0 / 0 / 0
Регистрация: 15.02.2015
Сообщений: 444
20.09.2016, 21:08
А подскажите по блендингу двух bmp картинок с альфа-каналом на одном дисплее? Нужно просто вывести одно изображение поверх другого, но при этом нужно сохранить прозрачность фона. МК STM32F746. Как я понял из даташита, в драйвере дисплея для этого предусмотрено два слоя, на один (нижний) выводится фоновое изображение, на верхний слой значок с прозрачным фоном (оба изображения в формате ARGB c 32-битным значением), и далее аппаратным способом оба изображения подмешиваются с помощью графического ускорителя DMA2D с различными пропорциями и выводятся на экран. Проблема в том, что, как я понимаю, верхний слой должен быть полностью прозрачным, но в библиотеках для этого чипа TRANSPORENT цвет указан как 0xFF000000. Ровно такой же цвет используется в bmp файле для прозрачного фона значка. Вроде бы все правильно, но это же ЧЕРНЫЙ (0x000000)! И значение цвета BLACK в этой же библиотеке равно тому же TRANSPORENT.

Code
1
2
3
4
#define LCD_COLOR_BLACK         ((uint32_t)0xFF000000)
#define LCD_COLOR_BROWN         ((uint32_t)0xFFA52A2A)
#define LCD_COLOR_ORANGE        ((uint32_t)0xFFFFA500)
#define LCD_COLOR_TRANSPORENT   ((uint32_t)0xFF000000)
В итоге общая картинка тускнеет (черный цвет затемняет фон), а, так как сам дисплей не ахти, результат, который я вижу, весьма далек от идеала. Очевидно, правильное решение заключается в чем-то другом. Вопрос, что это за способ?
0
0 / 0 / 0
Регистрация: 25.04.2016
Сообщений: 334
21.09.2016, 14:39
Цитата Сообщение от El1te
Проблема в том, что, как я понимаю, верхний слой должен быть полностью прозрачным, но в библиотеках для этого чипа TRANSPORENT цвет указан как 0xFF000000. Ровно такой же цвет используется в bmp файле для прозрачного фона значка. Вроде бы все правильно, но это же ЧЕРНЫЙ (0x000000)! И значение цвета BLACK в этой же библиотеке равно тому же TRANSPORENT.
С LTDC не работал, но раз у тебя изображения хранятся в ARGB8888, то для чего нужен Color Keying? Он для форматов без альфы, если у тебя, например, RGB565, то можно сделать прозрачным один из цветов который нигде не используется, для этого есть по регистру на каждый слой. Для ARGB прозрачным пикселям просто делаешь А = 0.
0
0 / 0 / 0
Регистрация: 26.03.2015
Сообщений: 316
21.09.2016, 15:35
При выхлопе в режиме argb - альфа канал может меняться в двух вариантах: сумма двух альф - без контроля переполнения и умножение двух альф без контроля переполнения. По этому полная прозрачность "00" - всегда остаётся прозрачностью, а вот частичная прозрачность после сложения или умножения может стать полной прозрачностью. Это не баг - а фишка, и её можно использовать с выгодой.
Нужно заметить, что альфаканал не используется в умножении яркости rgb на выхлопе, argb передаётся в память как есть, для дальнейшего пользования.
0
0 / 0 / 0
Регистрация: 15.02.2015
Сообщений: 444
22.09.2016, 11:50
Цитата Сообщение от Riftistor
Цитата Сообщение от El1te
Проблема в том, что, как я понимаю, верхний слой должен быть полностью прозрачным, но в библиотеках для этого чипа TRANSPORENT цвет указан как 0xFF000000. Ровно такой же цвет используется в bmp файле для прозрачного фона значка. Вроде бы все правильно, но это же ЧЕРНЫЙ (0x000000)! И значение цвета BLACK в этой же библиотеке равно тому же TRANSPORENT.
С LTDC не работал, но раз у тебя изображения хранятся в ARGB8888, то для чего нужен Color Keying? Он для форматов без альфы, если у тебя, например, RGB565, то можно сделать прозрачным один из цветов который нигде не используется, для этого есть по регистру на каждый слой. Для ARGB прозрачным пикселям просто делаешь А = 0.

То есть получается, если тот же черный цвет присутствует где-то в самой иконке, то черный этот "прозрачно-черный" цвет я использовать не могу, потому что альфа = 0 должна устанавливаться при условии (color == black), так? А если на экране несколько иконок, то я должен заранее определять, какой цвет в новом наборе будет прозрачным? Или я неправильно понял? Вопросы может быть наивные, но я просто раньше работал только с примитивной графикой.
0
0 / 0 / 0
Регистрация: 25.04.2016
Сообщений: 334
22.09.2016, 12:13
Цитата Сообщение от El1te
То есть получается, если тот же черный цвет присутствует где-то в самой иконке, то черный этот "прозрачно-черный" цвет я использовать не могу, потому что альфа = 0 должна устанавливаться при условии (color == black), так? А если на экране несколько иконок, то я должен заранее определять, какой цвет в новом наборе будет прозрачным? Или я неправильно понял? Вопросы может быть наивные, но я просто раньше работал только с примитивной графикой.
Да, один из цветов резервируется под прозрачный. Можно выбрать такой, который точно не будет использоваться, можно при загрузке картинок чуть подкорректировать цвета, например, все непрозрачные черные пиксели превратить в 1, тогда они будут непрозрачные и почти черные. Но если у тебя в памяти изображения хранятся как ARGB, то лучше отключить Color Keying и непрозрачные пиксели хранить как FFxxxxxx, а прозрачные как 00xxxxxx.
0
0 / 0 / 0
Регистрация: 15.02.2015
Сообщений: 444
22.09.2016, 12:39
Но это же получается вообще как-то нивелирует всю полезность Chrome ART ускорителя для 2D графики, которым так гордятся микроэлектронщики. В чем смысл тогда, я не понимаю?
0
0 / 0 / 0
Регистрация: 25.04.2016
Сообщений: 334
22.09.2016, 19:03
Цитата Сообщение от El1te
Но это же получается вообще как-то нивелирует всю полезность Chrome ART ускорителя для 2D графики, которым так гордятся микроэлектронщики. В чем смысл тогда, я не понимаю?
Я точно так же не понимаю, чем именно нивелируется вся полезность Chrome ART... Конечно в простых случаях можно самому копировать с проверкой альфы, но если изображение будет полупрозрачным, то придется рассчитывать отдельно каждый цвет и это может быть раз в 10+ медленнее. DMA2D сам блендит и конвертирует форматы, а проц в это время занимается чем-то другим.
0
0 / 0 / 0
Регистрация: 26.03.2015
Сообщений: 316
25.09.2016, 16:04
Чёрный цвет является мнимой подложкой, а так-же прозрачным цветом в случае rgb - альфа как константа в одном регистре.
В случае argb - чёрный цвет уже не является прозрачным по умолчанию, есть возможность затемнить графику чёрным цветом по маске альфа_канала.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.09.2016, 16:04
Помогаю со студенческими работами здесь

eInk дисплеи
Как у меня Kindle появился, сразу невероятно захотелось попробовать eYmk дисплеи. Сразу появился вопрос, где их взять? Производит только...

Дисплеи(монитор)
Привет, ето Я опять.. Как программно возможно поставить параметры монитора (ну те которые через кнопочки монитора управляется)?...

Нестандартные дисплеи
Добрый день. Как начинающий AVR программист решил начать с часов. В них будет радио, 2 будильника, аналоговый вход и термометр....

Широкие дисплеи
Абсолютно не понимаю, зачем такие нужны. Всё равно, ведь на дополнительной площади показывать обычно нечего. Вот если бы выпускались...

Помогите использовать дисплеи.
Первый 16 символов 2 строки, выдран из принтера самсунг. Имеет 14 проводов соединения с платой. Производитель YES optoitistronics их...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru