QNX-SCREEN: Input Events
输入事件可以来自不同的设备,并且每个设备都具有与每个事件类型相关的特定属性。
输入事件是屏幕事件类型的子集。以下是输入事件:
SCREEN_EVENT_JOG (屏幕\事件\点动)
SCREEN_EVENT_POINTER (屏幕\事件\指针)
SCREEN_EVENT_KEYBOARD (屏幕\事件\键盘)
SCREEN_EVENT_GAMEPAD (屏幕\事件\游戏板)
SCREEN_EVENT_JOYSTICK (屏幕\事件\操纵杆)
SCREEN_EVENT_GESTURE (屏幕\事件\手势)
SCREEN_EVENT_MTOUCH_PRETOUCH (屏幕\事件\多点触摸\预触摸)
SCREEN_EVENT_MTOUCH_TOUCH (屏幕\事件\触摸\触摸)
SCREEN_EVENT_MTOUCH_MOVE (屏幕\事件\触摸\移动)
SCREEN_EVENT_MTOUCH_RELEASE (屏幕\事件\触摸\释放)
除了所有输入事件共有的以下属性外,应用程序还必须注意每个输入事件类型的细节,并相应地进行处理:
SCREEN_PROPERTY_TIMESTAMP (屏幕\属性\时间戳)
输入事件发生的时间戳。请注意,在计算时间戳时,屏幕使用实时时钟,而不是单调时钟。
SCREEN_PROPERTY_SEQUENCE_ID (屏幕\属性\序列\ ID)
与事件关联的序列ID。序列ID用于确定多点触控输入事件发生的顺序。
SCREEN_PROPERTY_TYPE (屏幕\属性\类型)
收件人定义的事件类型。一旦确定接收到的是输入事件,就可以获得输入接收者的句柄。例如,输入事件的焦点可以是以下任一项:
CREEN_PROPERTY_DISPLAY
SCREEN_PROPERTY_WINDOW
SCREEN_PROPERTY_SESSION
Keyboard events (键盘事件)
键盘事件可能与文本输入、导航、选择或使用特殊键(即具有特殊功能的键,如音量增大/减小)有关。
应用程序在处理键盘事件时感兴趣的属性包括:
SCREEN_PROPERTY_SYM (屏幕/属性/符号)
由按键产生的输出。参见sys/keycodes.h。
SCREEN_PROPERTY_FLAGS (屏幕\属性\标志)
指示应用程序是否可以使用逻辑数据的指示器。使用此选项确定从键盘接收的输入类型。屏幕属性标志的位根据键盘事件设置。对于键盘事件,以下掩码有效:
SCREEN_FLAG_KEY_DOWN
SCREEN_FLAG_KEY_REPEAT
SCREEN_FLAG_SCAN_VALID
SCREEN_FLAG_SYM_VALID
SCREEN_FLAG_CAP_VALID
SCREEN_PROPERTY_MODIFIERS (屏幕\属性\修改器)
与键盘事件关联的修饰符。
SCREEN_PROPERTY_KEY_CAP (屏幕\属性\键\盖)
按键盖上与按下的按键对应的面值。参见sys/keycodes.h。
SCREEN_PROPERTY_SCAN (屏幕\属性\扫描)
与键盘事件关联的扫描代码(物理键位置)。参见sys/usbcodes.h。
Pointer events (指针事件)
指针事件的接收者基于指针单击时光标的位置。也就是说,当检测到第一个指针事件时,输入事件集中在光标位置处活动的显示器、窗口或会话上。单击时,所有后续指针事件将发送给同一收件人,直到释放指针按钮。
屏幕自动绘制光标,这样应用程序就不必在光标移动时绘制和重画光标。通过在显示部分设置游标参数,可以在graphics.conf中配置游标的可见性。光标可以配置为始终可见、始终不可见或由屏幕自动确定。屏幕根据光标不活动或是否连接了触摸设备来确定光标的可见性。
应用程序在处理指针事件时感兴趣的属性包括:
SCREEN_PROPERTY_BUTTONS (屏幕\属性\按钮)
指示指针事件的哪些按钮被按下的位掩码。
SCREEN_PROPERTY_BUTTONS的位根据屏幕鼠标按钮类型设置。应用程序可以确定一系列指针事件的动作是单击、选择、移动还是从按下然后释放的按钮拖动。例如,单击可以通过鼠标左键的存在来跟踪,然后在很短的时间间隔内在相对相同的位置上没有鼠标左键。
SCREEN_PROPERTY_FLAGS (屏幕\属性\标志)
位置是相对还是绝对的指示器。使用此选项确定如何计算光标的移动,以建立用户的操作(例如,单击、移动、拖动等)。SCREEN_PROPERTY_FLAGS的位根据SCREEN事件标志设置。对于指针事件,以下掩码有效:
SCREEN_FLAG_DISPLACEMENT_VALID (屏幕\标志\位移\有效)
SCREEN_FLAG_POSITION_VALID (屏幕\标志\位置\有效)SCREEN_FLAG_SOURCE_POSITION_VALID (屏幕\标志\源\位置\有效)SCREEN_FLAG_SIZE_VALID (屏幕\标志\大小\有效)
SCREEN_PROPERTY_POSITION (屏幕\属性\位置)
指针事件的x和y位置(以像素为单位)。
SCREEN_PROPERTY_SOURCE_POSITION (屏幕\属性\源\位置)
指针事件相对于缓冲区的x和y位置。
SCREEN_PROPERTY_SIZE (屏幕\属性\大小)
光标区域的宽度和高度(以像素为单位)。
SCREEN_PROPERTY_DISPLACEMENT(屏幕\属性\位移)
自上次事件以来光标的x和y位移(以像素为单位)。
Touch events (触摸事件)
触摸事件的焦点基于每个接触点的位置。每个联系人都是独立发送的。也就是说,当检测到该联系人ID的第一次触摸事件时,输入事件将集中在该联系人位置处激活的显示器、窗口或会话上。
触摸事件与指针类似,只是触摸是直接输入(无光标)。也就是说,如果没有接触,就没有位置。对多点触摸(即多触点)的支持取决于硬件的支持。当支持多点触摸时,每个触点都独立处理,触摸、移动和释放都是单独的输入事件。
应用程序在处理指针事件时感兴趣的属性包括:
SCREEN_PROPERTY_TOUCH_ID (屏幕\属性\触摸\ID)
与触摸事件关联的联系人ID。该ID用于识别多点触摸的不同接触点。
SCREEN_PROPERTY_FLAGS (屏幕\属性\标志)
指示应用程序是否可以使用逻辑数据的指示器。使用此选项确定您从触摸设备接收的输入类型。SCREEN_PROPERTY_FLAGS的位根据SCREEN事件标志设置。对于指针事件,以下掩码有效:
SCREEN_FLAG_POSITION_VALID
SCREEN_FLAG_SOURCE_POSITION_VALID
SCREEN_FLAG_SIZE_VALID
SCREEN_PROPERTY_POSITION (屏幕\属性\位置)
接触区域左上角的x和y位置(以像素为单位)。
SCREEN_PROPERTY_SOURCE_POSITION (屏幕\属性\源\位置)
接触点相对于缓冲区的x和y位置(以像素为单位)。
SCREEN_PROPERTY_SIZE (屏幕\属性\大小)
接触区域的宽度和高度(以像素为单位)。
SCREEN_PROPERTY_SIZE (屏幕\属性\源\大小)
以缓冲区坐标表示的接触区域的宽度和高度。
SCREEN_PROPERTY_TOUCH_TYPE (屏幕\属性\触摸\类型)
与触摸事件关联的触摸类型。有效的触摸类型是手指或触笔,如屏幕触摸类型中所定义。
SCREEN_PROPERTY_TOUCH_PRESSURE(屏幕\属性\触摸\压力)
与触摸事件相关的压力。
SCREEN_PROPERTY_TOUCH_ORIENTATION (屏幕\属性\触摸\方向)
与触摸事件关联的方向。
Jog, Joystick, and Gamepad (点动、操纵杆和游戏板)
操纵杆和游戏板事件可以具有模拟和按钮组件。点动事件基本上仅在一个方向上模拟(例如鼠标滚轮)。
应用程序在处理点动、操纵杆和游戏板事件时感兴趣的属性包括:
SCREEN_PROPERTY_BUTTONS (屏幕\属性\按钮)
指示按下游戏板事件的哪些按钮的位掩码。
请注意,D-pad、A、B、X、Y、Start、Select、Left和Right都是游戏板上的按钮。SCREEN_PROPERTY_BUTTONS的位根据屏幕游戏按钮类型设置。屏幕游戏按钮类型用于将不同控制器的按钮映射到通用游戏控件布局。通常,您会创建一个结构来表示游戏控制器,然后将按钮映射到游戏按钮枚举中的一个位。
SCREEN_PROPERTY_FLAGS (屏幕\属性\标志)
指示值是离散值还是模拟值的指示器。SCREEN_PROPERTY_FLAGS的位根据SCREEN事件标志设置。对于点动事件,屏幕标志有效。
SCREEN_PROPERTY_ANALOG0 (屏幕\属性\模拟0)
一个模拟控制器的x、y和z值。对于没有三个自由度的模拟控制器,只有x和y值有效;z的值为0。此属性适用于游戏板和操纵杆事件。
SCREEN_PROPERTY_ANALOG1 (屏幕\属性1)
第二个模拟控制器的x、y和z值。对于没有三个自由度的模拟控制器,只有x和y值有效;z的值为0。此属性仅适用于游戏板事件。
SCREEN_PROPERTY_DISPLACEMENT (屏幕\属性\位移)
具有相对位移的事件的x和y坐标。
SCREEN_PROPERTY_JOG_COUNT (屏幕\属性\点动\计数)
点动计数,一个离散值,与点动事件关联。
SCREEN_PROPERTY_MODIFIERS (屏幕\属性\修改器)
传递两个16位值的32位整数。高阶16位表示参与触点的数量,低阶16位表示非参与触点。参与联系人是指主动用于计算手势的联系人数量。非参与联系人是指在确定手势时检测到但未考虑的联系人数量。有关更多信息,请参阅“多点触摸(touch)会话”部分。
Gesture events (手势事件)
手势事件可以是手势识别(构成一个手势的一系列输入事件)的结果,也可以是简单的手势事件(例如,来自支持手势的设备)。在手势识别的情况下,将发送手势事件代替序列输入事件。可以使用 SCREEN_PROPERTY_EVENT session属性的会话获取原始输入和手势事件。
应用程序在处理手势事件时感兴趣的属性包括:
SCREEN_PROPERTY_FLAGS (屏幕\属性\标志)
指示应用程序是否可以使用逻辑数据的指示器。使用此选项确定如何确定您从触摸设备接收的输入类型。SCREEN_PROPERTY_FLAGS的位根据SCREEN事件标志设置。对于指针事件,以下掩码有效:
SCREEN_FLAG_DISPLACEMENT_VALID
SCREEN_FLAG_POSITION_VALID
SCREEN_FLAG_SOURCE_POSITION_VALID
SCREEN_FLAG_SIZE_VALID
SCREEN_PROPERTY_POSITION (屏幕\属性\位置)
手势相对于输入接收者左上角的x和y位置。
SCREEN_PROPERTY_SIZE (屏幕\属性\大小)
手势的宽度和高度(以像素为单位)(例如,滑动的大小)。
SCREEN_PROPERTY_DISPLACEMENT(屏幕\属性\位移)
具有相对位移的事件的x和y坐标。
SCREEN_PROPERTY_DURATION (屏幕\属性\持续时间)
手势事件的持续时间(以纳秒为单位)。
SCREEN_PROPERTY_SYM (屏幕\属性\符号)
标识手势事件的符号。
SCREEN_PROPERTY_SCAN (屏幕\属性\扫描)
识别手势事件的扫描代码。
Buffers
缓冲区是存储像素数据的内存区域。多个缓冲区可以与窗口或流相关联,但只有一个缓冲区可以与pixmap相关联。
可以创建的缓冲区包括:
Internal buffers
内部缓冲区是通过调用以下屏幕API函数之一创建的缓冲区:
screen_create_pixmap_buffer()
screen_create_window_buffers()
screen_create_stream_buffers()
外部缓冲器:
外部缓冲区是通过调用screen_create_buffer()创建的缓冲区,其内存由应用程序分配。只有在将外部缓冲区附加到pixmap、窗口或流之一后,才能使用(例如渲染到)外部缓冲区。
内部缓冲区:
通过调用以下屏幕API函数之一,可以为PIXMAP、流和窗口创建缓冲区。
screen_create_pixmap_buffer()
screen_create_stream_buffers()
screen_create_window_buffers()
如果SCREEN_USAGE_READ或SCREEN_USAGE_WRITE不足以满足缓冲区的预期用途,则可以在创建缓冲区之前在SCREEN API对象上设置SCREEN_PROPERTY_USAGE。否则,只需通过调用适当的函数为Screen API对象创建缓冲区。例如,要为窗口创建缓冲区,请执行以下操作:
…
screen_context_t ctx;
screen_window_t win;
int num_bufs = 2;
…
screen_create_window(&win, ctx);
screen_create_window_buffers(win, num_bufs);
…
现在可以继续使用缓冲区。请参阅“使用缓冲区”。
External buffers
由于内存位置或缓冲区大小的要求,驱动程序等应用程序可能需要分配自己的缓冲区。这些应用程序必须确保在分配缓冲区时满足所有使用限制,以使屏幕能够成功连接缓冲区。未能满足使用限制还可能导致工件和系统不稳定。
创建自己的缓冲区并分配内存的应用程序必须:
1、通过调用 screen_create_buffer()创建screen_buffer_t类型的缓冲区。例如:
…
screen_buffer_t created_buf = NULL;
…
screen_create_buffer(&created_buf);
…
2、设置缓冲区属性。
您必须至少为应用程序分配的缓冲区设置以下属性:
SCREEN_PROPERTY_FORMAT
SCREEN_PROPERTY_BUFFER_SIZE
SCREEN_PROPERTY_SIZE
SCREEN_PROPERTY_STRIDE
如果使用的是一种平面YUV格式,则还应设置“SCREEN_PROPERTY_PLANAR_OFFSETS”属性。
例如,对于SCREEN_FORMAT_NV12的缓冲区:
…
const int width=1024, height=64, stride=4096;
const int nbytes = strideheight + stride(height/2);
…
screen_set_buffer_property_iv(created_buf,SCREEN_PROPERTY_FORMAT,(const int[]){SCREEN_FORMAT_NV12});
screen_set_buffer_property_iv(created_buf,SCREEN_PROPERTY_BUFFER_SIZE,(const int[]){width, height});
screen_set_buffer_property_iv(created_buf,SCREEN_PROPERTY_SIZE,(const int[]){nbytes});
screen_set_buffer_property_iv(created_buf,SCREEN_PROPERTY_STRIDE,(const int[]){stride});
screen_set_buffer_property_iv(created_buf,SCREEN_PROPERTY_PLANAR_OFFSETS,(const int[]){0,(height*stride),-1});
…
3、为缓冲区分配内存并为其分配访问权限。
您可以使用SCREEN_PROPERTY_POINTER属性或SCREEN_PROPERTY_FD 属性来分配内存。但是,请注意,根据使用的属性,可能需要在内存上设置不同的属性:
SCREEN_PROPERTY_POINTER
a、为缓冲区分配内存。
为缓冲区分配一些内存。如何以及从何处分配内存取决于应用程序;它可以静态分配(从固定地址映射)或从共享内存对象分配。例如:
…
int fd;
uint32_t *mmap_ptr;
…
fd = shm_open(SHM_ANON, O_CREAT|O_EXCL|O_RDWR, 0400);
shm_ctl(fd, SHMCTL_ANON, 0, nbytes);
mmap_ptr = mmap(NULL, nbytes , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
…
b、将指针指定给缓冲区。
必须将SCREEN_PROPERTY_POINTER 属性设置为指向已为此缓冲区分配的内存。例如:
…
screen_set_buffer_property_pv(created_buf, SCREEN_PROPERTY_POINTER, (void**)&mmap_ptr);
…
SCREEN_PROPERTY_FD
a、为缓冲区分配内存。
如何以及从何处分配内存取决于应用程序;它可以静态分配(从固定地址映射)或从共享内存对象分配。例如:
…
int fd;
…
fd = shm_open(SHM_ANON, O_CREAT|O_EXCL|O_RDWR, 0400);
…
/* Seal the memory so it can’t be modified /
if (0 != shm_ctl(shm_fd, SHMCTL_SEAL, 0, 0)){
/ error */
…
}
…
注意:使用SCREEN_PROPERTY_FD属性指示内存时,必须确保:
调用shm_ctl()来设置SHMCTL_SEAL标志,以防止修改共享内存对象。
确保未在共享内存对象上设置SHMCTL_REVOCABLE标志。可以使用SHMCTL_GET_FLAGS标志调用shm_ctl(),以验证正在使用的对象上设置了哪些标志。如果设置了SHMCTL_REVOCABLE标志,则无法将此对象与缓冲区关联。
b、将文件描述符分配给缓冲区。
必须将SCREEN_PROPERTY_FD 属性设置为指向已为此缓冲区分配的内存。例如:
…
screen_set_buffer_property_iv(created_buf, SCREEN_PROPERTY_FD, &fd);
…
4、在使用外部缓冲区之前,先将其附加到pixmap、窗口或流。请参阅“附加缓冲区”。
您必须使用在其类型中包含SCREEN_BUFFER_PROVIDER_CONTEXT 上下文的特权屏幕上下文来附加缓冲区。例如:
…
screen_context_t screen_ctx;
…
screen_create_context(&screen_ctx, (SCREEN_APPLICATION_CONTEXT | SCREEN_BUFFER_PROVIDER_CONTEXT));
Attaching buffers
通过分别调用以下函数,可以附加一个缓冲区(类型为 screen_buffer_t)以将其与pixmap、流或窗口相关联:
screen_attach_pixmap_buffer()
screen_attach_stream_buffers()
screen_attach_window_buffers()
要附加缓冲区,请执行以下操作:
1、获取屏幕缓冲区screen_buffer_t。
要访问缓冲区,可以检索以下任意内容:
外部缓冲区(即,通过调用screen_create_buffer()创建并分配内存的缓冲区)。
通过调用screen_acquire_buffer()函数从流中提取缓冲区。例如:
screen_stream_t astream = NULL;
screen_buffer_t buffer = NULL;
…
screen_acquire_buffer(&buffer, astream, NULL, NULL, NULL, SCREEN_ACQUIRE_DONT_BLOCK);
…
通过调用screen_get_*_property_pv()函数及其返回缓冲区的有效属性之一,从pixmap、流或窗口获取缓冲区。
pixmap
使用以下属性之一调用screen_get_pixmap_property_pv():
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_RENDER_BUFFERS
stream
使用以下属性之一调用 screen_get_stream_property_pv() :
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_FRONT_BUFFERS
SCREEN_PROPERTY_RENDER_BUFFERS
window
使用以下属性之一调用screen_get_window_property_pv():
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_FRONT_BUFFER
SCREEN_PROPERTY_RENDER_BUFFERS
例如:
…
screen_buffer_t win_buf;
win_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t));
…
screen_get_window_property_pv(win, SCREEN_PROPERTY_RENDER_BUFFERS, (void*)win_buf));
…
2、在要将缓冲区附加到的SCREEN API对象(即pixmap、stream或window)上设置SCREEN_属性_用法。
在pixmap、stream或window中,您应该在附加缓冲区之前指出缓冲区的预期用途,因为如果未正确设置用途,屏幕可能会阻止对缓冲区的访问。
…
screen_window_t a_win;
…
int usage = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
screen_set_window_property_iv(a_win, SCREEN_PROPERTY_USAGE, &usage);
…
如果在要附加缓冲区的Screen API对象上设置的预期用途与最初创建的缓冲区用途不兼容,则Screen可能无法附加缓冲区,或者缓冲区可能无法用于预期用途。
3、通过调用适当的Screen API函数,将缓冲区附加到有效的Screen API对象。
例如:
…
screen_attach_window_buffers(a_win, num_bufs, win_buf);
…
与pixmaps和windows不同,如果不先调用screen_destroy_stream_buffers(),则无法将缓冲区附加到已经具有与其关联的缓冲区的流。
Using buffers
要使用与Screen API对象关联的缓冲区,必须从该对象检索它。以下是可以检索可供使用的有效缓冲区的方法(例如,用于blitting或rendering目的):
pixmax
使用以下属性之一调用screen_get_pixmap_property_pv():
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_RENDER_BUFFERS
例如:
…
screen_context context;
screen_pixmap_t screen_pix = NULL;
screen_buffer_t pix_buf;
uint32_t pix_ptr;
…
screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS, (void*)&pix_buf));
screen_get_buffer_property_pv(pix_buf, SCREEN_PROPERTY_POINTER, (void**)&pix_ptr));
…
screen_fill(context, pix_buf, (const int[]){SCREEN_BLIT_COLOR, 0xabcd, SCREEN_BLIT_END});
…
stream:
使用以下属性之一调用screen_get_stream_property_pv():
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_FRONT_BUFFERS
SCREEN_PROPERTY_RENDER_BUFFERS
例如:…
int num_bufs = 0;
screen_buffer_t stream_buf = NULL;
screen_get_stream_property_iv(stream, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &num_bufs);
a_stream_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t));
…
screen_get_stream_property_pv(stream, SCREEN_PROPERTY_RENDER_BUFFERS, (void*)stream_buf));
…
screen_post_stream(stream, stream_buf[0], 0, NULL, 0));
…
调用 screen_acquire_buffer() 函数,例如:
…
screen_context ctx;
screen_stream_t a_stream;
screen_buffer_t buffer, dest_buffer;
…
screen_acquire_buffer(&buffer, a_stream, NULL, NULL, NULL, SCREEN_ACQUIRE_DONT_BLOCK);
…
screen_blit(ctx, buffer, dest_buffer, (const int[]){SCREEN_BLIT_COLOR, 0xabcd, SCREEN_BLIT_END});
…
windows
使用以下属性之一调用screen_get_window_property_pv():
SCREEN_PROPERTY_BUFFERS
SCREEN_PROPERTY_FRONT_BUFFER
SCREEN_PROPERTY_RENDER_BUFFERS
例如:…
int num_bufs = 0;
screen_buffer_t win_buf = NULL;
screen_get_window_property_iv(win, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &num_bufs);
other_win_buf = calloc((size_t)num_bufs, sizeof(screen_buffer_t));
…
screen_get_window_property_pv(win, SCREEN_PROPERTY_RENDER_BUFFERS, (void*)win_buf));
…
screen_post_window(win, win_buf[0], 0, NULL, 0));
…
Working with images
本章介绍如何使用图像库libimg加载和渲染图像。
图像库为图像编解码器提供了一个通用接口。您需要将任何必需的图像编解码器(及其依赖项)以及图像配置文件放到运行应用程序的目标上。您需要包括(至少):
位于/etc/system/config/img.conf的配置文件(请参见img_lib_attach()文档中的描述)
Q
N
X
T
A
R
G
E
T
/
p
r
o
c
e
s
s
o
r
/
l
i
b
/
d
l
l
中的图像编解码器(
i
m
g
c
o
d
e
c
.
∗
.
s
o
)及其依赖项(如果有)(通常为
QNX_TARGET/processor/lib/dll中的图像编解码器(img_codec.*.so)及其依赖项(如果有)(通常为
QNXTARGET/processor/lib/dll中的图像编解码器(imgcodec.∗.so)及其依赖项(如果有)(通常为QNX_TARGET/processor/usr/lib/)
图像库使用的编解码器包括:
img_codec_bmp.so
Windows位图格式编解码器。为所有已知变体(头版本5.x除外)以及旧版OS/2变体提供完整的Microsoft BMP支持。不支持v1.x DDB格式。
img_codec_gif.so
图形交换格式编解码器。该编解码器支持GIF 87a和GIF 89a变体以及图形控制扩展,该扩展为该格式提供了大部分重要功能(透明、隔行、多帧等)。它忽略了允许嵌入文本、注释、应用程序数据等的其他扩展。
此编解码器需要libgif.so.5库。
img_codec_jpg.so
联合摄影专家组文件格式编解码器。支持24位RGB、YUV和灰度。
此编解码器需要libjpeg.so.4库。
img_codec_pcx.so
个人计算机交换格式解码器。
img_codec_png.so
便携式网络图形编解码器。提供完整的PNG支持,支持alpha、透明度和交错。此编解码器忽略以下块:
• background color(背景色)
• chromaticity(色度)
• gamma(伽马射线)
• histogram(直方图)
• physical pixel dimension(物理像素尺寸)
• significant bits(有效位)
• text data(文本数据)
• image last-modified time(上次修改图像的时间)
此编解码器需要以下库:
• libpng16.so.16
• libz.so.2
img_codec_sgi.so
SGI格式编解码器。它支持黑白、灰度和彩色图像(sgi、.rgb、.rgba、.bw)。
此编解码器仅支持解码。
img_codec_tga.so
Truevision图形适配器格式编解码器。对于解码,此编解码器处理游程编码(RLE)压缩,并支持以下格式:
• true color 16-, 24-, and 32-bit
• cmap 15-, 16-, 24-, and 32-bit
• black and white 8-bit
对于编码,此编解码器支持真彩色(8888)32位RLE。
img_codec_tif.so
标记图像文件格式编解码器。支持Adobe TIFF 6.0版规范中的完整基线TIFF解码(例如,双层、灰度、RGB、多个子文件、PackBits和Huffman压缩)。支持一些TIFF扩展,例如CCITT双层编码(支持传真图像解码)、LZW压缩和相关的alpha。
TIFF编码器仅限于编码灰度和RGB图像。
此编解码器需要以下库:
• libtiff.so.5
• libz.so.2
• liblzma.so.5
由于TIFF图像不是连续的数据流,TIFF解码器必须能够在图像流中查找图像数据。因此,它可能与某些单向或无缓冲IO流不兼容。为获得最佳效果,请从文件或完整内存缓冲区解码TIFF图像。
img_codec_wbmp.so
无线应用协议位图文件格式编解码器。支持单色图像的解码和编码。
要显示图像,应用程序需要:
• 连接到图像库
• 加载图像文件
• 清理分配的资源并从映像库中分离
让我们更详细地了解这些步骤中的每一步。
Attaching to the image library
调用img_lib_attach()时,图像库将初始化并加载在img.conf配置文件中列出的编解码器。您可以自定义此文件以仅加载应用程序所需的编解码器,并通过设置LIBIMG_CFGFILE环境变量更改图像库查找它的位置。如果未设置此环境变量,库将检查默认位置/etc/system/config/img.conf。有关此文件格式的更多信息,请参阅img_lib_attach()的文档。
To use 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;
}
Load an image
要加载图像,请执行以下步骤:
1.编解码器的枚举
首先,您需要一个已安装的编解码器列表,您可以通过调用img_codec_list()来检索该列表。
如果您有关于数据的其他信息(例如,mime-type或扩展名),则可以使用诸如img_codec_list_byext()或img_codec_list_bymime()之类的变量。这将为您提供一个编解码器列表,其中仅包括符合指定标准的编解码器。但是请记住,扩展或mime-type不一定保证数据是特定格式的(也就是说,它们可能存在)。因此,如果处理数据所声称的格式的编解码器失败,那么准备尝试所有编解码器总是很好的。
2. 建立底层输入源
图像数据必须来自文件、TCP/IP套接字或内存缓冲区等源。此步骤涉及建立数据的来源。此步骤可能根本不涉及任何工作(即,如果它是已存储在内存中的文件),也可能涉及打开文件或执行其他任务。
3.将图像库常规IO接口与输入源关联
图像库解码器需要一种传统的方式来访问数据,这就是IO流的来源。使用io_open()将io_stream_t与上一步中的数据源相关联。
4. 数据识别
这一步包括允许您列举的编解码器查看数据,以确定哪个编解码器能够处理数据。您可以使用img_decode_validate()执行此操作,img_decode_validate()贯穿编解码器列表,并指示哪些(如果有的话)批准了数据。然后可以使用该编解码器对数据进行解码。
5.初始化解码器
此步骤通知解码器即将进行解码操作,并允许其设置可能需要的任何资源。使用img_decode_begin()执行此步骤。
6. 解码帧
使用img_decode_frame()对帧进行解码,直到完成或没有其他帧为止(当img_decode_frame()返回IMG_ERR_NODATA时)。
7. 完成解码
调用img_decode_finish()以允许解码器在自身完成后进行清理。
尽管此过程可能看起来很复杂,但有两个更高级别的API调用可以简化此过程:img_load_file()
此函数负责上述所有步骤。但是,此函数仅加载第一帧,并且仅适用于文件源。img_load()
此函数负责所有步骤,但不包括建立输入源并将其与io_stream_t关联。这提供了img_load_file()的便利性,但取消了仅限文件的限制。与img_load_file()一样,它仅限于加载第一帧。
Here’s an example of using 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 be
loaded in the format we specify) by enabling the following two
lines */
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);
Clean up resources
使用完图像库后,通过释放img_t结构中图像库分配的所有内存来进行清理。例如:
• 如果设置了img_t::flags和IMG_DIRECT,则需要释放img_t::access.direct.data。
• 如果设置了img_t::format和IMG_FMT_PALETTE,并且img_t::npalette大于零(0),则需要释放img_t::palette。
• 使用img_lib_detach()从图像库中分离并释放所有相关资源。
• 如果使用io_open()手动创建输入流,请使用io_close()关闭输入流。
• 如果使用屏幕缓冲区显示图像,请释放缓冲区以及屏幕和窗口API函数使用的任何相关内存。
Image API(部分)
图像API包括此处描述的函数和数据类型。
要使用此图像API提供的功能以及此处的数据类型和函数,您需要打开一个I/O流,该流由io_open()和io_close()函数管理。io_open()用于将io_stream_t值与图像数据(文件、TCIP/IP套接字或内存缓冲区)关联。函数的作用是:释放输入流并释放资源。由于io_open()和io_close()不是<img.h>头文件的一部分,因此需要包含<io/io.h>头文件,其中包含<img.h>头文件。因此,要使用图像API,只需包含<io/io.h>头文件即可。
img_lib_attach()
初始化图像库
简介:
#include <img/img.h>
int img_lib_attach( img_lib_t* ilib );
参数:
ilib
函数存储库句柄的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于初始化图像库,查找配置文件,并加载该文件中列出的编解码器。
如果函数找不到配置文件,它仍然会填充有效的库句柄,但不会加载编解码器,并且图像无法解码。在这种情况下,函数返回IMG_ERR_CFG。您可以在库初始化后通过调用img_cfg_read()加载编解码器。
The img.conf Configuration File
图像库使用配置文件确定要加载的编解码器,此函数首先检查环境变量LIBIMG_CFGFILE,它是配置文件的完整路径。如果未设置,则检查默认位置/etc/system/config/img.conf。
配置文件中的编解码器指定为节。配置文件的每个部分都由方括号中的编解码器名称来划分,后面是一个无序的属性列表,指定有关该编解码器的其他信息。应该至少有一个mimetype行和扩展列表与编解码器关联。例如:
[img_codec_jpg.so]
mime=image/jpeg:image/jpg
ext=jpg:jpeg
此示例说明了如何在同一行中指定多个条目,但已从原始行简化。默认配置文件包含更多的mimetype条目。
返回:
IMG_ERR_OK
成功
IMG_ERR_MEM
内存分配失败
IMG_ERR_CFG
配置文件错误或丢失。返回的句柄仍然有效,但尚未预加载任何编解码器。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_lib_detach()
从库中分离
简介:
#include <img/img.h>
void img_lib_detach( img_lib_t ilib );
参数:
ilib
img_lib_attach()填写的库句柄。句柄将不再有效。
库:
libimg:
Use the -l img option to qcc to link against this library.
描述:
此函数将从图像库中分离并释放所有相关资源。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_load()
从流中解码帧
简介:
#include <img/img.h>
int img_load( img_lib_t ilib,
io_stream_t *input,
const img_decode_callouts_t *callouts,
img_t *img );
参数:
ilib
图像库的句柄,由img_lib_attach()返回。
input
输入流
callouts
指向img_decode_callouts_t结构的指针,该结构为解码器提供系统调用。如果为此值指定NULL,则会提供一组默认标注。
Img
函数用解码帧的信息填充的img_t结构的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于解码来自流媒体源的帧。此函数仅对遇到的第一帧进行解码。
返回:
IMG_ERR_OK
成功
IMG_ERR_MEM
内存分配失败
IMG_ERR_FORMAT
找不到合适的编解码器。您需要的编解码器可能丢失或损坏,或者文件可能已损坏。
IMG_ERR_NOSUPPORT
不支持输出数据;编解码器和应用程序无法就输出格式达成一致。IMG_ERR_NODATA
不存在帧数据。
IMG_ERR_CORRUPT
文件中遇到无效数据,导致解码无法继续。部分框架可能完好无损。IMG_ERR_TRUNC
遇到文件过早结束。部分框架可能完好无损。
IMG_ERR_INTR
解码被应用程序中断。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_load_file()
简介:
从文件系统上的文件解码帧
参数:
#include <img/img.h>
int img_load_file( img_lib_t ilib,
const char* path,
const img_decode_callouts_t* callouts,
img_t* img );
参数:
ilib
图像库的句柄,由img_lib_attach()返回。
path
可从中读取数据的文件的完整路径。
callouts
指向img_decode_callouts_t结构的指针,该结构为解码器提供系统调用。如果为此值指定NULL,则会提供一组默认标注。
Img
函数用解码帧的信息填充的img_t结构的地址。
在调用img_load_file()之前,可以重写元素,例如格式:
img.format = IMG_FMT_G8;
img.flags |= IMG_FORMAT;
img_load_file(…);
在上面的示例中,由于格式是在加载之前设置的,所以libimg将强制加载的图像转换为IMG_FMT_G8格式,而不管实际的源图像格式如何。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于解码文件系统上文件中的帧。此函数仅对遇到的第一帧进行解码。
如果要在加载文件时调整其大小,请使用img_load_resize_file()。
返回:
IMG_ERR_OK
成功
IMG_ERR_CORRUPT
文件中遇到无效数据,导致解码无法继续。部分框架可能完好无损。
IMG_ERR_DLL
处理处理文件类型的DLL时出错。检查以确保DLL没有丢失或损坏。IMG_ERR_FILE
访问路径时出错(设置了errno)。
IMG_ERR_FORMAT
找不到合适的编解码器。您需要的编解码器可能丢失或损坏,或者文件可能已损坏。
IMG_ERR_INTR
解码被应用程序中断。
IMG_ERR_MEM
内存分配失败
IMG_ERR_NODATA
不存在帧数据。此错误不太可能发生,因为文件通常至少包含一个帧。IMG_ERR_NOSUPPORT
不支持输出数据;编解码器和应用程序无法就输出格式达成一致。IMG_ERR_TRUNC
遇到文件过早结束。部分框架可能完好无损。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_load_resize_file()
从文件系统上的文件解码帧并调整其大小
简介:
#include <img/img.h>
int img_load_resize_file( img_lib_t ilib,
const char *path,
const img_decode_callouts_t *callouts,
img_t *img );
参数:
ilib
图像库的句柄,由img_lib_attach()返回。
path
可从中读取数据的文件的完整路径。
callouts
指向img_decode_callouts_t结构的指针,该结构为解码器提供系统调用。如果为此值指定NULL,则会提供一组默认标注。
img
函数用解码帧的信息填充的img_t结构的地址。
如果在调用此函数之前设置图像的宽度和高度(img.w和img.h),则图像的大小将调整为适合指定的尺寸,而不是像img_load_file()那样进行剪裁。在解码期间动态执行大小调整,而不会导致加载整个原始图像然后随后调整其大小的内存损失。
如果仅指定一个尺寸,则将根据原始图像的纵横比计算另一个尺寸。
您还需要在img结构中设置相应的维度标志。例如,如果指定宽度,则需要在标志中设置IMG_W位。
库:
libimg
Use the -l img option to qcc to link against this library.
此函数用于解码文件系统上文件中的帧,如果指定了图像宽度和高度,还可以选择调整其大小。此函数仅对遇到的第一帧进行解码。
如果在调用此函数之前未指定图像的高度和宽度,则图像库会将高度和宽度设置为图像的原始大小。当调用其调用时,应用程序可以选择调整图像的大小。
至少支持以下标注:
• set_value_f
• choose_format_f
返回:
IMG_ERR_OK
成功
IMG_ERR_CORRUPT
文件中遇到无效数据,导致解码无法继续。部分框架可能完好无损。
IMG_ERR_DLL
处理处理文件类型的DLL时出错。检查以确保DLL没有丢失或损坏。
IMG_ERR_FILE
访问路径时出错(设置了errno)。
IMG_ERR_FORMAT
找不到合适的编解码器。您需要的编解码器可能丢失或损坏,或者文件可能已损坏。
IMG_ERR_INTR
应用程序中断了解码。
IMG_ERR_MEM
内存分配失败。
IMG_ERR_NODATA
不存在帧数据。此错误不太可能发生,因为文件通常至少包含一个帧。
IMG_ERR_NOSUPPORT
不支持输出数据;编解码器和应用程序无法就输出格式达成一致。
IMG_ERR_TRUNC
遇到文件过早结束。部分框架可能完好无损。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_codec_list()
枚举编解码器
简介:
#include <img/img.h>
size_t img_codec_list( img_lib_t ilib,
img_codec_t* buf,
size_t nbuf,
img_codec_t* exclude,
size_t nexclude );
参数:
ilib
图像库的句柄,由img_lib_attach()返回
buf
函数用可用编解码器的句柄填充的数组地址。
nbuf
buf数组中的项数。
exclude
希望函数从列表中排除的编解码器句柄数组的地址。
nexclude
排除数组中的项数。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数列出安装的所有编解码器,排除指定的编解码器除外。
该函数最多可将nbuf句柄复制到buf指定的数组中。如果nbuf为0,则不进行复制。此函数返回匹配编解码器的总数,如果缓冲区不够大,无法存储所有匹配的编解码器,则该总数可能大于nbuf。
返回:
匹配的编解码器的总数。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_codec_list_byext()
按文件扩展名枚举编解码器
简介:
#include <img/img.h>
size_t img_codec_list_byext( img_lib_t ilib,
const char* string,
img_codec_t* buf,
size_t nbuf);
参数:
ilib
图像库的句柄,由img_lib_attach()返回。
string
包含要标识的文件扩展名的字符串。例如,.jpg或my_file.jpg,用于处理JPEG的编解码器。
延期必须以句点开始。
buf
函数用可用编解码器的句柄填充的数组地址。
nbuf
buf数组中的项数。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数枚举处理具有指定扩展名的文件的编解码器。
虽然没有定义什么是扩展以及如何命名的标准,但似乎有一个事实上的标准来管理它们的使用。术语“扩展名”起源于固有的文件名属性,尽管大多数现代实现不再将其视为文件名的单独组件。因此,该术语已演变为松散地描述文件名中最后一次出现的字符之后的字符部分。性格这一原则可以在整个万维网以及许多使用扩展作为内容识别机制的操作系统中看到。虽然扩展本身并不保证文件包含的数据的性质,但它们通常是从已知集合中适当分配的,因此,它们代表了决定哪一个编解码器应该处理数据的合理标准,至少在初始过程中是这样。
该函数最多可将nbuf句柄复制到buf指定的数组中。如果nbuf为0,则不进行复制。此函数返回匹配编解码器的总数,如果缓冲区不够大,无法存储所有匹配的编解码器,则该总数可能大于nbuf。
返回:
匹配的编解码器的总数。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_codec_list_bymime()
按MIME类型枚举编解码器
简介:
#include <img/img.h>
size_t img_codec_list_bymime( img_lib_t ilib,
const char* mime,
img_codec_t* buf,
size_t nbuf );
参数:
ilib
图像库的句柄,由img_lib_attach()返回。
mime
描述所需MIME类型的字符串(根据RFC 2046)。
buf
函数用可用编解码器的句柄填充的数组地址。
nbuf
buf数组中的项目数。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数枚举处理指定MIME类型的编解码器。
该函数最多可将nbuf句柄复制到buf指定的数组中。如果nbuf为0,则不进行复制。此函数返回匹配编解码器的总数,如果缓冲区不够大,无法存储所有匹配的编解码器,则该总数可能大于nbuf。
返回:
匹配的编解码器的总数。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
io_open()
初始化IO流
简介:
#include <io/io.h>
io_stream_t *io_open( io_open_f *open_f,
io_mode_t mode, …)
参数:
open_f
指向建立流的函数的指针。该库提供了两个函数:IO_FD()(用于基于FD的读/写)和IO_MEM()(用于基于内存缓冲区的读/写)。见下文。
mode
打开模式,IO_READ或IO_WRITE。
…
其他参数取决于指定的开度,如下所述。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于初始化流。该流可以是基于fd的,也可以是内存缓冲区,具体取决于指定的open_f:
IO_FD()
unix类型fd的缓冲流。需要一个额外的参数:一个int,指定(先前打开的)准备读取或写入的fd。
IO_MEM()
对内存缓冲区的流式支持。需要其他参数(按顺序):
1.用于指定内存缓冲区大小的无符号字符。这必须是非零。
2.用于指定缓冲区地址的空指针
当应用程序完成一个流时,它应该调用io_close()来释放它。
返回:
指向流对象的指针,如果发生错误(设置了errno),则为NULL。
错误:
ENOMEM
内存不足,无法分配结构。
EINVAL
打开模式无效。
ENOTSUP
流不支持模式。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
io_close()
释放输入流
简介:
#include <io/io.h>
void io_close( io_stream_t *stream );
参数:
stream
指向io_open()返回的流对象的指针。
库:
Libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于释放与输入流关联的资源。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_decode_validate()
查找用于解码的编解码器
简介:
#include <img/img.h>
int img_decode_validate( const img_codec_t *codecs,
size_t ncodecs,
io_stream_t *input,
unsigned *codec );
参数:
codes
指向img_codec_t句柄数组的指针,提供要尝试的编解码器列表。函数将按顺序尝试每个编解码器,直到找到验证流中数据的编解码器。
ncodecs
编解码器阵列中的项目数。
input
输入源。
codec
函数存储验证数据流的编解码器索引的无符号值的地址。如果找不到这样的编解码器,该内存将保持不变。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于查找用于解码的合适编解码器。
返回:
操作状态:
IMG_ERR_OK
成功找到了合适的编解码器。检查codec以获取验证数据流的codec阵列中的codec索引。
IMG_ERR_DLL
处理处理文件类型的DLL时出错。检查以确保DLL没有丢失或损坏。
IMG_ERR_FORMAT
没有安装的编解码器将输入数据识别为其支持的格式。这可能意味着数据的格式不受支持,或者数据流已损坏。
IMG_ERR_OK
编解码器未提供此功能的实现。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_decode_begin()
准备解码流中的一个或多个帧
简介:
#include <img/img.h>
int img_decode_begin( img_codec_t codec,
io_stream_t *input,
uintptr_t *decode_data );
参数:
codec
要使用的编解码器。要找出要使用的编解码器,请参阅img_codec_list、list_byext、list_bymime和img_decode_validate。
input
输入源。
decode_data
uintptr_t的地址,解码器使用该地址存储解码过程中所需的数据。不应传递NULL,而应传递初始化为0的uintptr_t的有效地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数准备对流中的一帧(或一系列帧)进行解码。
返回:
IMG_ERR_OK
成功
IMG_ERR_NOTIMPL
编解码器未提供此功能的实现。
Other
解码器的begin()函数可能传回以标记错误的任何其他代码(有关已定义错误的列表,请参阅img_errno.h)。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_decode_frame()
解码帧
简介:
#include <img/img.h>
int img_decode_frame( img_codec_t codec,
io_stream_t *input,
const img_decode_callouts_t *callouts,
img_t *img,
uintptr_t *decode_data );
参数:
codec
用于解码帧的编解码器的句柄。
input
输入源。
callouts
指向img_decode_callouts_t结构的指针,该结构为解码器提供系统调用。如果将此值传递为NULL,则将使用一组默认标注。有关更多详细信息,请参阅img_decode_callouts_t的说明。
img
一个img_t结构的地址,用来填充有关解码帧的信息。
decode_data
用于img_decode_begin()的uintptr_t的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于解码帧。您需要先调用img_decode_begin()来准备解码,然后调用img_decode_finish()来释放分配给解码的任何资源。
返回值:
IMG_ERR_OK
成功。整个画面被解码了。
IMG_ERR_OK
内存分配失败。
IMG_ERR_NOSUPPORT
不支持输出数据格式;编解码器和应用程序无法就输出格式达成一致。
IMG_ERR_NODATA
不存在帧数据。此返回代码表示多帧数据源的结束。
IMG_ERR_CORRUPT
流中遇到无效数据,导致解码无法继续。部分框架可能完好无损。
IMG_ERR_TRUNC
遇到数据过早结束。部分框架可能完好无损。
IMG_ERR_INTR
解码被应用程序中断。
IMG_ERR_DLL
访问编解码器DLL时出错;检查errno和/或尝试使用DL_DEBUG=1运行应用程序。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_decode_finish()
释放解码资源
简介:
#include <img/img.h>
int img_decode_finish( img_codec_t codec,
io_stream_t *input,
uintptr_t *decode_data );
参数:
codec
用于解码的编解码器的句柄。
input
指向图像数据输入流的指针。
decode_data
用于img_decode_begin()和img_decode_frame()的uintptr_t的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数完成解码过程并释放解码会话期间分配的资源。您应该在完成一系列帧的解码后调用此函数,以释放解码器可能已分配的与这些帧相关的任何资源。
您不需要解码流中的所有帧,但在解码您感兴趣的帧后,应始终使用img_decode_finish(),以避免潜在的内存泄漏。
返回:
IMG_ERR_OK
成功
IMG_ERR_NOTIMPL
编解码器未提供此功能的实现。
Other
解码器的begin()函数可能传回以标记错误的任何其他代码(有关已定义错误的列表,请参阅img_errno.h)。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_encode_begin()
准备将一个或多个帧编码到流
简介:
#include <img/img.h>
int img_encode_begin( img_codec_t codec,
io_stream_t *output,
uintptr_t *encode_data );
参数:
codec
要使用的编解码器。要找出要使用的编解码器,请参阅img_codec_list()、img_codec_list_byext()和img_codec_list_bymime()。
output
输出目标
encode_data
uintptr¬¬¬_t地址,编码器使用该地址在整个编码过程中存储所需的数据。传递初始化为0(非空)的uintptr_t的有效地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数准备将一帧(或一系列帧)编码为流。
返回:
IMG_ERR_OK
成功
IMG_ERR_NOTIMPL
编解码器未提供此功能的实现。
Other
编码器的encode_begin()函数可能传回以标记错误的任何其他代码(有关已定义错误的列表,请参阅img_errno.h)。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_encode_finish()
释放编码资源
简介:
#include <img/img.h>
int img_encode_finish( img_codec_t codec,
io_stream_t *output,
uintptr_t *encode_data );
参数:
codec
用于编码的编解码器的句柄。
output
指向图像数据的输出流的指针。
encode_data
用于img_encode_begin()和img_encode_frame()的uintptr_t的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
他的功能完成编码过程并释放编码会话期间分配的资源。您应该在完成一系列帧的编码后调用此函数,以释放编码器可能已分配的与这些帧相关联的任何资源。
返回:
IMG_ERR_OK
成功
IMG_ERR_NOTIMPL
编解码器未提供此功能的实现。
Other
解码器的encode_finish()函数可能传回以标记错误的任何其他代码(有关已定义错误的列表,请参阅img_errno.h)。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_encode_frame()
对帧进行编码
简介:
#include <img/img.h>
int img_encode_frame( img_codec_t codec,
io_stream_t *output,
const img_encode_callouts_t *callouts,
img_t *img,
uintptr_t *encode_data );
参数:
codec
用于对帧进行编码的编解码器的句柄。
output
输出目标。
callouts
指向img_encode_callouts_t结构的指针,该结构为编码器提供系统调用。如果将此值传递为NULL,则库将使用一组默认标注。有关更多详细信息,请参见img_encode_callouts_t的说明。
img
描述要编码的帧的img_t结构的地址。
encode_data
用于img_encode_begin()的uintptr_t的地址。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数用于对帧进行编码。您需要先调用img_encode_begin()来准备编码,然后调用img_encode_finish()来释放分配给编码的任何资源。
返回:
IMG_ERR_OK
成功完整的帧被编码。
IMG_ERR_MEM
内存分配失败。
IMG_ERR_NOSUPPORT
不支持输入数据格式;编解码器和应用程序无法就输出格式达成一致。
IMG_ERR_TRUNC
写入数据时出错;文件被截断。
IMG_ERR_INTR
编码被应用程序中断。
IMG_ERR_DLL
访问编解码器DLL时出错;检查errno和/或尝试使用DL_DEBUG=1运行应用程序。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_cfg_read()
读取配置文件并加载编解码器
简介:
#include <img/img.h>
int img_cfg_read (img_lib_t ilib,
const char *path )
参数:
ilib
img_lib_attach()填写的库句柄。
path
要读取的配置文件的路径。
库:
libimg
Use the -l img option to qcc to link against this library.
描述:
此函数读取路径指定的配置文件,并加载其中列出的编解码器。
有关配置文件格式的说明,请参见img_lib_attach()。
返回:
IMG_ERR_OK
成功
IMG_ERR_MEM
内存分配失败
IMG_ERR_CFG
无法打开指定的文件,或者该文件的格式不正确。
分类:
Image library
Safety:
Interrupt handler No
Signal handler No
Thread No
img_decode_callouts_t
解码器调用表
简介:
#include <img/img.h>
typedef struct {
img_decode_choose_format_f *choose_format_f;
img_decode_setup_f *setup_f;
img_decode_abort_f *abort_f;
img_decode_scanline_f *scanline_f;
img_decode_set_palette_f *set_palette_f;
img_decode_set_transparency_f *set_transparency_f;
img_decode_frame_f *frame_f;
img_decode_set_value_f *set_value_f;
uintptr_t data;
} img_decode_callouts_t;
描述:
img_decode_callouts_t结构定义了一个解码器callout表。它为解码器提供了一个调用列表,供其在解码的各个阶段调用:
• img_decode_choose_format_f *choose_format_f
• img_decode_setup_f *setup_f
• img_decode_abort_f abort_f
• img_decode_scanline_f scanline_f
• img_decode_set_palette_f *set_palette_f
• img_decode_set_transparency_f *set_transparency_f
• img_decode_frame_f *frame_f
• img_decode_set_value_f *set_value_f
• uintptr_t data
img_decode_choose_format_f *choose_format_f
指向从解码器提供的列表中选择图像格式的函数的指针。您将首先获得此标注(除非预先选择了格式,在这种情况下,它将根本不会被调用)。
该函数采用以下形式:
typdef unsigned (img_decode_choose_format_f) (
uintptr_t data,
img_t *img,
const img_format_t formats,
unsigned nformats );
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值
img
指向部分填充的img_t结构的指针,提供有关帧的重要信息。
formats
可供选择的img_format_t格式数组。
nformats
格式数组中的元素数。
如果未提供choose_format()标注,则库将提供一个默认值,用于选择列表中的第一种格式。
函数应返回formats数组内的索引,或一个越界值(例如,nformats),以指示不需要任何格式;解码器将IMG_ERR_NOSUPPORT的情况下出错。
或者,它可以返回一个越界值(例如,nformats),以指示任何格式都不可接受。在这种情况下,它可以通过设置img->format并断言img->flags的IMG_FORMAT位来选择不同的格式。在这种情况下,最终结果将与加载时间之前最初选择的格式相同。
img_decode_setup_f setup_f
指向执行开始帧解码所需的任何设置的函数的指针。
该函数采用以下形式:
typedef int (img_decode_setup_f) ( uintptr_t data,
img_t img,
unsigned flags );
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值。
img
指向部分填充的img_t结构的指针,提供有关被解码帧的重要信息。
flags
标记以提供有关数据及其到达方式的提示,这些提示可能会影响函数所做的假设和操作。标志可以具有以下值:
MG_SETUP_PAL_SHARED-调色板(如果有)可以在解码过程中在该帧和其他帧之间共享。这对于多帧格式很有意义,但在其他情况下可以忽略。
I MG_SETUP_TOP_DOWN -扫描线按顺序完成,从上到下移动
IMG_SETUP_BOTTOM_UP -扫描线按顺序完成,从下向上移动
IMG_SETUP_MULTIPASS-扫描线处理在多个通道中分段(例如,平面和某些隔行方案)。
IMG_SETUP_READONLY-数据(img)应为只读。如果在标志中指定了此值,则不要修改数据。否则,对图像库函数的某些调用(例如,img_load_resize_file())将导致错误。
您的设置功能可以(但不必)设置img_t的访问字段。此字段告诉解码器如何记录正在解码的图像数据。您可以通过设置img->access.direct或img->access.indirect并断言适当的标志IMG_DIRECT或IMG_INDIRECT来设置它。
或者,调用img_decode_frame()(或img_load_file()等)的代码可以在调用img_decode_frame()、img_load_file()等之前进行设置,或者您可以依赖库的默认行为,即从系统RAM为图像和/或调色板分配内存(只有在尚未设置IMG_DIRECT、IMG_INDIRECT和IMG_PALETTE标志时,库才会执行此操作)。
如果您依赖此默认行为,则可以稍后通过简单地释放img_t::access.direct.data或img_t::palete(但不能同时释放两者)来释放内存。只有在图像解码成功时才需要这样做,并且只有在处理完图像后才需要这样做。您不必担心解码失败时释放内存,因为这是自动完成的。
如果一切正常,它应该返回IMG_ERR_OK,否则返回一些其他错误代码。IMG_ERR_OK之外的任何内容都会导致解码停止,错误代码会传播回应用程序。
img_decode_abort_f abort_f
指向在解码失败时调用的函数的指针(在调用setup_f之后)。库将自动释放它作为设置的一部分分配的任何内存(如果您依赖上面在img_decode_setup_f中描述的默认行为)。
该函数采用以下形式:
typedef void (img_decode_abort_f) (
uintptr_t data,
img_t img );
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值。
info
指向需要释放的img_t结构的指针。
img_decode_scanline_f scanline_f
指向函数的指针,该函数在扫描线解码时被调用以通知应用程序。
该函数采用以下形式:
typedef int (img_decode_scanline_f) (
uintptr_t data,
img_t img,
unsigned row,
unsigned npass_line,
unsigned npass_total );
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值。
img
指向描述帧的img_ t的指针。
row
已解码扫描线的索引。扫描线从0(最上面的扫描线)到(h-1)开始编号,其中h表示图像的高度。
npass_line
完成扫描线所需的额外通过次数(在此通过之后)。平面格式和某些隔行格式跨多个过程分割扫描线,一次只传送部分数据(当在setup_f()callout中设置IMG_SETUP_MULTIPASS标志位时就是这种情况)。当该值为0时,您知道扫描线已完成。
npass_total
完成整个帧剩余的额外扫描线过程数(在此过程之后)。当此值作为0传入时,您将知道帧已完成。
此总数包括部分过程,其中IMG_SETUP_MULTIPASS标志是在setup_f() callout中设置的。如果未设置此标志,则“扫描线通过”相当于“扫描线完成”,即npass_total反映剩余待解码的行数。在任何一种情况下,该值都会给出剩余总工作量与已完成工作量的比较。
此函数应返回IMG_ERR_OK以继续解码,或返回其他值以中止解码。返回的代码将传播回应用程序。通常,在这种情况下,IMG_ERR_INTR是一个很好的值,除非您希望使用另一个值。
img_decode_set_transparency_f set_transparency_f
指向一个函数的指针,该函数通知应用程序图像具有透明颜色,这意味着图像的设计者打算将图像中的特定颜色视为透明。源图像中该颜色的像素不应渲染到目标。
此函数仅适用于支持颜色遮罩形式的透明度的图像格式(与通过alpha混合实现的透明度相反),目前仅适用于GIF格式。
该函数采用以下形式:
typedef void (img_decode_set_transparency_f) (
uintptr_t data,
img_t img,
img_color_t color );
此函数的参数为:
data
应用程序数据-img_decode¬_callouts_t数据成员的值。
img
指向描述帧的img_t的指针。
color
要视为透明的颜色。该值将为:
基于调色板或IMG_FMT_G8的索引号(0-255)
16bpp格式的16位值(编码与图像格式相同)
24或32 bpp格式的32位值(编码为IMG_FMT_PKHE_ARGB888)
当您收到此标注时,img_t的透明度字段将已设置。此调用的唯一原因是由于存在透明度而进行额外处理。
mg_decode_set_palette_f set_palette_f
指向通知应用程序图像调色板的函数的指针。在对主体进行任何解码之前,在设置之后调用此函数。
如果不提供标注,或提供的标注返回非零,库会将调色板数据复制到img->palette指向的缓冲区中(如果设置了IMG_PALETTE标志位),并根据需要将数据转换为IMG_FMT_PKHE_ARGB8888(img_color_t的正确表示)。如果提供的详图索引返回0,则不会进行复制。
该函数采用以下形式:
typedef int (img_decode_set_palette_f) (
uintptr_t data,
img_t *img,
const uint8_t palette,
img_format_t format );
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值。
img
指向描述帧的img_ t的指针。
palette
指向为图像设置的调色板的指针。调色板数据的格式由format描述。
format
调色板的格式。如果希望将调色板数据复制到img->palette,则返回0,或者返回非零以指示不希望进行此复制/转换。
如果一切正常,它应该返回IMG_ERR_OK,否则返回一些其他错误代码。IMG_ERR_OK之外的任何内容都会导致解码停止,错误代码会传播回应用程序。
img_decode_frame_f frame_f
指向一个函数的指针,该函数在帧成功解码后调用。
该函数采用以下形式:
typedef void ( img_decode_frame_f ) (
uintptr_t data,
img_t img );
img_decode_set_value_f set_value_f
指向函数的指针,该函数被调用以告知应用程序在文件中遇到的其他属性。
该函数采用以下形式:
typedef int (img_decode_set_value_f) (
uintptr_t data,
img_t *img,
unsigned type,
uintptr_t value );
某些图像文件格式指定了img_t中未表示的其他信息,例如DPI、x/y位置、注释等。此调出的目的是为应用程序提供接收此信息的方式。
当前,仅当处理渐进式图像(例如渐进式JPEG图像文件)时才会调用此调用。
此函数的参数为:
data
应用程序数据-img_decode_callouts_t数据成员的值。
img
指向描述帧的img_t的指针。
类型
img_value_type枚举中的一个类型。
value
请参阅img_value_type枚举。
img_value_type枚举提供库使用的值类型,其形式如下:
#include <img/img.h>
enum img_value_type {
IMG_VALUE_TYPE_INVALID = 0,
IMG_VALUE_TYPE_PROGRESSIVE,
IMG_VALUE_TYPE_ANIM_PLAY_COUNT,
IMG_VALUE_TYPE_ANIM_FRAME_DELAY,
IMG_VALUE_TYPE_FRAME_COUNT
};
枚举具有以下可能的值类型:
IMG_VALUE_TYPE_INVALID
不是有效的类型。
IMG_VALUE_TYPE_PROGRESSIVE
指示图像是渐进式还是非渐进式。值0表示非逐行扫描图像,值1表示逐行扫描图像。
IMG_VALUE_TYPE_ANIM_PLAY_COUNT
应播放动画的次数。值为0表示永远玩。
IMG_VALUE_TYPE_ANIM_FRAME_DELAY
必须显示当前帧的最短时间(毫秒)
IMG_VALUE_TYPE_FRAME_COUNT
图像中的帧数。此值永远不为0。
实现set_value_f()调用不需要编解码器。要么信息不可用,要么应假定合理的默认值(参见img_value_type)。
如果一切正常,它应该返回IMG_ERR_OK,否则它应该返回一些其他错误代码。除IMG_ERR_OK之外的任何操作都会导致解码停止,并将错误代码传播回应用程序。
uintptr_t data
用户定义的数据作为附加参数传递给标注。
分类:
Image library
img_encode_callouts_t
编码器标注表
简介:
include <img/img.h>
typedef struct {
img_encode_choose_format_f *choose_format_f;
img_encode_setup_f *setup_f;
img_encode_abort_f *abort_f;
img_encode_scanline_f *scanline_f;
img_encode_set_palette_f *get_palette_f;
img_encode_set_transparency_f *get_transparency_f;
img_encode_frame_f *frame_f;
uintptrt_t data;
} img_encode_callouts_t;
描述:
img_encode_callouts_t结构定义了编码器标注表。它为编码器提供了一个调用列表,供其在编码的各个阶段调用:
• img_encode_choose_format_f choose_format_f
• img_encode_setup_f setup_f
• img_encode_abort_f* abort_f
• img_encode_scanline_f* scanline_f
• img_encode_get_transparency_f* get_transparency_f
• img_encode_get_palette_f* get_palette_f
• img_encode_frame_f* frame_f
• uintptrt_t data
img_encode_choose_format_f *choose_format_f
指向从解码器提供的列表中为图像选择替代格式的函数的指针。这是编码过程中调用的第一个调用,但仅当编码器无法表示所提供图像的格式时才会调用。在这种情况下,应用程序可能准备以所请求的格式之一提供数据,或者可能完全中止编码。
该函数采用以下形式:
typdef unsigned (img_encode_choose_format_f) (
uintptrt_t data,
const img_t *img,
const img_format_t formats,
unsigned nformats );
此函数的参数为:
data
应用程序数据—img_encode_callouts_t的数据成员的值。
img
指向描述正在编码的帧的img_t结构的指针。
format
可供选择的可能的img_format_t格式的数组。
nformat
格式数组中的元素数。
如果不提供choose_format()标注,库将选择与提供的图像最匹配的格式,并根据需要自动将数据转换为该格式。
函数应返回formats数组内的索引,或一个越界值(例如,nformats),以指示不需要任何格式;编码器将在IMG_ERR_NOSUPPORT的情况下出错。
img_encode_setup_f setup_f
指向执行开始帧编码所需的任何设置的函数的指针。
该函数采用以下形式:
typedef int (img_encode_setup_f) (
uintptrt_t data,
img_t img,
unsigned flags );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t数据成员的值。
img
指向描述正在编码的帧的img_t结构的指针。
flags
标记以提供有关数据编码方式的提示,这可能会影响函数所做的假设和操作。它可以具有以下值:
IMG_SETUP_TOP_DOWN-扫描线按顺序编码,自上而下移动
IMG_SETUP_BOTTOM_U-扫描线按顺序编码,自下而上移动
IMG_SETUP_MULTIPASS-扫描线在多个通道中分段(例如,平面和某些隔行方案)。
如果一切正常,此函数应返回IMG_ERR_OK,否则返回其他错误代码。IMG_ERR_OK之外的任何内容都会导致编码停止,错误代码会传播回应用程序。
img_encode_abort_f abort_f
指向在编码失败时调用的函数的指针(在调用setup_f()之后)。
该函数采用以下形式:
typedef void (img_encode_abort_f) (
uintptrt_t data,
img_t img );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t的数据成员的值。
img
指向描述正在编码的帧的img_t结构的指针。
img_encode_scanline_f scanline_f
指向函数的指针,该函数在扫描线编码后被调用以通知应用程序。
该函数采用以下形式:
typedef int (img_encode_scanline_f) (
uintptrt_t data,
img_t img,
unsigned row,
unsigned npass_line,
unsigned npass_total );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t的数据成员的值。
img
指向描述正在编码的帧的img_t的指针。
row
已编码扫描线的索引。扫描线编号从0(最上面的扫描线)开始,到图像高度-1。
npass_line
完成扫描线所需的额外通过次数(在此通过之后)。平面格式和某些隔行格式跨多个过程分割扫描线,一次只对部分数据进行编码(当在setup_f()callout中设置IMG_SETUP_MULTIPASS标志位时就是这种情况)。当该值为0时,您知道扫描线已完成。
npass_total
完成整个帧剩余的额外扫描线过程数(在此过程之后)。当此值作为0传入时,您将知道帧已完成。
此总数包括部分过程,其中IMG_SETUP_MULTIPASS标志是在setup_f()调用中设置的。如果未设置此标志,则“扫描线通过”相当于“扫描线完成”,即npass_total反映了剩余待编码的行数。在任何一种情况下,该值都会给出剩余总工作量与已完成工作量的比较。
此函数应返回IMG_ERR_OK以继续编码,或返回其他值以中止编码。返回的代码将传播回应用程序。通常,在这种情况下,IMG_ERR_INTR是一个很好的值,除非您希望使用另一个值。
img_encode_get_transparency_f get_transparency_f
指向满足图像透明度颜色要求的函数的指针。仅当出于某种原因,img_t的透明度字段中未准确表示透明度颜色时,才需要提供此功能。
该函数采用以下形式:
typedef int (img_encode_get_transparency_f) (
uintptrt_t data,
img_t *img,
img_color_t color );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t的数据成员的值。
img
指向描述帧的img_ t的指针。
color
指向要用透明颜色填充的img_color_t的指针。此数据的格式应与帧数据本身的格式匹配。
如果不提供此详图索引,库将根据需要自动使用和转换图像透明度字段。
此函数应返回IMG_ERR_OK以表示请求字段的有效性。如果返回一些其他值,编码器将忽略透明度,并且它不会在生成的编码数据中表示。编码将继续进行。
img_encode_get_palette_f get_palette_f
指向满足图像调色板请求的函数的指针。仅当出于某种原因,img_t中未准确表示调色板时,才需要提供此功能。
该函数采用以下形式:
typedef int (img_encode_get_palette_f) (
uintptrt_t data,
img_t *img,
uint8_t palette,
img_format_t format );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t的数据成员的值。
img
指向描述正在编码的帧的img_t的指针。
palette
指向用调色板数据填充的缓冲区的指针。
format
编码器希望调色板数据采用的格式。
如果一切正常,此函数应返回IMG_ERR_OK,否则返回其他错误代码。IMG_ERR_OK之外的任何内容都会导致编码停止,错误代码会传播回应用程序。
img_encode_frame_f frame_f
指向一个函数的指针,该函数在帧成功编码后调用。
该函数采用以下形式:
typedef void ( img_encode_frame_f ) (
uintptrt_t data,
img_t *img );
此函数的参数为:
data
应用程序数据-img_encode_callouts_t数据成员的值。
img
指向描述正在编码的帧的img_ t的指针。
uintptrt_t data
用户定义的数据作为附加参数传递给标注。
分类:
Image library
img_t
描述图像的信息
简介:
#include <img/img.h>
typedef struct {
union {
struct {
uint8 *data;
unsigned stride;
} direct;
struct {
img_access_f *access_f;
Uintptrt data;
} indirect;
} access;
unsigned w, h;
img_format_t format;
unsigned npalette;
img_color_t *palette;
unsigned flags;
union {
uint8 index;
uint16 rgb16;
img_color_t rgb32;
} transparency;
unsigned quality;
} img_t;
描述:
img_t结构描述解码帧。成员包括:
access
直接和间接两种结构的并集,具体取决于您希望直接还是间接访问图像数据。应设置IMG_DIRECT(直接)或IMG_INDIRECT(间接)标志,以指示采用哪种访问模式。
使用直接访问模型,任何对图像数据进行操作的人都可以通过指针直接访问图像数据。图像数据的开头由direct.data指向,并且假设指向的数据是一个连续的缓冲区,每个缓冲区包含h个direct.stride字节的扫描线。
跨距可以比以指定格式表示单个扫描线所需的实际字节数大得多(如果需要);任何对映像进行操作的人都不应覆盖或以其他方式考虑“中间”填充字节。
使用间接访问模型,任何对图像数据进行操作的人都可以通过一个函数进行访问;函数指针由indirect.access_f给出,而indirect.data提供了一种工具,可以为访问函数提供一些上下文。
访问函数是您提供的一种函数,用于向图像或从图像中读取或写入一系列像素。访问函数必须编码为读写器,无法从参数中判断数据流的方向。
void access_f(uintptr_t data, unsigned x,
unsigned y, unsigned n, uint8_t *pixels)
• data —数据字段(来自img_t::access.indirect.data)
• x, y —正在访问的像素运行图像中的x和y位置
• n —运行中的像素数
• pixels —指向像素数据的指针。如果您的函数是读卡器,它应该将指定的图像数据运行复制到此缓冲区;如果是写操作,则应将缓冲区中的像素复制到图像中
以像素为单位的数据格式将与图像格式相同;也就是说,此级别不需要数据转换。x、y和n参数保证不会超出图像的边界,因此您不必进行检查。
w,h
图像帧的宽度和高度,以像素为单位。仅当设置了IMG_W和IMG_H标志位时,这些成员才有效。
format
图像像素数据的img_format_t。如果设置了IMG_FORMAT标志位,则此字段有效。
npalette
图像调色板颜色表中的颜色数。仅当格式基于调色板(即,IMG_FMT_PALETTE位设置为format)时,才应使用此字段。
palette
调色板颜色表。如果设置了IMG_PALETTE标志位,则此字段有效。
flags
指示结构中哪些字段有效的标志。可以是一个或多个:
IMG_TRANSPARENCY
“透明度”字段有效,图像中指定的颜色应视为透明。
IMG_FORMAT
格式字段有效。
IMG_W
w字段是有效的。
IMG_H
h字段是有效的。
IMG_DIRECT
直接字段是有效的。
IMG_INDIRECT
间接字段有效。
IMG_PALETTE
调色板字段有效。
IMG_QUALITY
“质量”字段有效。
IMG_PAL8_ALPHA
PAL8图像调色板包含alpha数据。因此,可以将颜色值视为8888而不是888。
IMG_TRANSPARENCY_TO_ALPHA
如果目标格式支持,将透明度转换为alpha值。即使不支持色度,该功能也允许利用透明度。
IMG_TRANSPARENCY_TO_ALPHA
指示源图像是否包含任何类型的透明度。此标志仅由图像库设置。应用程序无法设置此标志,但可以使用它来确定是否存在用于优化的透明度。
transparency
透明颜色。仅当设置了IMG_TRANSPARENCY标志位时,此选项才有效。应使用的联合字段取决于图像的格式:
index-用于基于调色板或灰度图像(IMG_FMT_PALETTE位设置为格式或格式为IMG_FMT_G8)
rgb16-用于16bpp图像。编码方式与图像数据相同。
rgb32-用于24或32 bpp RGB图像。编码始终为IMG_FMT_PKHE_ARGB8888。
quality
如果设置了IMG_QUALITY标志,则编解码器可以处理新img_t成员的未签名质量。例如,img_codec_jpg.so将使用此值确定编码的输出质量。例如,当调用img_write()时。
分类:
Image library
img_format_t
图像格式
简介:
#include <img/img.h>
typedef enum {
…
} img_format_t;
描述:
img_format_t是这些可能的图像格式的枚举:
IMG_FMT_INVALID
无效的图像格式
IMG_FMT_MONO
单色位图,1位/像素,每字节8像素。
IMG_FMT_G8
8位/像素灰度贴图。
IMG_FMT_PAL1
1位/像素索引到包含2个条目的调色板中,每个字节包含8个像素。
IMG_FMT_PAL4
4位/像素索引到最多16个条目的调色板中,每个字节压缩2个像素。
IMG_FMT_PAL8
8位/像素索引到最多256个条目的调色板中。
IMG_FMT_PKLE_RGB565
16位/像素RGB压缩为16位小端整数类型,位0-4表示B,位5-10表示G,位11-15表示R。
IMG_FMT_PKBE_RGB565
IMG_FMT_PKLE_RGB565的大端版本
IMG_FMT_PKLE_ARGB1555
16位/像素ARGB压缩为16位小端整数类型,其中位0-4表示B,位5-9表示G,位10-14表示R,位A为最高有效位。
IMG_FMT_PKBE_ARGB1555
IMG_FMT_PKLE_ARGB1555的大端版本
IMG_FMT_BGR888
24位/像素BGR,每个通道8位作为有序字节序列。
IMG_FMT_RGB888
24位/像素RGB,每个通道8位作为有序字节序列。
IMG_FMT_RGBA8888
32位/像素RGBA,每个通道8位作为有序字节序列。
IMG_FMT_PKLE_ARGB8888
32位/像素ARGB压缩为32位小端整数类型,字节0(最低有效字节)表示B,字节1表示G,字节2表示R,字节3表示A。
IMG_FMT_PKBE_ ARGB8888
IMG_FMT_PKLE_ ARGB8888的大端版本
IMG_FMT_PKLE_XRGB8888
24位/像素BGR,每个通道8位作为有序字节序列,后跟单字节填充。
IMG_FMT_PKBE_XRGB888
IMG_FMT_PKLE_ XRGB8888的大端版本
除了上面列出的PKLE和PKBE变体外,还有PKHE和PKOE变体,可以更容易地识别主机端(HE)格式和其他端(OE)。例如,如果代码在x86平台上执行,IMG_FMT_PKHE_ARGB1555等于IMG_FMT_PKLE_ARGB1555。
分类:
Image library
Synchronization services(同步服务)
QNX Neutrino RTOS提供POSIX标准线程级同步原语,其中一些即使在不同进程的线程之间也很有用。
同步服务至少包括以下内容:
Synchronization service Supported between processes Supported across a QNX Neutrino LAN
Mutexes
Yesa No
Condvars
Yes No
Barriers
Yesa No
Sleepon locks
No No
Reader/writer locks
Yesa No
Semaphores
Yes Yes (named only)
FIFO scheduling
Yes No
Send/Receive/Reply
Yes Yes
Atomic operations
Yes No
在进程之间共享这种类型的对象可能是一个安全问题;请参阅本章后面的“在进程之间安全共享互斥锁、屏障和读写器锁”。
上述同步原语由内核直接实现,除了:
barriers, sleepon locks, and reader/writer locks (which are built from mutexes and condvars)
atomic operations (which are either implemented directly by the processor or emulated in the kernel)
您应该只在普通内存映射中分配mutexes, condvars, barriers, reader/writer locks和semaphores,以及您计划对其使用原子操作的对象。在某些处理器上,如果在未缓存内存中分配对象,则诸如pthread_mutex_lock()之类的原子操作和调用将导致错误。
Mutexes: mutual exclusion locks
互斥锁是最简单的同步服务。互斥锁用于确保以独占方式访问线程之间共享的数据。
Condvars: condition variables
条件变量(condvar)用于阻止临界段内的线程,直到满足某个条件为止。该条件可以是任意复杂的,并且与condvar无关。但是,condvar必须始终与互斥锁一起使用才能实现监视器。
Barriers
屏障是一种同步机制,它允许您将多个协作线程(例如,在矩阵计算中)“关在一起”,迫使它们在某个特定点等待,直到所有线程都完成,然后任何一个线程才能继续。
Sleepon locks
Sleepon锁与Condvar非常相似,但有一些细微的区别。
Reader/writer locks
更正式的说法是“多个读卡器,单写器锁”,当数据结构的访问模式由多个线程读取数据和(最多)一个线程写入数据组成时,使用这些锁。这些锁比互斥锁更昂贵,但对于这种数据访问模式很有用。
Safely sharing mutexes, barriers, and reader/writer locks between processes
在进程之间安全地共享互斥锁、屏障和读写器锁
您可以在进程之间共享大多数同步对象,但安全性可能是一个问题。
Semaphores
信号量是一种常见的同步形式,它允许线程在信号量上“post”和“wait”来控制线程何时唤醒或睡眠。
Synchronization via scheduling policy
通过选择POSIX FIFO调度策略,我们可以保证在非SMP系统上没有具有相同优先级的两个线程同时执行关键部分。
Synchronization via message passing
我们的发送/接收/回复消息传递IPC服务(稍后描述)通过其阻塞性质实现隐式同步。在许多情况下,这些IPC服务会使其他同步服务变得不必要。它们也是唯一可以在网络上使用的同步和IPC原语(命名信号量除外,命名信号量构建在消息传递之上)。
Synchronization via atomic operations
在某些情况下,您可能希望执行一个短操作(例如递增一个变量),并保证该操作将以原子方式执行,即该操作不会被另一个线程或ISR(中断服务例程)抢占。
Synchronization services implementation
下表列出了各种微核调用以及由此构造的更高级别POSIX调用:
Microkernel call POSIX call Description
SyncTypeCreate()
pthread_mutex_init(), pthread_cond_init(), sem_init()
Create object for mutex, condvars, and semaphore
SyncDestroy()
pthread_mutex_destroy(), pthread_cond_destroy(), sem_destroy()
Destroy synchronization object
SyncCondvarWait()
pthread_cond_wait(), pthread_cond_timedwait()
Block on a condvar
SyncCondvarSignal()
pthread_cond_broadcast(), pthread_cond_signal()
Wake up condvar-blocked threads
SyncMutexLock()
pthread_mutex_lock(), pthread_mutex_trylock()
Lock a mutex
SyncMutexUnlock()
pthread_mutex_unlock()
Unlock a mutex
SyncSemPost()
sem_post()
Post a semaphore
SyncSemWait()
sem_wait(), sem_trywait()
Wait on a semaphore
Semaphores(信号量)
信号量是一种常见的同步形式,它允许线程在信号量上“post”和“wait”来控制线程何时唤醒或睡眠。
信号量不同于其他同步原语,因为它们是“异步安全的”,可以由信号处理程序进行操作。如果想要的效果是让信号处理程序唤醒线程,那么信号量是正确的选择。
信号量的QNX中微子实现支持命名信号量和未命名信号量(请参阅下面的“命名和未命名信号量”)。
信号量还是互斥量?
与互斥量相比,信号量的一个关键优势是,信号量被定义为在进程之间操作。
尽管我们的互斥在进程之间工作,POSIX线程标准认为这是一种可选功能。因此,如果您的代码依赖于进程之间工作的互斥体,那么为了确保可移植性,您可能应该使用信号量而不是互斥体。
但是,根据您的需要,在考虑以下因素后,您可能希望使用互斥量而不是信号量:
通常,互斥锁比信号量快得多,信号量总是需要一个内核条目。
对于单个进程中线程之间的同步,互斥比信号量更有效。
信号量不影响线程的有效优先级;如果需要优先级继承,请使用互斥锁(请参阅本章中的“互斥锁:互斥锁”)。
使用信号量
post(sem_post())操作增加信号量;wait(sem_wait())操作将其递减。
如果等待的信号量为正,则不会阻塞。等待非正信号量将阻塞,直到其他线程执行post。在等待之前发布一次或多次是有效的。这种用法允许一个或多个线程执行等待而不阻塞。
由于信号量与条件变量一样,由于错误唤醒,可以合法返回非零值,因此正确使用需要循环:
while (sem_wait(&s) && (errno == EINTR)) { do_nothing(); }
do_critical_region(); /* Semaphore was decremented /
有关可用于信号量的函数的完整列表,请参阅C库参考中的sem_()函数。
命名和未命名信号量
未命名信号量使用sem_init()创建,并使用sem_destroy()销毁。它们可以由同一进程中的多个线程使用。然而,在进程之间使用未命名的信号量需要一个共享内存对象,这意味着大量内存开销。
命名信号量使用sem_open()创建,并使用sem_close()关闭。与未命名信号量一样,它们可以由同一进程中的多个线程使用。然而,与未命名信号量不同,命名信号量可以在不同进程中的线程之间轻松共享。
除了匿名命名信号量之外,命名信号量具有路径和名称,因此可以在进程之间找到它们,而无需使用共享内存对象和它们所隐含的开销。因此,命名信号量比未命名信号量更适用于进程间通信。
此外,命名信号量(包括匿名命名信号量)可以由sigevent发布(例如,从ISR返回或由服务器传递),并且它们可以在父进程和子进程之间通过fork()共享,而无需共享映射。
匿名命名信号量不像其他命名信号量(即带有名称的命名信号量)那样具有路径和名称,但它们共享上述命名信号量的其他优点。有关匿名命名信号量的更多信息,请参阅C库参考中的sem_open()。
相关概念
信号量(QNX中微子入门)
作为互斥体的信号量(QNX中微子入门)
相关参考
sem_close()
sem_destroy()
sem_getvalue()
sem_init()
sem_open()
sem_post()
sem_timedwait()
sem_trywait()
sem_unlink()
sem_wait()
Semaphores(信号量)
信号量
让我们从浴室搬到厨房,因为那是一个社会上可以接受的同时有多人的地方。在厨房里,你可能不想让每个人都同时在那里。事实上,你可能想限制厨房里的人数(厨师太多等等)。
假设你不想同时有两个人以上。你能用互斥锁吗?不是我们定义的那样。为什么不呢?对于我们的类比来说,这实际上是一个非常有趣的问题。让我们把它分解成几个步骤。
计数为1的信号量
浴室可以有两种情况之一,两种状态相互关联:
门没有锁,房间里没有人
门是锁着的,房间里有一个人
没有其他组合是可能的门不能锁在没有人的房间里(我们如何打开它?),如果房间里有人,门是不能打开的(他们如何确保自己的隐私?)。这是一个计数为1的信号量示例,该房间中最多只能有一个人,或者一个线程使用该信号量。
这里的关键(请原谅双关语)是我们描述锁的方式。在你典型的浴室锁里,你只能从里面锁和开锁,没有外面的钥匙。实际上,这意味着互斥体的所有权是一个原子操作,在获取互斥体的过程中,不可能有其他线程获得互斥体,从而导致双方都拥有互斥体。在我们的家庭类比中,这不太明显,因为人类比1和0聪明得多。
我们厨房需要的是另一种锁。
计数大于1的信号量
假设我们在厨房里安装了传统的钥匙锁。这把锁的工作原理是,如果你有钥匙,你可以开锁然后进去。任何使用这把锁的人都同意,当他们进入室内时,他们会立即从室内锁门,以便室外的任何人都需要钥匙。
好吧,现在控制厨房里有多少人把两把钥匙挂在门外就变得很简单了!厨房总是锁着的。当有人想进厨房时,他们会看看门外是否挂着钥匙。如果是这样的话,他们会随身携带,打开厨房的门,走进去,然后用钥匙锁上门。
由于进入厨房的人在厨房时必须随身携带钥匙,因此我们通过限制门外挂钩上可用钥匙的数量,直接控制在任何给定点允许进入厨房的人数。
对于线程,这是通过信号量实现的。“普通”信号量的工作原理与互斥体的工作原理类似,您要么拥有互斥体,在这种情况下您可以访问资源,要么没有互斥体,在这种情况下您没有访问权。我们刚才在厨房中描述的信号量是一个计数信号量,它跟踪计数(通过线程可用的键数)。
Synchronization primitives
互斥量和条件变量(condvar)的数量没有限制。
未命名信号量的数量没有限制,但命名信号量的数量受到可用文件描述符数量的限制(请参阅上面的“文件描述符”)。
sem_init()
初始化未命名的信号量
简介:
#include <semaphore.h>
int sem_init( sem_t * sem,
int pshared,
unsigned value );
参数:
sem
指向要初始化的信号量的sem_t对象的指针。
确保sem是32位对齐的总是安全的,而且通常更快。
pshared
如果希望通过共享映射在进程之间共享信号量,则为非零。
value
信号量的初始值。正值表示将在不阻塞的情况下成功执行的信号量等待操作(例如,sem_wait())的数量,零值表示下一个信号量等待操作将阻塞调用线程。该值不得超过SEM_VALUE_MAX。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:初始化sem参数所引用的未命名信号量。此信号量的初始计数器值由value参数指定。
您应该只在普通内存映射中分配同步对象。在某些处理器上,如果在未缓存内存中分配控制结构,则对pthread_mutex_lock()的调用等原子操作将导致故障。
您可以在对sem_wait()、sem_trywait()、sem_post()和sem_destroy()的后续调用中使用初始化的信号量。初始化的信号量在被sem_destroy()函数销毁或释放信号量所在的内存之前是有效的。
如果pshared参数为非零,那么可以通过共享映射在进程之间共享信号量。然后,任何进程都可以将sem与sem_wait()、sem_trywait()、sem_post()和sem_destroy()函数一起使用。
不要在同一信号量上混合使用命名信号量操作(sem_open()和sem_close())和未命名信号量操作(sem_init()和sem_destroy())。
返回:
0
成功。sem引用的信号量已初始化。
-1
发生错误(已设置错误号)。
错误:
EAGAIN
初始化信号量所需的资源已用尽。
EBUSY
给定的信号量之前已初始化,尚未销毁。
EINVAL
value参数超过了SEM_VALUE_MAX。
EPERM
该进程缺少初始化信号量的适当权限。
ENOSPC
初始化信号量所需的资源已用尽。
ENOSYS
不支持sem_init()函数。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler No
Thread Yes
注意事项:
不要从多个线程初始化同一信号量。最好在启动任何线程之前设置信号量。
相关概念:
Synchronization primitives (QNX Neutrino User’s Guide)
sem_open()
创建或访问命名信号量
简介:
#include <semaphore.h>
#include <fcntl.h>
sem_t * sem_open( const char * sem_name,
int oflags,
… );
参数:
sem_name
要创建或访问的信号量的名称,或SEM_ANON(表示O_ANON,也表示O_CREAT)。
当您创建一个匿名的命名信号量(见下文)时,此参数将被忽略。
oflags
影响函数如何创建新信号量的标志。此论点是以下内容的组合:
O_ANON
O_CREAT
O_EXC
不要将标签设置为O_RDONLY、O_RDWR或O_WRONLY。根据POSIX,信号量的行为没有用这些标志定义。QNX中微子库默默地忽略了这些选项,但它们可能会降低代码的可移植性。
有关更多信息,请参阅下文。
如果设置O_CREAT标签,还必须传递以下参数:
mode_t mode
信号量的模式(就像文件模式一样)。为了便于移植,您应该将读、写和执行位设置为相同的值。一种简单的方法是使用<sys/stat.h>中的常量:
S_IRWXG用于组访问。
S_IRWXG用于组访问。
S_IRWXO供其他人访问。
S_IRWXU供您自己访问。
有关更多信息,请参阅struct stat的条目。
创建匿名命名信号量时,必须提供此参数,但忽略它。
unsigned int value
信号量的初始值。正值表示将在不阻塞的情况下成功执行的信号量等待操作(例如,sem_wait())的数量,零值表示下一个信号量等待操作将阻塞调用线程。该值不得超过SEM_VALUE_MAX。
库
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:创建或访问一个命名的信号量。只要系统启动,信号量就会持续存在。
函数的作用是:返回一个信号量描述符,可以与sem_wait()、sem_trywait()和sem_post()一起使用。您可以一直使用它,直到调用sem_close()。您可以通过调用sem_unlink()来取消信号量的链接;当所有进程都取消了信号量的链接时,它就被销毁了。
命名信号量始终在/dev/sem下创建:
如果name参数以斜杠开头,信号量将被赋予该名称。
如果name参数不是以斜杠字符开头,信号量将被赋予该名称,并以当前工作目录作为前缀。
在任何一种情况下,都不会解释除前导斜杠字符以外的斜杠字符,并且使用指定的名称(包括这些斜杠字符)来标识信号量。换句话说,附加的斜杠不会在/dev/sem下创建目录结构。
例如,如果当前目录为/tmp:
name Pathname space entry
/my_sem /dev/sem/my_sem
my_sem /dev/sem/tmp/my_sem
oflags参数仅用于创建信号量。创建新信号量时,可以将一组标记设置为O_CREAT、(O_CREAT | O_EXCL)或O_ANON:
O_ANON
意味着你的创造。创建新的命名信号量时,将其设置为匿名命名信号量。
匿名命名信号量不像其他命名信号量(即带名称的命名信号量)那样具有路径,但它们确实比未命名信号量有一些优势。明确地:
一个命名信号量(包括一个匿名命名信号量)可以由一个sigevent发布(例如,从ISR返回或由服务器交付)。
匿名命名信号量可以通过fork()在父进程和子进程之间共享,而无需共享映射。
对于匿名命名信号量,将忽略sem_name和模式参数。
O_CREAT
创建一个新的命名信号量。如果设置此位,则必须向sem_open()提供模式和值参数。
O_EXCL
创建新的命名信号量时,如果已存在具有sem_name的信号量,O_EXCL将导致sem_open()失败。如果没有O_EXCL,sem_open()会附加到现有的信号量,如果sem_name不存在,则会创建一个新的信号量。
不要在同一信号量上混合使用命名信号量操作(sem_open()和sem_close())和未命名信号量操作(sem_init()和sem_destroy())。
命名信号量的QNX实现
请注意,信号量的QNX实现与POSIX标准不同,POSIX标准要求“如果一个进程使用相同的名称值多次成功调用sem_open(),则每次成功调用都应返回相同的信号量地址…”。
在命名信号量的QNX实现中,如果一个进程使用相同的名称值(sem_name)多次成功调用sem_open(),那么对该函数的所有调用都将返回引用相同基础对象的sem_t对象。此行为如POSIX标准中所规定。
但是,命名信号量的QNX实现与POSIX标准中指定的行为不同,如下所示:每次成功调用sem_open()返回的信号量地址都是唯一的(即,调用1将返回地址A,而调用2将返回地址B,等等)。此行为意味着,对于每个信号量,在处理完信号量后,必须将对sem_open()的调用与对sem_close()的调用相匹配。
返回:
指向已创建或访问的信号量的指针,或SEM_FAILED而失败(设置了errno)。
错误:
EACCES
指定的信号量存在且您没有访问它的权限,或者您正在尝试创建一个新的信号量,但您没有访问它的权限。
EEXIST
您在oflags中指定了O_CREAT和O_EXCL,但信号量已经存在。
EINTR
电话被一个信号打断了。
EINVAL
sem_name参数无效,或者在创建信号量时,该值大于SEM_VALUE_MAX。
ELOOP
符号链接或前缀的级别太多。
EMFILE
进程正在使用过多的文件或信号量。
ENFILE
系统资源不足,无法打开信号灯。
ENOENT
sem_name参数标识的信号量不存在,并且您没有在标签中指定O_CREAT。
ENOMEM
内存不足,无法创建新的命名信号量。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler No
Thread Yes
相关概念:
Synchronization primitives (QNX Neutrino User’s Guide)
sem_close()
关闭指定的信号量
简介:
#include <semaphore.h>
int sem_close( sem_t * sem );
参数:
sem
指向信号量的指针,由sem_open()返回。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:关闭由sem_open()打开的命名信号量sem,释放与该sem相关的所有系统资源。
不要在同一信号量上混合使用命名信号量操作(sem_open()和sem_close())和未命名信号量操作(sem_init()和sem_destroy())。
返回:
0
成功
-1
发生错误(已设置错误号)。
错误:
EINVAL
无效的信号量描述符。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
相关概念:
Synchronization primitives (QNX Neutrino User’s Guide)
sem_destroy()
销毁未命名的信号量
简介:
#include <semaphore.h>
int sem_destroy( sem_t * sem );
参数:
sem
指向要销毁的信号量的sem_t对象的指针。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:销毁sem参数引用的未命名信号量。信号量之前必须由sem_init()函数初始化。
不要在信号灯被破坏后再使用它。如果您破坏了其他线程当前被阻止的信号量,它们将被解除阻止,并出现错误(EINVAL)。
不要在同一信号量上混合使用命名信号量操作(sem_open()和sem_close())和未命名信号量操作(sem_init()和sem_destroy())。
返回:
0
成功
-1
发生错误(已设置错误号)。
错误:
EINVAL
无效的信号量描述符。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
sem_getvalue()
获取已命名或未命名信号量的值
简介:
#include <semaphore.h>
int sem_getvalue( sem_t * sem,
int * value );
参数:
sem
指向要获取其值的信号量的sem_t对象的指针。
value
指向函数可以存储信号量值的位置的指针。正值表示将返回而不阻塞的信号量等待操作(例如,sem_wait())的数量。零或负值表示任何后续的信号量等待操作都将阻塞。对于未命名(sem_init())信号量实现,负值表示当前阻止等待信号量的线程数。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:获取信号量值sem的快照,并将其存储在value中。此值可以随时更改,并保证仅在sem_getvalue()调用中的某个点有效。
此函数用于调试信号量代码。
返回:
0
成功
-1
发生错误(已设置错误号)。
错误:
EINVAL
无效的信号量描述符。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
sem_post()
增加一个命名或未命名的信号量
简介:
#include <semaphore.h>
int sem_post( sem_t * sem );
参数:
sem
指向要增加其值的信号量的sem_t对象的指针。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:增加sem参数引用的信号量。如果当前有任何线程被阻止等待信号量,那么其中一个线程将从调用sem_wait成功返回。
要解除阻止的线程是根据对被阻止线程有效的调度策略确定的。最高优先级的等待线程被解除阻止,如果有多个最高优先级线程被阻止等待信号量,则等待时间最长的最高优先级线程被解除阻止。
sem_post()函数对于信号是可重入的,可以从信号处理程序调用。
返回:
0
成功
-1
发生错误(已设置错误号)。
错误:
EINTR
调用被一个信号打断了。
EINVAL
sem参数未指向有效的信号量描述符。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
sem_timedwait(), sem_timedwait_monotonic()
等待已命名或未命名的信号量,并超时
简介:
#include <semaphore.h>
#include <time.h>
int sem_timedwait(
sem_t * sem,
const struct timespec * abs_timeout );
int sem_timedwait_monotonic(
sem_t * sem,
const struct timespec * abs_timeout );
参数:
sem
要等待的信号量。
abs_timeout
指向timespec结构的指针,该结构指定超时过期的绝对时间。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
sem_timedwait()函数会像在sem_wait()函数中一样减少sem引用的信号量。如果无法减少信号量(即,如果计数为0),则函数将阻塞,直到另一个线程增加信号量的计数,或者直到指定的超时过期。超时基于CLOCK_REALTIME时钟。
sem_timedwait_monotonic()函数是QNX中微子的扩展;它与sem_timedwait()类似,但它使用CLOCK_MONOTONIC,因此超时不受系统时间更改的影响。
当abs_timeout指定的绝对时间过去时,超时将过期,这是由超时所基于的时钟测量的(即,当该时钟的值等于或超过abs_timeout时),或者如果在调用时已通过abs_timeout指定的绝对时间,则超时将过期。
返回:
0
调用线程成功地减少了sem指定的信号量。
-1
呼叫未成功(已设置错误号)。信号量的状态不变。
错误:
EINTR
一个信号中断了这个功能。
EINVAL
信号量sem无效,否则线程将被阻塞,并且abs_timeout参数指定的纳秒字段值小于零或大于或等于10亿。
ETIMEDOUT
在指定的超时过期之前,无法减少信号量。
例子:
#include <stdio.h>
#include <semaphore.h>
#include <time.h>
main(){
struct timespec tm;
sem_t sem;
int i=0;
sem_init( &sem, 0, 0);
do {
clock_gettime(CLOCK_REALTIME, &tm);
tm.tv_sec += 1;
i++;
printf("i=%d\n",i);
if (i==10) {
sem_post(&sem);
}
} while ( sem_timedwait( &sem, &tm ) == -1 );
printf("Semaphore acquired after %d timeouts\n", i);
return;
}
分类:
sem_timedwait() is POSIX 1003.1; sem_timedwait_monotonic() is QNX Neutrino
Safety:
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes
sem_trywait()
等待已命名或未命名的信号量,但不要阻止
简介:
#include <semaphore.h>
int sem_trywait( sem_t * sem );
参数:
sem
指向要等待的信号量的sem_t对象的指针。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
如果信号量的值大于零,则sem_trywait()函数将信号量递减;否则,函数将直接返回。
返回:
0
信号量已成功递减。
-1
信号量的状态保持不变(设置了errno)。
错误:
EAGAIN
计数不大于0,因此sem_trywait()无法立即将其递减。
EAGAIN
无效的信号量描述符。
EINTR
一个信号中断了这个功能。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
sem_unlink()
销毁已命名的信号量
简介:
#include <semaphore.h>
int sem_unlink( const char * sem_name );
参数:
sem_name
要销毁的信号量的名称。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:销毁指定的信号量sem_name。移除打开的信号量的方式与unlink()移除打开的文件的方式相同;打开了信号量的进程仍然可以使用它,但只要最后一个进程使用sem_close()关闭信号量,信号量就会消失。
在未链接的信号量上使用sem_open()的任何尝试都将引用新的信号量。
只要系统保持运行,信号量就是持久的。
返回:
0
成功
-1
发生错误(已设置错误号)。
错误:
EACCES
您没有取消信号灯链接的权限。
ELOOP
符号链接或前缀的级别太多。
ENOENT
信号量sem_name不存在。
ENOENT
sem_name参数长于(NAME_MAX-8)。
分类:
POSIX 1003.1
Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes
sem_wait()
等待已命名或未命名的信号量
简介:
#include <semaphore.h>
int sem_wait( sem_t * sem );
参数:
sem
指向要等待的信号量的sem_t对象的指针。
库:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
描述:
函数的作用是:减少sem参数引用的信号量。如果信号量值不大于零,那么调用线程将阻塞,直到它可以减少计数器(即,另一个线程发布信号量),或者调用被信号中断。
一些线程最终应该调用sem_post()来增加信号量。
返回:
0
信号量已成功递减。
-1
信号量的状态保持不变(设置了errno)。
错误:
EINVAL
无效的信号量描述符。
EINTR
一个信号中断了这个功能。
分类:
POSIX 1003.1
Safety:
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes