Графика (работа с изображениями)

Конечно проще простого использовать метод рисования прямо на текущую видеостраницу, однако это не всегда удобно. К примеру у вас в игре 50 различных персонажей. С таким подходом при рисовании этих персонажей помимо фона игры и прочих мелочей будет затрачиваться уйма времени, да и само программирование превратится в адский труд. Гораздо проще занести каждого персонажа в отдельный буфер, и в нужный момент выводить готовый рисунок на экран. Согласитесь , что удобнее один раз с ведром сходить до колодца , чем 50 раз бегать туда с кружкой.
Для того чтобы создать изображение в буфере, очень удобно воспользоваться функцией ImageCreate.

Ее синтаксис:

buffer = ImageCreate( width, height [, [ color ][, depth ]] )

  • width - Ширина создаваемого изображения
  • height - Высота создаваемого изображения
  • color - Цвет , которым будет заполнено изображение при создании. По умолчанию если не использовать этот параметр, то для режимов экрана с цветностью меньше 24, этот параметр равен нулю (черный), для 24 и больше этот параметр равен &hFF00FF (розовый).
  • depth - Глубина цвета создаваемого изображения. При выводе этого изображения на экран, глубина цвета изображения и глубина цвета экрана должны совпадать! Если не использовать этот параметр, то определяется автоматически по глубине цвета экрана.

Пример (для экрана с глубиной цвета 8):

Screen 13
Dim img As Any Ptr = Imagecreate(50,50,15,8)
Line img,(1,1)-(50,50),12
Put  (0,0),img
Sleep
Imagedestroy(img)

Пример (для экрана с глубиной цвета 32):

Screen 14,32
Dim img As Any Ptr = Imagecreate(50,50,&hFFFFFF)
Line img,(1,1)-(50,50),&hFF0000
Put  (0,0),img
Sleep
Imagedestroy(img)


Оба примера рисуют одно и тоже, только в первом функция ImageCreate создает изображения с глубиной цвета 8, а во втором с глубиной 32.
Мы создали изображение с размерами 50х50 , и заполнили его белым цветом. Возвращаемое значение функции (указатель на буфер), мы присвоили своей переменной img.  Далее нарисовали в этом буфере линию. Обратите внимание, когда раньше мы рисовали с помощью Line , мы не использовали параметр буфер, а выводили все на текущую видеостраницу.
Теперь когда рисунок готов , мы можем использовать указатель на него, чтобы выводить в любое время наш рисунок на экран с помощью функции PUT. Синтаксис функции Put мы рассмотрим чуть ниже, а теперь давайте чуточку изменим наш код, чтобы рисунок стал анимированным:

Screen 14,32
Dim img As Any Ptr = Imagecreate(50,50,&hFFFFFF)
Line img,(1,1)-(50,50),&hFF0000
For a As Integer=0 To 150
    Cls
    Put  (a,100),img
    Sleep(10)
Next
Sleep
Imagedestroy(img)


Ничего сложного: выводим рисунок в цикле в меняющихся координатах по оси Х. И для того, чтобы наш рисунок не превратился в кашу, очищаем экран перед каждым рисованием с помощью CLS.

А теперь синтаксис функции PUT:

Put  target,  STEP ( x , y ), source , ( x1 , y1 ) - STEP ( x2 , y2 ) , method  , param

