SDL_LockTexture() 返回意外的音高值
SDL_LockTexture() returning an unexpected pitch value
我正在使用 SDL2.0.7(Nexus 5、armeabi-v7a、ndk 16.1)在本机应用程序上显示 Android 相机预览。
我正在使用 N21 YUV 图像格式,我期待创建该格式的 SDL_Texture
,pitch SDL_LockTexture()
返回的值将大于我现在得到的值。
示例代码:
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV21, SDL_TEXTUREACCESS_STREAMING, 720, 480);
int res = SDL_LockTexture(texture, nullptr, &pixels, &pitch);
我期望得到 720 * 12 / 8
的间距值,即 1080
,其中 720
是一行的宽度, 12
是单个 YUV N21 像素的位数,8
是一个字节中的位数,因为 the SDL2 documentation 表示:
pitch: this is filled in with the pitch of the locked pixels; the pitch is the length of one row in bytes
现在,函数调用实际返回的pitch值是720
。事实是,如果我使用 720
值,相机预览将以不自然的绿色优势显示,而如果我忽略 720
间距并使用我预期的 1080
间距,相机预览很好(应用程序运行也很流畅)。
我的假设有什么问题吗(例如,N21 像素的位数是 12,正如 Android 的 ImageFormat.getBitsPerPixel()
所暗示的那样)?我是否以错误的方式使用了 SDL 库?
流式纹理的创建纹理实用程序在内部执行此操作:
// ...
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
size = texture->h * data->pitch;
if (data->yuv) {
/* Need to add size for the U and V planes */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
if (data->nv12) {
/* Need to add size for the U/V plane */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
}
}
// ...
在你的例子中,因为你使用的是 SDL_PIXELFORMAT_NV21
,yuv
是假的,nv12
是真的(如果听起来很奇怪,用调试器试试)。
这意味着分配的大小不是 pitch * height
。相反,它是:
(pitch * height) + 2 * ((height + 1) / 2) * ((pitch + 1) / 2);
在这种情况下,pitch
等于 width
。
归根结底,它是图像大小的 1.5 倍,即每像素 12 位。
当然 pitch
的值在某种程度上是 错误的 ,因为它等于 width
.
实际上,由于分配了 space,它应该是您期望的图像宽度的 1.5 倍。
但是我不太确定,因为我不是 SDL2 的专家。
我正在使用 SDL2.0.7(Nexus 5、armeabi-v7a、ndk 16.1)在本机应用程序上显示 Android 相机预览。
我正在使用 N21 YUV 图像格式,我期待创建该格式的 SDL_Texture
,pitch SDL_LockTexture()
返回的值将大于我现在得到的值。
示例代码:
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_NV21, SDL_TEXTUREACCESS_STREAMING, 720, 480);
int res = SDL_LockTexture(texture, nullptr, &pixels, &pitch);
我期望得到 720 * 12 / 8
的间距值,即 1080
,其中 720
是一行的宽度, 12
是单个 YUV N21 像素的位数,8
是一个字节中的位数,因为 the SDL2 documentation 表示:
pitch: this is filled in with the pitch of the locked pixels; the pitch is the length of one row in bytes
现在,函数调用实际返回的pitch值是720
。事实是,如果我使用 720
值,相机预览将以不自然的绿色优势显示,而如果我忽略 720
间距并使用我预期的 1080
间距,相机预览很好(应用程序运行也很流畅)。
我的假设有什么问题吗(例如,N21 像素的位数是 12,正如 Android 的 ImageFormat.getBitsPerPixel()
所暗示的那样)?我是否以错误的方式使用了 SDL 库?
流式纹理的创建纹理实用程序在内部执行此操作:
// ...
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
size = texture->h * data->pitch;
if (data->yuv) {
/* Need to add size for the U and V planes */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
if (data->nv12) {
/* Need to add size for the U/V plane */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
}
}
// ...
在你的例子中,因为你使用的是 SDL_PIXELFORMAT_NV21
,yuv
是假的,nv12
是真的(如果听起来很奇怪,用调试器试试)。
这意味着分配的大小不是 pitch * height
。相反,它是:
(pitch * height) + 2 * ((height + 1) / 2) * ((pitch + 1) / 2);
在这种情况下,pitch
等于 width
。
归根结底,它是图像大小的 1.5 倍,即每像素 12 位。
当然 pitch
的值在某种程度上是 错误的 ,因为它等于 width
.
实际上,由于分配了 space,它应该是您期望的图像宽度的 1.5 倍。
但是我不太确定,因为我不是 SDL2 的专家。