Статья демонстрирует основные приемы по загрузке и рендерингу изображений
Graphics Framework не располагает средствами для обработки стандартных форматов изображений, в частности: открытие, декодирование и сохранение изображений. По этой причине приложения, использующие Graphics Framework могут полагаться на штатную библиотеку работы с изображениями.
Библиотека располагает набором кодеков и программных интерфейсов для работы с основными стандартизованными типами изображений. Кодеки поставляются в виде отдельных загружаемых библиотеки и их перечень может быть легко расширен. Для точной настройки кодеков используется конфигурационный файл /etc/system/config/img.conf. Полный перечень дополнительных компонентов библиотеки включает:
/lib/dll/img_codec_*.so
Основной набор кодеков включает:
Кодек поддерживает декодирование, но не кодирование. |
Кодек поддерживает декодирование, но не кодирование. |
Перед тем, как приложение сможет отобразить изображение, оно должно выполнить подготовительные операции, как указано в разделе Основы рисования.
Также приложению следует выполнить следующие действия:
Посмотрим на эти шаги подробнее.
При вызове функции img_lib_attach() библиотека инициализирует и загружает доступные кодеки, указанные в конфигурационном файле /etc/system/config/img.conf. В этом файле можно настроить перечень кодеков и расширений файлов. Путь поиска конфигурационного файла можно переопределить с помощью переменной окружения LIBIMG_CFGFILE
.
Пример использования img_lib_attach():
img_lib_t ilib = NULL;int rc;...if ( (rc = img_lib_attach( &ilib )) != IMG_ERR_OK ){fprintf( stderr, "img_lib_attach() failed: %d\n", rc );return (-1);}
Подразумеваются следующие шаги:
Если имеются дополнительные сведения об изображении (например, mime-тип или расширение файла), следует рассмотреть использование функций img_codec_list_byext() и img_codec_list_bymime(). Это позволит ограничить перечень подходящих кодеков. Также стоит учитывать, что расширение и mime-тип не обязаны гарантировать, что содержимое файла соответствует форматы. В общем случае целесообразно проверять полный перечень кодеков на совместимость с объектом. |
io_stream_t
с источником данных из предыдущего шага.
IMG_ERR_NODATA
).
Данный алгоритм может быть излишним для прикладного приложения. На этот случай имеется несколько вызовов, осуществляющих данные действия неявно:
io_stream_t
. Это обеспечивает степень удобства, сопоставимую с функцией img_load_file(), но снимает ограничение на работу лиь с файлами. Функция также возвращает лишь первый кадр. Пример использования img_load_file():
int rc;img_t img;.../* initialize an img_t by setting its flags to 0 */img.flags = 0;/* if we want, we can preselect a format (ie force the image to beloaded in the format we specify) by enabling the following twolines */img.format = IMG_FMT_PKLE_ARGB1555;img.flags |= IMG_FORMAT;/* likewise, we can 'clip' the loaded image by enabling the following */img.w = 100;img.flags |= IMG_W;img.h = 100;img.flags |= IMG_H;if ( (rc = img_load_file( ilib, argv[optind], NULL, &img )) != IMG_ERR_OK ){fprintf( stderr, "img_load_file(%s) failed: %d\n", argv[optind], rc );return (-1);}fprintf( stdout, "img is %dx%dx%d\n", img.w, img.h, IMG_FMT_BPP( img.format ) );/* for our purposes we''re done with the img lib */img_lib_detach( ilib );
Данный шаг более сложный. Следует определить зависим ли кадр от палитры и установить ее:
gf_palette_t palette;...if ( img.format & IMG_FMT_PALETTE ){/* setup palette if necessary */palette.ncolors = img.npalette;palette.colors = img.palette;} elseif ( img.format == IMG_FMT_G8 ){/* we can render G8 images in GF by using a palette of grays */palette.ncolors = 256;palette.colors = (img_color_t *)g8pal;}
Затем следует создать на основе изображения поверхность, сделав тем самым доступным его для GF
API. Выполнить это можно с помощью gf_surface_attach() как указано ниже:
/* attach a surface to the image data; this allows us to blit the imagedata to another surface (or the display) in GF */int rc = gf_surface_attach( &img_surf, setup.gdev, img.w, img.h,img.access.direct.stride,img_fmt_to_gf( img.format ),&palette, img.access.direct.data, 0 );if ( rc != GF_ERR_OK ){fprintf( stderr, "gf_surface_attach() failed: %d\n", rc );/* might fail here if the decoder gave us a format that cannotmap to GF; in this case we could have preselected a formatthat is supported by GF (code above shows how to do this) */return (-1);}
Поверхности, созданные через gf_surface_attach(), имеют ряд ограничений:
Перед блиттингом изображения в поверхность следует проконтролировать альфа-канал и обработку прозрачности:
gf_setup_t setup;...if ( img.flags & IMG_TRANSPARENCY ){/* we can handle transparency in GF using chroma */gf_chroma_t chroma;memset( &chroma, 0, sizeof chroma );chroma.mode = GF_CHROMA_OP_SRC_MATCH | GF_CHROMA_OP_NO_DRAW;if ( img.format & IMG_FMT_PALETTE ){chroma.color0 = img.palette[img.transparency.index];} elseif ( IMG_FMT_BPP(img.format) < 24 ){chroma.color0 = img.transparency.rgb16;} else {chroma.color0 = img.transparency.rgb32;}gf_context_set_chroma( setup.context, &chroma );}if ( img.format & IMG_FMT_ALPHA ){gf_alpha_t alpha;memset( &alpha, 0, sizeof alpha );alpha.mode = GF_ALPHA_M1_SRC_PIXEL_ALPHA | GF_BLEND_SRC_M1 | GF_BLEND_DST_1mM1;gf_context_set_alpha( setup.context, &alpha );}
Блиттинг изображения в поверхность выполняется функцией gf_draw_blit2():
gf_draw_blit2( setup.context, img_surf, NULL, 0, 0,img.w - 1, img.h - 1, setup.x1, setup.y1 );
После завершения использования библиотеки работы с изображениями следует озаботиться освобождением ресурсов:
/* it's a good idea to do this before we free the image to ensure therenderer is done with the data */gf_draw_finish( setup.context );/* unlock the h/w */gf_draw_end( setup.context );if ( img.format & IMG_FMT_ALPHA )gf_context_disable_alpha( setup.context );if ( img.flags & IMG_TRANSPARENCY )gf_context_disable_chroma( setup.context );/* release the attached surface; we're not going to blit from it anymore (in real life this surface could be recycled if needed) */gf_surface_free( img_surf );/* above code only releases the surface; we still have the actual imagedata hanging around. We relied on the library to allocate this forus. The following is all that's needed when we rely on this defaultbehaviour (note that this free() takes care of the palette also,if applicable, since the lib allocates it all in one chunk) */free( img.access.direct.data );
Предыдущий раздел: Библиотека Image