У функции только три обязательных параметра:  x , y , source

  • target - буфер, используется для получения при копировании всего буфера или определенной части из параметра source .
  • STEP - используется при относительных координатах от последнего рисования
  • x,y - координаты вывода изображения или если используется параметр target начальные координаты части копируемого рисунка.
  • source - буфер изображения
  • x1,y1 - начальные координаты для рисования рисунка в буфере target. Если не используется, то рисуется от координат 0,0. Параметр может использоваться только при использовании параметра target
  • STEP - используется при относительных координатах от координат x1, y1.Параметр может использоваться только при использовании параметра target
  • x2,y2 -  конечные координаты для рисования рисунка в буфере target Если не используется, то рисуется до конечных координат рисунка. Параметр может использоваться только при использовании параметра target
  • method - Один из методов рисования:
    • Фон-независимые методы (Не используются при копировании в буфер target):
      • Pset - Копируются все пикселы
      • PReset - Копируются все пикселы с инвертированием
      • Trans - Копируются все пикселы, кроме пикселей прозрачного цвета.
    • Фон-зависимые методы:
      • And - Смешивание пикселей по битовому методу And
      • Or -  Смешивание пикселей по битовому методу Or
      • Xor -  Смешивание пикселей по битовому методу Xor
      • Alpha -  Смешивание пикселей с прозрачностью
      • Add - Метод добавления пикселей к прозрачным участкам.
      • Custom - пользовательский метод, используемый со своей процедурой, в которой преобразуются пикселы
  • param - параметр, может использоваться как:
    • дополнительный параметр для своей процедуры с методом Custom
    • дополнительный параметр для методов Add и Alpha , определяющий интенсивность в диапазоне 0-255.

Я не смогу на словах передать отображаемые пикселы при различных методах рисования. Это вам нужно увидеть самим. Пример из справки по функции PUT очень хорошо это показывает.

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

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

Синтаксис GET:

Get [source,] [Step] (x1, y1) - [STEP] (x2, y2), dest]

  • source - буфер изображения, из которого возможно копирование в буфер dest
  • Step - используется при относительных координатах от последнего рисования
  • x1, y1 - координаты левого верхнего угла копируемого участка
  • Step - используется при относительных координатах от координат x1, y1
  • x2, y2 - координаты правого нижнего угла копируемого участка
  • dest - буфер приемник

Пример:

Screen 13
Line (1,1)-(50,50),12
Dim img As Any Ptr = Imagecreate(50,50)
Get(0,0)-(49,49),img
Put(50,0),img
Sleep
Imagedestroy(img)


В примере мы сначала нарисовали на экране линию. Далее создаем буфер изображения с помощью ImageCreate и помещаем в этот буфер при помощи GET скопированную часть экрана. Потом попросту это изображение с помощью PUT выводим на экран только в других координатах.

Очень часто требуется получить информацию об изображении. Использовать  данную возможность можно с помощью функции  ImageInfo  

Синтаксис:

result = ImageInfo ( [width] [, [height] [, [bypp] [, [pitch] [, [pixdata] [, [imgsize]]]]]] )

  • width - Ширина
  • height - Высота
  • bypp - Кол-во бит на пиксель
  • pitch - Размер каждой строки буфера (ScanLine) в байтах.
  • pixdata - Указатель на начало пиксельных данных
  • imgsize - Общий объем памяти, используемый изображением

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

Пример(из справки, чуть изменил):

Dim As Any Ptr img, pixdata
Dim As Integer pitch,bpp
Screen 14,32
img = Imagecreate(128, 128)
ImageInfo img,,,, pitch,pixdata
For y As Integer = 0 To 127
    Dim As Uinteger Ptr p = pixdata + y * pitch   
    For x As Integer = 0 To 127
        p[x] = Rgb(x * 4, y * 4, (x+y) * 4)
    Next x
Next y
Put (95, 50), img
Imagedestroy img
Sleep


В этом примере создается изображение, далее с помощью функции ImageInfo, получаем нужные параметры. Внешний цикл перечисляет все страницы буфера, внутренний каждый пиксель страницы. И конечно же в каждый пиксель записывается определенное значение с помощью макроса RGB. Далее после того, как рисунок дорисовался, он выводится на экран с помощью PUT.
    
Рисовать на экране это хорошо, но часто хочется сохранить нарисованное в файл для последующей загрузки. В FreeBasic есть встроенная возможность сохранять или загружать изображения только в формате BMP. Если понадобится сохранение или загрузка в другие форматы, то придется использовать сторонние библиотеки.

Для загрузки изображения используется функция BLOAD , для сохранения BSAVE.

Синтакис функции BLOAD:

result = BLoad( filename [, [ dest ] [, pal ] ] )

У функции три параметра и только один (filename) обязательный:

  • filename   - Имя файла изображения с полным путем к нему    
  • dest   - Буфер памяти, куда будет загружено изображение, если не указывать или записать 0, то загружаться будет на текущую видеостраницу       
  • pal  - Адрес буфера для загрузки информации о палитре изображения. Если поставить 0, то будет использоваться текущая палитра экрана.       

