Перейти к публикации
Форум - ComputerCraft
ECS

[OC] Image: глобальная библиотека для работы с изображениями

Рекомендованные сообщения

9si3o9g4xr49.png

 

Хочу представить вам большую библиотеку, предназначенную для работы с изображениями, созданными в нашем Фотошопе. С ее помощью можно манипулировать графикой воистину волшебным образом: изображения можно обрезать, расширять, поворачивать, отражать, инвертировать, изменять их яркость, цветовой тон, насыщенность и добавлять фотофильтры. Разрабатывали мы ее примерно год, содержит она более 1000 строк кода и удовлетворяет практически всем наши требованиям к хорошей графике в OpenComputers, если, конечно, местную графику вообще можно назвать хорошей.

 

Начало работы

 

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

wget https://raw.githubusercontent.com/IgorTimofeev/OpenComputers/master/lib/colorlib.lua lib/colorlib.lua -f
wget https://raw.githubusercontent.com/IgorTimofeev/OpenComputers/master/lib/image.lua lib/image.lua -f

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

local image = require("image")

Структура изображений

(для общего развития)

 

 

 

 

Для начала я расскажу вам, как реализовано хранение изображений в оперативной памяти компьютера. Итак, каждое изображение у нас - это обычный массив. Мы специально используем одномерный массив для экономии оперативной памяти, а при отрисовке библиотека сама получает координаты x и y по особым формулам, что совсем не сказывается на производительности. В данном массиве чередуются цвет фонацвет текстаальфа-канал и символ. Это что касается оперативной памяти.

 

2yk2hua52epk.png

 

А теперь я покажу вам, каким образом данные о пикселях хранятся в файлах .pic на жестком диске, используя различные методы кодировки (0, 1, 2 или 3). Для наглядности мы будем открывать один и тот же файл "Love.pic", демонстрирующий нашу любовь к моду OpenComputers, сохраненный с различными методами кодировки.

 

c30bb7a00c712b43f0e1b3a7c6e5e1a7.png

 

К примеру, при кодировке 0 изображение с сердечком хранится в следующем виде:

 

c6hya1ahw1s5.png

 

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

 

Далее рассмотрим метод кодировки 1. Мы довольно долго пользовались им, он использует простейшее "сжатие", когда данные записываются не в виде символов, а в виде последовательности байт.

 

ndvhklzb7h5b.png

 

У него есть один недостаток: в файле постоянно повторяются схожие данные, к примеру, если наше изображение имеет размеры 10х10 пикселей и черный фон, то данные о фоне повторятся в файле 100 раз. Это неправильно.

 

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

 

v0wc5n437ouo.png

 

Видно, что размер файла уже существенно уменьшился. Однако для записи цветов тут используются 3 байта (т.е. белый будет 0xFFFFFF), в то время как палитра OpenComputers поддерживает лишь 256 возможных оттенков. Отсюда вывод, что мы неэкономно храним данные.

 

Если взглянуть на метод кодировки 3, то сразу видно, что размер файла стал еще меньше. При этом на цвет используется лишь 1 байт (т.е. белый будет 0xFF). Это крайне оптимизированный формат картинок, вылизанный, что называется, дочиста.

 

dkt1on4yejh2.png

 

 

 

 

Методы работы с файлами изображений

(загрузка, отрисовка, сохранение)

 

 

 

 

image.load( string путь ): table изображение

 

     Загружает существующий файл .pic из указанного пути и возвращает изображение

     в виде массива.

local myPicture = image.load("MineOS/System/OS/Icons/Love.pic")

image.savestring путь, table изображение [, int метод кодирования] )

 

     Сохраняет существующий массив изображения в файл по указанному пути. Формат

     файла должен быть .pic. Опционально можно указать метод кодирования от 0 до 3,

     однако крайне рекомендуется использовать 3 для экономии места на диске.

image.save("copyOfMyPicture.pic", myPicture)

image.drawint x, int y, table изображение )

 

     Рисует загруженное ранее изображение по указанным координатам.

image.draw(8, 4, myPicture)

     c30bb7a00c712b43f0e1b3a7c6e5e1a7.png

 

 

 

 

Методы трансформирования изображений

(вращение, отражение, обрезание и т.п.)

 

 
image.expand( table  изображение, string направление, int количество пикселей[, int цвет фона, int цвет текста, int прозрачность, string символ] ): table картинка
 
     Расширяет указанную картинку в указанном направлении (fromRight, fromLeft, fromTop, fromBottom),
     создавая при этом пустые белые пиксели. Если указаны опциональные аргументы, то вместо пустых
     пикселей могут быть вполне конкретные значения.
image.draw(8, 4, myPicture)
myPicture = image.expand(myPicture, "fromRight", 10)
image.draw(53, 4, myPicture)

     f71b8eeb84b15bdde5b870e654e1550e.png

 
image.croptable изображениеstring направление, int количество пикселей ): table изображение
 
     Обрезает указанную картинку в указанном направлении (fromRight, fromLeft, fromTop, fromBottom),
     удаляя лишние пиксели.
image.draw(8, 4, myPicture)
myPicture = image.crop(myPicture, "fromRight", 10)
image.draw(53, 4, myPicture)

     d7d6c2b5f23e907672b10c4f4ae36ee1.png

 
image.rotatetable изображение, int угол ): table изображение
 
     Поворачивает указанную картинку на указанный угол. Угол может иметь
     значение 90, 180 и 270 градусов.
image.draw(8, 4, myPicture)
myPicture = image.rotate(myPicture, 90)
image.draw(53, 4, myPicture)

     f198a2151699bdb2ca57d9202922acc4.png

 
image.flipVerticaltable изображение): table изображение
 
     Отражает указанную картинку по вертикали.
image.draw(8, 4, myPicture)
myPicture = image.flipVertical(myPicture)
image.draw(53, 4, myPicture)

     eb84192cbfea127157c8f0b0d4bb486c.png

 
image.flipHorizontaltable изображение): table изображение
 
     Отражает указанную картинку по горизонтали.
image.draw(8, 4, myPicture)
myPicture = image.flipHorizontal(myPicture)
image.draw(53, 4, myPicture)

     d3aa82b1476473a70f2201cb2d99f541.png

 

 
Методы работы с цветом
(яркость, насыщенность, тон и т.п.)
 

 
image.hueSaturationBrightnesstable изображениеint тонint насыщенностьint яркость ): table изображение
 
     Корректирует цветовой тон, насыщенность и яркость указанной картинки.
     Значения аргументов могут быть отрицательными для уменьшения параметра
     и положительными для его увеличения. Если значение, к примеру, насыщенности
     менять не требуется, просто указывайте 0.
 
     Для удобства вы можете использовать следующие сокращения:
 
          image.huetable изображение, int тон ): table изображение
          image.saturationtable изображение, int насыщенность ): table изображение
          image.brightnesstable изображение, int яркость ): table изображение
          image.blackAndWhitetable изображение ): table изображение
 
image.draw(8, 4, myPicture)
--Изменяем цветовой тон к красному, уменьшаем яркость, не изменяя насыщенность
myPicture = image.hueSaturationBrightness(myPicture, 200, 0, -10 )
image.draw(53, 4, myPicture)

     b0df3eab1f76586e8aa77b484c1781f1.png

 
image.colorBalancetable изображениеint красныйint зеленыйint синий ): table изображение
 
     Корректирует цветовые каналы указанной картинки. Аргументы цветовых
     каналов могут принимать как отрицательные значения для уменьшения интенсивности канала,
     так и положительные для увеличения.
 
image.draw(8, 4, myPicture)
--Делаем изображение "зеленее"
myPicture = image.colorBalance(myPicture, 0, 255, 0)
image.draw(53, 4, myPicture)

     ee3a0a1730b3be4a475fb68d633ad2c8.png

 

image.inverttable изображение ): table изображение
 
     Инвертирует цвета в указанной картинке.
image.draw(8, 4, myPicture)
myPicture = image.invert(myPicture)
image.draw(53, 4, myPicture)

     2b720ba1c8c23e69efa58c4304178fee.png

 
image.photoFiltertable изображениеint цветint прозрачность ): table изображение
 
     Накладывает на указанное изображение фотофильтр с указанной прозрачностью.
     Прозрачность может быть от 0 до 255.
 
image.draw(8, 4, myPicture)
--Накладываем сиреневый фотофильтр с прозрачностью 80
myPicture = image.photoFilter(myPicture, 0xFF00FF, 80)
image.draw(53, 4, myPicture)

     f8b9f5e57468903b3b996aaa7b04e10c.png

 

 

 

Изменено пользователем ECS
  • Like 9

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

 

 

Вынес функционал фотошопа в либу?
 

 

Тут функционала раза в 4 больше, чем в фотошопе, плюс, сам фотошоп всегда юзал функции из этой либы, являясь как бы графической оболочкой к либе. Хотел на днях перекодить ФШ с нуля, добавить поддержку двойного буфера, слоев, истории - поэтому и интегрировал все функции в либу image. Ну, и выложил ее сюда, чего добру пропадать.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×