JaggerDer 90 Опубликовано: 17 сентября, 2015 (изменено) "Недавно" почитал о формате .png и под впечатлением(ради чего сделал бесполезную семибайтную подпись файла) решил придумать свой формат изображения для OpenComputers и, естественно библиотеку для работы с ним. Изображение закодированное в этом формате имеет малый размер, поддерживает альфа-канал и в нем возможно закодировать utf8 символ на "пискель". Картинки: Библиотека для работы с .ocif Конечно же я сделал библиотеку для работы с форматом. Точнее сказать библиотека сделала формат, но это неважно. Сама же библиотека умеет делать три тривиальные вещи: Кодировать изображение и записывать в файл: write( filename:string, image:table, full_array:bool ):nilfilename - название файла, в который запишется закодированное изображениеimage - массив изображения; может быть представлен в двух форматах: удобном для восприятия и оптимизированным для уменьшения занимаемой оперативной памятиfull_array - выбор формата массива: true - "удобный" массив, в ином случае оптимизированный Читать изображение: read( filename:string, full_array:bool ):tablefilename - название файла, который будет прочитан и декодирован. Результат возвращается в виде оптимизированного формата массива full_array - выбор формата массива: true - "удобный" массив, в ином случае оптимизированный Рисовать прочитанное изображение: draw(image:table, frame:number, rawPosX:number, drawPosY:number, gpu:table ):nilimage - принимает оптимизированный формат изображенияframe - выбор фрейма, который будет отрисован.drawPosX, drawPosY - позиция с которой происходит отрисовкаgpu - ваша видеокартаФункция неоптимизирована и нестабильна! Так же теперь есть небольшие настройки: Выбор режима работы: setMode( mode:string ):boolна данный момент режима только два, это: "24bit" - 24bit формат, и стандартный: "8bit" или nil - то есть 8bit.24bit требует больше места для хранения, но точно передает все доступные цвета; 8bit занимет меньше места на диске, но у него хромает цветопередача(240 цветных оттенков + 16 оттенков серого). Выбор месторасположения файла ралитры: setPalette( palette_path:string ):nilвыбирает местораположение файла с палитрой, т.к. вам, вероятно, будет неудобен стандартный вариант с расположением в корне и названием "palette.cia".В режиме 8bit необходимо загружать палитру этой функцией! Это собственно и все, что она умеет делать. .OCIF - Open Computers Image Format Так как объяснить как работает данный формат стало тяжело даже мне, я решил удалить этот раздел, пока не придумаю как описать то, что происходит в этой адской системе. Но вкраце расскажу. "Пиксель" в данном формате кодируется 4 байтами в лучшем случае и 9 байтами в худшем(т.к размер utf8 символа в байтах имеет переменную длину). Первый байт кодирует цвет символа, второй - цвет фона, третий - альфа-канал, а остальными байтами кодируется символ. В файл также записывается такая служебная информация как подпись формата и ширина с высотой изображения. Расскажу немного о массивах, в которых у нас хранится раскодированное изображение. Таких массива у нас два: обычный и оптимизированный. В первом массиве очень удобно редактировать нашу картинку, иначе он прост для восприятия, относительно; второй массив является оптимизированным, то есть его невозможно читать. Оптимизированный вид массива сделан для того, чтобы он занимал меньше места в оперативной памяти, так как изображения в памяти занимают достаточно много места. Так же данный формат поддерживает альфа-канал. Вот так выглядит обыный массив: --Константы(можно скопипастить)-- local IMAGE_WIDTH = 1 local IMAGE_HEIGHT = 2 local IMAGE_FRAMES = 3 local IMAGE = 4 --Сырое изображение, т.е. массив(первый формат, удобен для редактирования из редактора) local ocif_image_raw = { [IMAGE_WIDTH] = 8, --Ширина изображения [IMAGE_HEIGHT] = 4, --Высота изображения [IMAGE_FRAMES] = 2, --Кол-во изображений [IMAGE] = { 0xffffff, 0x000000, 0, '┌', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x000000, 0, '┐', 0xffffff, 0x114B96, 120, '╞', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, 'O', 0xffffff, 0x114B96, 120, 'C', 0xffffff, 0x114B96, 120, 'I', 0xffffff, 0x114B96, 120, 'F', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '╡', 0xffffff, 0x114B96, 120, '╞', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, 'L', 0xffffff, 0x114B96, 120, 'I', 0xffffff, 0x114B96, 120, 'B', 0xffffff, 0x114B96, 120, 'R', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '╡', 0xffffff, 0x114B96, 120, '└', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '─', 0xffffff, 0x114B96, 120, '┘' }, [IMAGE+1] = { 0xffffff, 0x000000, 0, '┌', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x000000, 0, '┐', 0xffffff, 0x114B96, 0, '╞', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, 'O', 0xffffff, 0x114B96, 0, 'C', 0xffffff, 0x114B96, 0, 'I', 0xffffff, 0x114B96, 0, 'F', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '╡', 0xffffff, 0x114B96, 0, '╞', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, 'L', 0xffffff, 0x114B96, 0, 'I', 0xffffff, 0x114B96, 0, 'B', 0xffffff, 0x114B96, 0, 'R', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '╡', 0xffffff, 0x114B96, 0, '└', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '─', 0xffffff, 0x114B96, 0, '┘' } } А так оптимизированный: local IMAGE_WIDTH = 1 local IMAGE_HEIGHT = 2 local IMAGE = 3 local image_raw_optimized { [IMAGE_WIDTH] = 8, [IMAGE_HEIGHT] = 5, [IMAGE] = { 65480,"1", 65480,"0", 65480,"З", 65480,"0", 65480,"1", 2760," ", 2760," ", 2760," ", 2560," ", 14745344,"1", 65280,"0", 65280,"1", 65280,"0", 65280,"1", 2560," ", 2560," ", 2560," ", 2560," ", 65280,"1", 65280,"0", 65280,"1", 65280,"0", 65280,"1", 2560," ", 65280,"P", 65280,"A", 65280,"S", 65280,"░", 65280,"Ж", 65280,"B", 65280,"I", 65280,"N", 22783," ", 22783," ", 22783," ", 22728," ", 22728," ", 22728," ", 22728," ", 22728," " } } Думаю это наглядно объяснит, почему лучше не надо редактировать во втором формате массива? Установка Установка библиотеки: wget https://raw.githubusercontent.com/Pirnogion/OpenComputers_library/master/ocif/ocif.lua lib/ocif.lua Установка цветовой палитры: wget https://raw.githubusercontent.com/Pirnogion/OpenComputers_library/master/ocif/palette.cia lib/palette.cia Установка примера: wget https://raw.githubusercontent.com/Pirnogion/OpenComputers_library/master/ocif/example.lua /example В завершение Весь исходный код можно посмотреть на GitHub: https://github.com/Pirnogion/OpenComputers_library/tree/master/ocif З.Ы. Насчет бита-терминатора - так его обозвали в википедии, ко мне никаких претензий. З.Ы.Ы. Насчет моего английского - ОТСТАНЬТЕ! Во всем виноват Google translate. Обновления Обновление 1: Добавил альфа-канал, теперь есть возможность делать изображение полупрозрачными. Так же изменил "форму" массива(сырого изображения) для того, чтобы он занимал меньше оперативной памяти, к сожалению массив стал менее понятным "из кода". Добавил пример, который показывает как пользоваться библиотекой. Обновление 2: Изменил способ кодировки, теперь файл занимает вдвое меньший размер на диске. Добавил оптимизированный формат массива сырого изображения. Сделал возможность передавать массив в двух форматах. Небольшой фикс примера. Обновление 3: Изменил способ конвертации цветов при помощи формулы на таблицу цветов. Теперь для работы нужен файл цветовой палитры. Появились небольшие цветопотери. Неясно почему. Обновление 4: Исправил ситуацию с потерей цветов. Теперь можно выбирать режим работы 24bit(без цветопотерь) или 8bit(с небольшой потерей цветов). В первом случае размер файла выходит больше, а во-втором, соответственно, меньше. Обновление 5: Выловил кучу багов и сделал некоторые оптимизации Обновление 6: Добавил по предложению одного человека, возможность записывать в один файл до нескольких изображений. Добавил возможность чтения изображения в "удобной", неоптимизированной формате массива. Убрал принудительную загрузку палитры. Теперь ее необходимо прогружать функцией setPalette. Изменено 29 сентября, 2015 пользователем JaggerDer 7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Quant 442 Опубликовано: 17 сентября, 2015 Во всем виноват Google translate. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
JaggerDer Автор темы 90 Опубликовано: 22 сентября, 2015 Сделал пару обновлений библиотеки. Добавил альфа-канал и провел пару оптимизаций. Кстати, насчет того, что нельзя засунуть в 1 байт целый цвет. Оказывается я ошибался и кодировал цвета в 24 битном формате, что очень избыточно для 8 битного цвета, который используется в OpenComputers. Можно цвет закодировать и 1 байтом. Проверено на практике. А совсем недавно пытался доказать паре человек обратное Достижение получено Написать и придумать РАБОЧИЙ формат картинок 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 22 сентября, 2015 Давно юзаю данную библиотеку в своей "ОС", каждая иконка - файл со структурой ocif. Удобная штука, рекомендую Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Krutoy 1 169 Опубликовано: 23 сентября, 2015 А совсем недавно пытался доказать паре человек обратное Похоже, я на подсознательном уровне понимал, что это возможно, но не мог объяснить =)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 23 сентября, 2015 (изменено) Похоже, я на подсознательном уровне понимал, что это возможно, но не мог объяснить =)) Кстати, знаешь, какие костыли мы придумываем, чтобы сделать адекватную трансляцию 0xffffff -> 0xff? Кошмар какой-то - начинали с генерации 8-битной палитры и заканчиваем какими-то совершенно безумными формулами Вот примерчик: Изменено 23 сентября, 2015 пользователем EliteClubSessions Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you 403 Опубликовано: 23 сентября, 2015 (изменено) Кстати, знаешь, какие костыли мы придумываем, чтобы сделать адекватную трансляцию 0xffffff -> 0xff? Кошмар какой-то - начинали с генерации 8-битной палитры и заканчиваем какими-то совершенно безумными формулами Сделал пару обновлений библиотеки. Добавил альфа-канал и провел пару оптимизаций. Кстати, насчет того, что нельзя засунуть в 1 байт целый цвет. Оказывается я ошибался и кодировал цвета в 24 битном формате, что очень избыточно для 8 битного цвета, который используется в OpenComputers. Можно цвет закодировать и 1 байтом. Проверено на практике. А совсем недавно пытался доказать паре человек обратное OC, для мониторов тир3, юзает стандартную программную 8-битную палитру 6*8*5+16 Внутри кода sicot.lua есть простая формула генерации, и комментарии по безопасной палитре. Изменено 23 сентября, 2015 пользователем swg2you 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 24 сентября, 2015 Внутри кода sicot.lua есть простая формула генерации, и комментарии по безопасной палитре. Красава, спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
JaggerDer Автор темы 90 Опубликовано: 27 сентября, 2015 (изменено) OC, для мониторов тир3, юзает стандартную программную 8-битную палитру 6*8*5+16 Внутри кода sicot.lua есть простая формула генерации, и комментарии по безопасной палитре. Но монитор третьего уровня почему-то выводит больше чем 240 цветов и больше 16 цветов grayscale. Но за формулу все-равно спасибо. Вот таблица цветов, которую я сгенерировал по вашей формуле. Может быть я где-то накосячил. Код генерации таблицы: local f = io.open("colors", "w") local line = 0 local x = 0 f:write( "colors = {\n" ) for r=0,5 do for g=0,7 do for b=0,4 do line = " [" .. x .. "] = 0x" .. string.format("%X", r*0x330000 + g*0x2400 + b*0x3F) .. ",\n" f:write( line ) x = x + 1 end end end for i=1, 15, 1 do line = " [" .. 240+i .. "] = 0x" .. string.format("%X", gpu.getPaletteColor(i)) .. ",\n" f:write( line ) end f:write( "}\n" ) f:close() Изменено 27 сентября, 2015 пользователем JaggerDer Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
swg2you 403 Опубликовано: 27 сентября, 2015 (изменено) Но монитор третьего уровня почему-то выводит больше чем 240 цветов и больше 16 цветов grayscale. Но за формулу все-равно спасибо. Вот таблица цветов, которую я сгенерировал по вашей формуле. Может быть я где-то накосячил. Код генерации таблицы: local f = io.open("colors", "w") local line = 0 local x = 0 f:write( "colors = {\n" ) for r=0,5 do for g=0,7 do for b=0,4 do line = " [" .. x .. "] = 0x" .. string.format("%X", r*0x330000 + g*0x2400 + b*0x3F) .. ",\n" f:write( line ) x = x + 1 end end end for i=1, 15, 1 do line = " [" .. 240+i .. "] = 0x" .. string.format("%X", gpu.getPaletteColor(i)) .. ",\n" f:write( line ) end f:write( "}\n" ) f:close() Таблица и код вроде верные. При записи цвета 0xRRGGBB в монитор, значение 0xRRGGBB приводится к сокращенной палитре, реальное значение записанного цвета можно посмотреть вычитав знакоместо с помощью gpu.get. Т.е. если мы сделаем: gpu.setForeground(0x123456) gpu.set(5,5,' ') local s, fg, bg = gpu.get(5,5) То в fg мы получим вовсе не 0x123456, а приведенное значение. Алгоритм приведения неизвестен, но приведенные значения наиболее близки к палитре 6*8*5+16. Попробуй в sicot.lua покликать по битам меняя цвет, а потом кликнув на цвет посмотреть реальное значение приведенного цвета, чтобы узнать, какие именно цвета выводятся сверх палитры. В палитре Тир2 я находил аномальный 17-й цвет, возможно такие цвета есть и в Тир3. ЗЫ Реальные значения цветов могут немного отличаться от сгенерированных по формуле, это сделано для упрощения формулы генерации. Визуальных отличий быть не должно. Изменено 27 сентября, 2015 пользователем swg2you 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
1Ridav 1 049 Опубликовано: 29 сентября, 2015 Порой необходимо использовать много маленьких картинок, держать их в отдельных файлах не целесообразно из-за того, что загружать через http.get по отдельности довольно долгое занятие. Будет очень удобным возможность собирать пакеты десятков картинок в одном файле, а при запуске программы загружать разом в один массив 3 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
JaggerDer Автор темы 90 Опубликовано: 29 сентября, 2015 (изменено) Порой необходимо использовать много маленьких картинок, держать их в отдельных файлах не целесообразно из-за того, что загружать через http.get по отдельности довольно долгое занятие. Будет очень удобным возможность собирать пакеты десятков картинок в одном файле, а при запуске программы загружать разом в один массив Интересная идея, мне понравилась. Уже сделал Можно хранить до 255 картинок в одном файле(выделить больше 1 байта на кол-во картинок не позволила большая жаба). Изменено 29 сентября, 2015 пользователем JaggerDer 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах