ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 ноября
374587
dimonomid (09.12.2012 06:24 - 21:53, просмотров: 1064)
Скриншот с дисплея устройства: модуль для генерации bmp Решил поделиться своим модулем, который облегчает мне жизнь. Занимаясь разработкой различных устройств, я неоднократно сталкивался с типовой задачей: когда приходит время писать инструкцию по эксплуатации для пользователей, появляется необходимость делать скриншоты с дисплея устройства. То есть, для составления красивой документации нужно иметь возможность "сфотографировать" содержимое дисплея в любой момент времени, и сохранить получившуюся картинку в файл. Ну и потом уже можно вставлять эту картинку в саму инструкцию по эксплуатации. Например, вот такие скриншоты с дисплея зарядного устройства: (Простите, я так и не смог уговорить сахару отобразить эти картинки просто в один ряд. Если кто-то знает, как это делается - подскажите, пожалуйста) Для облегчения этой задачи в будущем, я написал универсальный модуль, который генерирует картинку в формате bmp, а данные изображения берет из пользовательской callback-функции (которая и должна вернуть цвет пикселя в определенной точке дисплея). Отличительной особенностью этого модуля является то, что данные генерируются маленькими частями (максимум - 4 байта) и возвращаются по одному байту, а не сразу вся картинка целиком. Такой алгоритм работает несколько медленнее, но он обладает существенным преимуществом: он дает вам полную свободу выбора в том, что именно и как именно вы будете делать с этими данными. То есть, для генерации изображения абсолютно любого размера и любой глубины цвета, в RAM будет выделено одно и то же количество памяти: 46 байт! (плюс еще около 20 байт стека) Как эти 46 байт будут выделены (из кучи, из стека или статически) - также зависит от вас. Конечно, если вы захотите поместить всю сгенерированную картинку в массив в RAM, то размер этого массива таки будет напрямую зависеть от размера изображения. Но в условиях ограниченных ресурсов микроконтроллера обычно имеет смысл, например, сразу передавать сгенерированные данные по UART (на ПК, или еще куда-нибудь), или, скажем, записывать во flash. Короче, делайте с ними что хотите. --- Размер кода: около 2 Кб в режиме оптимизации для наименьшего размера кода. Поддерживаемая глубина цвета: 1, 4, 8, 16, 24, 32 бит на пиксель. --- Вот, например, пользовательский код, генерирующий простенькую картинку. Здесь мы генерируем 24-битную картинку 256 x 50 пикселей, залитую градиентом из зеленого в синий: #include "bmp_writer/bmp_writer.h" /** * Пользовательская callback-функция, возвращающая цвет в определенной точке. * В реале здесь должен быть код, возвращающий цвет пикселя на экране, * но в этом примере мы просто генерим градиент. */ static T_BmpWr_Color32 _bmp_pix_color_get_32( uintptr_t user_data, T_BmpWr_Coord x, T_BmpWr_Coord y ) { return BMP_WR__COL_RGB_32bit(0x00, 0xff - x, x); } int main(void) { //-- Создаем структуру с параметрами для генератора картинки T_BmpWriter_CtorParams writer_ctor_params = { //-- Основные параметры изображения: глубина цвета, размер .color_depth = BMP_WR_COL_DEPTH__24, .width = 256, .height = 50, //-- Пользовательские callback-функции .callback = { //-- здесь нам нужна только одна пользовательская функция: // возвращающая цвет для 24- и 32-битных изображений .func = { .bpp_24_32 = { .p_pix_color_get = _bmp_pix_color_get_32, }, }, }, }; //-- Создаем объект T_BmpWriter с нужными параметрами T_BmpWriter *p_bmp_writer = new_bmp_writer(&writer_ctor_params); //-- Теперь, байт за байтом, запрашиваем все данные! while (bmp_writer__available_data_len__get(p_bmp_writer) > 0){ char cur_char = bmp_writer__next_byte__get(p_bmp_writer); //-- сейчас cur_char содержит очередной байт изображения. // мы можем сделать с ним все, что захотим: или накапливать // данные в буфер для записи во флеш (когда буфер будет // заполнен, то произвести запись, а потом продолжить // запрос данных изображения) или, может быть, передавать // куда-нибудь по UART (например, на ПК, где он будет сохранен) } //-- Все, картинка сгенерирована. // Удаляем объект delete_bmp_writer(p_bmp_writer); return 0; } Если интересно, вот тут можно прочитать подробную инструкцию с примерами и скачать сам модуль.