микроконтроллеры от ведущих мировых производителей

Графические контроллеры FTDI FTx.

Анимация изображений. Часть 2.

Сергей Долгушин, dsa@efo.ru

 

Первую часть статьи мы закончили на примерах использования команд VERTEX для вывода растровых изображений на экран дисплея. Возможности графических контроллеров FTDI не ограничиваются этими простыми функциями. Одновременно с выводом изображения мы можем изменять его ширину, высоту и угол поворота. Вторую части статьи мы посвятим рассказу об этих функциях микросхем FT8xx.

При работе с растровыми изображениями графические контроллеры FT8xx используют набор из шести коэффициентов, которые задают параметры вывода изображения на экран. Этот набор коэффициентов называется матрицей трансформации. Он определяет  масштаб выводимого на экран изображения, угол его поворота и т.д. Мы можем менять все коэффициенты с помощью низкоуровневых команд BITMAP_TRANSFORM или высокоуровневых команд  CMD_TRANSLATE, CMD_SCALE и CMD_ROTATE. Любые изменения коэффициентов матрицы действуют в пределах дисплей-листа до тех пор, пока мы не изменим их вновь.

properties

Рис.1 Свойства изображения

 

При использовании команд, оказывающих влияние на коэффициенты трансформации, следует помнить, что все манипуляции с растровыми изображениями происходят в пределах физических размеров этих изображений. Поясним это на примере нашей картинки с надписью “C Новым годом”. В поле “Information”  (см. рис. 1) мы видим параметры нашего изображения, в данном случае нас интересуют ширина и высота: 240 х 147 пикселей соответственно. Именно эти параметры и являются границами, в рамках которых мы можем производить те или иные манипуляции с изображением. На рисунке 2 наше изображение (белый фон и надпись являются его составными частями) отображается на черном фоне. В рамках белого прямоугольника с размерами 240 х 147 пикселей будут происходить все видимые на экране изменения изображения. Т.е., например, изменяя масштаб изображения в 2 раза, мы не увеличиваем его в границах экрана дисплея, а только в границах исходного изображения.

 bitmap

Рис.2 Вывод растрового изображения 

 

Команда сдвига изображения CMD_TRANSLATE


Описание работы функций трансформации изображений начнем с команды CMD_TRANSLATE. В общем случае, эту команду можно считать вспомогательной. Она отвечает за смещение видимого изображения относительно координат, указанных в функции вывода изображения на экран VERTEX (см. рис.3). Такие смещения необходимы для изменения центральной точки, относительно которой будет происходить трансформация изображения. По умолчанию, все манипуляции с изображением привязаны к левому верхнему углу данного изображения, т.е. той точки, координаты которой мы задаем командой VERTEX.

translate

Рис.3 Смещение изображения на 120 пикселей вправо

 

Вызов команды смещения в Arduino осуществляется следующим образом: FTImpl.Cmd_Translate(x*65536,y*65536), где x и y – смещение по соответствующим координатам в пикселях. Проиллюстрируем работу команды в Screen Editor:

BEGIN(BITMAPS)

CMD_LOADIDENTITY()

CMD_TRANSLATE(120*65536, 0)

CMD_SETMATRIX()

VERTEX2II(123, 58, 0, 0)

END()

На рисунке 3 приведен результат выполнения данного кода в Screen Editor. Обратите внимание, что команда Vertex2II выводит изображение в тех же координатах, что и на рисунке 2. А видимое изображение сдвинуто на 120 пикселей в результате выполнения команды CMD_TRANSLATE. В данном коде мы видим две вспомогательные команды – CMD_LOADIDENTITY и CMD_SETMATRIX. Первая команда всегда предваряет вызов функций, изменяющих коэффициенты трансформации. Вторая команда дает указание графическому процессору использовать в работе с растровыми изображениями матрицу с новыми коэффициентами.

translate_02

Рис.4 Смена изображений на экране с помощью команды TRANSLATE

 

Кроме вспомогательных функций, команду CMD_TRANSLATE можно использовать для создания анимированных эффектов. Например, плавное чередование двух изображений на экране дисплея можно сделать следующим образом (см. рис.4). Добавим в проект второе изображение, оно должно быть такой же ширины и высоты, что и первое. Код программы будет выглядеть следующим образом:

void loop()
{     
        int16_t y=-240, x=0;
        FTImpl.DLStart();
        FTImpl.ClearColorRGB(0, 0, 0);
        FTImpl.DLEnd();
        FTImpl.Finish();            
        while (1)
      {
                FTImpl.DLStart();
                  FTImpl.Begin(FT_BITMAPS);
                FTImpl.Cmd_LoadIdentity(); // функция, указывающая граф. процессору, что далее будет происходить трансформация изображения
                FTImpl.Cmd_Translate(x*65536, 0);
                FTImpl.Cmd_SetMatrix(); //функция, которая указывает гр.процессору, что необходимо применить изменения к текущему изображению
                FTImpl.Vertex2ii(123, 58, 0, 0);
                FTImpl.End();
                FTImpl.Begin(FT_BITMAPS);
                FTImpl.Cmd_LoadIdentity();
                FTImpl.Cmd_Translate(y*65536, 0);
                FTImpl.Cmd_SetMatrix();
                FTImpl.Vertex2ii(123, 58, 1, 0);
                FTImpl.End();
                FTImpl.DLEnd();
                FTImpl.Finish();
        y++;
        x++;
        delay(25);
     
      if (x>240)
         {
                 y=0;
                x=-240;
         }
       if (y>240)
        {
                y=-240;
                x=0;
        }
      }       

 
Более практичным вариантом применения данного эффекта может быть реализация анимированного переключателя (см. рис.5).

switch

Рис.5 Реализация анимированного переключателя  

В данном случае смещение будет применяться к верхней картинке, нижняя будет неподвижна. На рисунке 5 под номерами 1 и 2 изображены исходные изображения двух состояний переключателя. Под номером 3 показано их положение друг  относительно друга в приложении, картинка под номером 2 будет смещаться относительно неподвижной картинки под номером 1. Код примера будет следующим:
void loop()
{       
        int16_t x=0;

 
FTImpl.DLStart();
FTImpl.ClearColorRGB(254, 254, 254);
FTImpl.Clear(1, 1, 1);
FTImpl.DLEnd();
FTImpl.Finish();    

 
                while (1)
      {
        FTImpl.DLStart();
        FTImpl.ClearColorRGB(254, 254, 254);
        FTImpl.Clear(1, 1, 1);
       
        FTImpl.Begin(FT_BITMAPS);
        FTImpl.Vertex2ii(162, 104, 0, 0); // вывод неподвижного элемента (рис.5, 1)
        FTImpl.End();
       
        FTImpl.Begin(FT_BITMAPS);
        FTImpl.Cmd_LoadIdentity();
        FTImpl.Cmd_Translate(x*65536, 0);
        FTImpl.Cmd_SetMatrix();
        FTImpl.Vertex2ii(162, 104, 1, 0); // вывод подвижного элемента (рис.5, 2)
        FTImpl.End();
               
        FTImpl.DLEnd();
        FTImpl.Finish();
         
        x++;
        delay(10);
        if (x>110)
        {
         x=0;
         delay(2000);
        }
      }       
}

 

 

Команда изменения масштаба изображения CMD_SCALE

 

Следующей рассмотрим функцию CMD_SCALE, предназначенную для изменения масштаба изображения. Ее вызов осуществляется следующим образом: FTImpl.Cmd_Scale(sx*65536, sy*65536); где sx и sy – коэффициенты трансформации изображения по ширине и высоте.       

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

scale_01 scale_02 scale_03

Рис.6 Результат выполнения функции CMD_SCALE

 

В качестве примера работы используем предыдущий код со сменой картинок на экране дисплея. В тексте программы заменим функцию CMD_TRANSLATE на CMD_SCALE:

void loop()
{       
        float x=0;

 
        FTImpl.DLStart();
        FTImpl.ClearColorRGB(254, 254, 254);
        FTImpl.Clear(1, 1, 1);
        FTImpl.DLEnd();
        FTImpl.Finish();            

 
while (1)
      {
        while (x<1)
        {
                 FTImpl.DLStart();
                FTImpl.ClearColorRGB(254, 254, 254);
                FTImpl.Clear(1, 1, 1);
                FTImpl.Begin(FT_BITMAPS);
                FTImpl.Cmd_LoadIdentity();
                FTImpl.Cmd_Scale(x*65536, x*65536); // изменение коэффициентов трансформации
                FTImpl.Cmd_SetMatrix();
                FTImpl.Vertex2ii(240-((240*x)/2), 136-((136*x)/2), 1, 0); // расчет новых координат
                FTImpl.End();
                FTImpl.DLEnd();
                FTImpl.Finish();
       
                 x=x+0.01; // увеличиваем масштаб
                 delay(25);
        }
                
        while (x>0)
        {
                 FTImpl.DLStart();
                FTImpl.ClearColorRGB(254, 254, 254);
                FTImpl.Clear(1, 1, 1);
                FTImpl.Begin(FT_BITMAPS);
                FTImpl.Cmd_LoadIdentity();
                FTImpl.Cmd_Scale(x*65536, x*65536);
                FTImpl.Cmd_SetMatrix();
                FTImpl.Vertex2ii(240-((240*x)/2), 136-((136*x)/2), 0, 0);
                FTImpl.End();
               
               
                FTImpl.DLEnd();
                FTImpl.Finish();
                 x=x-0.01; // уменьшаем масштаб
                 delay(25);
        }
      }       
}

 

Расчет координат в функции вывода изображения VERTEX необходим, если мы хотим изменять масштаб изображения относительно центра картинки. По умолчанию, все функции трансформации изображений рассчитываются относительно верхнего левого угла изображения.

Вращение изображения – команда CMD_ROTATE

 


Для вращения изображения служит специальная команда CMD_ROTATE. Вращение изображения осуществляется вокруг верхнего левого угла этого изображения. Вызов функции в Arduino следующий: FTImpl.Cmd_Rotate(x), где x = 1/65536 круга, т.е. при угле поворота изображения на 3600 х = 65536.

Использование функции поворота при работе с растровыми изображениями имеет существенные ограничения, связанные с тем, что трансформация изображения происходит в границах этого изображения. На рисунке 7 показан поворот изображения на 150 относительно верхнего левого угла.

rotate

Рис.7 Поворот изображения на 150

Если предполагается использовать вращение изображения, то размеры исходной картинки и ее наполнение надо редактировать с учетом данных особенностей. Либо изначально увеличиваем размеры исходной картинки, а перед использованием команды вращения уменьшаем ее масштаб командой CMD_SCALE. Второй способ продемонстрируем на следующем примере:

 void loop()
{       
        float x=0;

 
        FTImpl.DLStart();
        FTImpl.ClearColorRGB(254, 254, 254);
        FTImpl.Clear(1, 1, 1);
        FTImpl.DLEnd();
        FTImpl.Finish();            

 
while (1)
      {
        while (x<360)
        {
        FTImpl.DLStart();
        FTImpl.ClearColorRGB(254, 254, 254);
        FTImpl.Clear(1, 1, 1);
        FTImpl.Begin(FT_BITMAPS);
        FTImpl.Cmd_LoadIdentity();
        //*************************************
        FTImpl.Cmd_Translate(120*65536, 73*65536);
        FTImpl.Cmd_Scale(32000, 32000);
        FTImpl.Cmd_Rotate(x*65536/360);
        FTImpl.Cmd_Translate(-120*65536, -73*65536);
        //*************************************
        FTImpl.Cmd_SetMatrix();
        FTImpl.Vertex2ii(120, 70,0, 0);
        FTImpl.End();
               
        FTImpl.DLEnd();
        FTImpl.Finish();
       
        x=x+4;
        delay(25);
        }
        x=0;
      }       
}

 

В результате выполнения данного кода на экране дисплея наша картинка будет равномерно вращаться вокруг своего центра. За реализацию этого вращения отвечают функции, которые мы выделили в тексте программы звездочками. Функция FTImpl.Cmd_Translate(120*65536, 73*65536) смещает верхний левый угол отображаемого изображения в центр области, выделенной под это изображение на экране дисплея. На рисунке 8 показан результат выполнения этой команды и последующий поворот на 300

rotate_02

Рис.8 Результат последовательного выполнения функция CMD_TRANSLATE и CMD_ROTATE

 

Красная метка отображает координаты точки, относительно которой на экран выводится картинка командой VERTEX.

Затем мы уменьшаем изображение командой CMD_SCALE таким образом, чтобы уменьшенная копия полностью умещалась внутри границ первоначального изображения при любых углах поворота. В нашем примере мы уменьшили изображение чуть больше, чем в 2 раза. Применяем команду поворота CMD_ROTATE и осуществляем обратный сдвиг видимого изображения командой CMD_TRANSLATE. На рисунке 9 показана последовательность состояний изображения.

rotate_03

Рис.9 Выполнение функций CMD_TRANSLATE и CMD_ROTATE

 

Сиреневая область – это наша исходная картинка. Фиолетовая область – это изображение после выполнения команд CMD_TRANSLATE(x, y) и поворота на 900 командой CMD_TARNSLATE. Видимое изображение на экране – это перекрывающиеся области сиреневого и фиолетового цветов. Зеленая область – это изображение после выполнения команды CMD_TRANSLATE(-x, -y). Видимое изображение на экране – это перекрывающиеся области сиреневого и зеленого цветов.          

На этом мы заканчиваем вторую часть статьи, посвященной анимационным эффектам. В продолжение темы работы с командами трансформации растровых изображений рекомендуем познакомиться с фирменным примером AN 285 “FT800 Demo Application - Logo Animation”, который доступен в виде скетча Arduino.

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

 

Архив с примерами, описанными в данной части