Пример:

Screen 14,32
Bload("2.bmp")
Sleep

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

Screenres 640,480,32
Dim As Any Ptr img = Imagecreate(320,240)
Bload("2.bmp",img)
Put(0,0),img
Sleep


Синтаксис функции BSAVE:

result = BSave( filename, source [,[ size ][, pal ]] )

  • filename - Имя файла для сохранения
  • source - Буфер изображения
  • size - Размер байт для сохранения, по умолчанию 0 .
  • pal  - адрес буфера с палитрой. Если параметр равен 0, то используется текущая палитра экрана

Если во втором параметре указать 0, то изображение будет взято с текущей страницы экрана. Если указать буфер во втором параметре, то рисунок будет взят из буфера. Третий и четвертый параметры могут понадобиться тогда, когда изображения рисуются не встроенными средствами FreeBasic. Именно тогда нужно указывать размер буфера, поскольку Freebasic не сможет определить его автоматически.

Пример_1:

Screen 1 
Circle(150,100),80,2,,,,F
Bsave("Circle.bmp",0)
Sleep

Пример_2:

Screen 14
Dim As Any Ptr img = Imagecreate(170,170,6)
Circle img,(85,85),80,3,,,,F
Bsave("Circle.bmp",img)
Sleep


В прошлой главе, рассматривая примитивы (линии, кружки, точки) , я не стал останавливаться на функции , рисующей текст на экране. Хоть она и простая сама по себе, но в ней есть один параметр, в котором указывается шрифт. Данный шрифт может загружаться с помощью функции BLOAD. 
Для того чтобы вывести надпись в графическом окне, используя графические шрифты, можно воспользоваться функцией Draw String. Эта функция использует шрифт по умолчанию, но как я и говорил, можно загрузить ваш собственный, созданный например в любом графическом редакторе. Особенно это полезно при разработке игр.

Синтаксис функции:

Draw String  buffer  STEP (x, y), text ,color , font , method ,blender, param

У функции три обязательных параметра: x, y, text

  • buffer - буфер для вывода строки, если не использовать, то вывод идет на экран
  • Step - используется при относительных координатах от последнего рисования
  • x, y - координаты для вывода строки
  • text -  выводимая строка
  • color - цвет строки
  • font - шрифт
  • method - Один из методов рисования:
    • Фон-независимые методы (Не используются при копировании в буфер):
      • Pset - Копируются все пикселы
      • PReset - Копируются все пикселы с инвертированием
      • Trans - Копируются все пикселы, кроме пикселей прозрачного цвета.
    • Фон-зависимые методы:
      • And - Смешивание пикселей по битовому методу And
      • Or -  Смешивание пикселей по битовому методу Or
      • Xor -  Смешивание пикселей по битовому методу Xor
      • Alpha -  Смешивание пикселей с прозрачностью
      • Add - Метод добавления пикселей к прозрачным участкам.
      • Custom - пользовательский метод, используемый со своей процедурой, в которой преобразуются пикселы
  • blender - указатель на процедуру при использовании метода Custom
  • param -
    • дополнительный параметр для своей процедуры с методом Custom
    • дополнительный параметр для методов Add и Alpha , определяющий интенсивность в диапазоне 0-255.

Пример:

Screen 1 
Draw String(10,10),"FreeBasic",2
Sleep


А теперь об использовании своих шрифтов для DrawString. Как для примера можете попробовать скопировать ниже рисунок с шрифтом в папку с исходным текстом примера ниже.

Изабелла декор

Пример:

Screen 14,32
Dim As Any Ptr font = Imagecreate(733,16)
Bload ("3.bmp",Font)
Draw String(10,10),"FreeBasic",2,font
Sleep


Дополнительно еще что касается шрифта: пример его создания на основе используемого в FreeBasic, можно найти в справке к функции Draw String. Для создания каких-то нестандартных шрифтов, можно использовать сторонние библиотеки(например ЭТА очень удобная). Так же можно использовать хороший пример создания шрифта на основе имеющихся в системе.

Всего доброго!

содержание | назад | вперед