Image Stride (Windows)

When a video image is stored in memory, the memory buffer might contain extra padding bytes after each row of pixels. The padding bytes affect how the image is stored in memory, but do not affect how the image is displayed.

The stride is the number of bytes from one row of pixels in memory to the next row of pixels in memory. Stride is also called pitch. If padding bytes are present, the stride is wider than the width of the image, as shown in the following illustration.



Two buffers that contain video frames with equal dimensions can have two different strides. If you process a video image, you must take the stride into account.

In addition, there are two ways that an image can be arranged in memory. In a top-down image, the top row of pixels in the image appears first in memory. In a bottom-up image, the last row of pixels appears first in memory. The following illustration shows the difference between a top-down image and a bottom-up image.



A bottom-up image has a negative stride, because stride is defined as the number of bytes need to move down a row of pixels, relative to the displayed image. YUV images should always be top-down, and any image that is contained in a Direct3D surface must be top-down. RGB images in system memory are usually bottom-up.

Video transforms in particular need to handle buffers with mismatched strides, because the input buffer might not match the output buffer. For example, suppose that you want to convert a source image and write the result to a destination image. Assume that both images have the same width and height, but might not have the same pixel format or the same image stride.

The following example code shows a generalized approach for writing this kind of function. This is not a complete working example, because it abstracts many of the specific details.

复制

void ProcessVideoImage(
    BYTE*       pDestScanLine0,
    LONG        lDestStride,
    const BYTE* pSrcScanLine0,
    LONG        lSrcStride,
    DWORD       dwWidthInPixels,
    DWORD       dwHeightInPixels
    )
{
    for (DWORD y = 0; y < dwHeightInPixels; y++)
    {
        SOURCE_PIXEL_TYPE *pSrcPixel = (SOURCE_PIXEL_TYPE*)pDestScanLine0;
        DEST_PIXEL_TYPE *pDestPixel = (DEST_PIXEL_TYPE*)pSrcScanLine0;

        for (DWORD x = 0; x < dwWidthInPixels; x +=2)
        {
            pDestPixel[x] = TransformPixelValue(pSrcPixel[x]);
        }
        pDestScanLine0 += lDestStride;
        pSrcScanLine0 += lSrcStride;
    }
}

This function takes six parameters:

  • A pointer to the start of scan line 0 in the destination image.
  • The stride of the destination image.
  • A pointer to the start of scan line 0 in the source image.
  • The stride of the source image.
  • The width of the image in pixels.
  • The height of the image in pixels.

The general idea is to process one row at a time, iterating over each pixel in the row. Assume that SOURCE_PIXEL_TYPE and DEST_PIXEL_TYPE are structures representing the pixel layout for the source and destination images, respectively. (For example, 32-bit RGB uses the RGBQUAD structure. Not every pixel format has a predefined structure.) Casting the array pointer to the structure type enables you to access the RGB or YUV components of each pixel. At the start of each row, the function stores a pointer to the row. At the end of the row, it increments the pointer by the width of the image stride, which advances the pointer to the next row.

This example calls a hypothetical function named TransformPixelValue for each pixel. This could be any function that calculates a target pixel from a source pixel. Of course, the exact details will depend on the particular task. For example, if you have a planar YUV format, you must access the chroma planes independently from the luma plane; with interlaced video, you might need to process the fields separately; and so forth.

To give a more concrete example, the following code converts a 32-bit RGB image into an AYUV image. The RGB pixels are accessed using an RGBQUADstructure, and the AYUV pixels are accessed using a DXVA2_AYUVSample8 structure structure.

复制

//-------------------------------------------------------------------
// Name: RGB32_To_AYUV
// Description: Converts an image from RGB32 to AYUV
//-------------------------------------------------------------------
void RGB32_To_AYUV(
    BYTE*       pDest,
    LONG        lDestStride,
    const BYTE* pSrc,
    LONG        lSrcStride,
    DWORD       dwWidthInPixels,
    DWORD       dwHeightInPixels
    )
{
    for (DWORD y = 0; y < dwHeightInPixels; y++)
    {
        RGBQUAD             *pSrcPixel = (RGBQUAD*)pSrc;
        DXVA2_AYUVSample8   *pDestPixel = (DXVA2_AYUVSample8*)pDest;

        for (DWORD x = 0; x < dwWidthInPixels; x++)
        {
            pDestPixel[x].Alpha = 0x80;
            pDestPixel[x].Y = RGBtoY(pSrcPixel[x]);
            pDestPixel[x].Cb = RGBtoU(pSrcPixel[x]);
            pDestPixel[x].Cr = RGBtoV(pSrcPixel[x]);
        }
        pDest += lDestStride;
        pSrc += lSrcStride;
    }
}

The next example converts a 32-bit RGB image to a YV12 image. This example shows how to handle a planar YUV format. (YV12 is a planar 4:2:0 format.) In this example, the function maintains three separate pointers for the three planes in the target image. However, the basic approach is the same as the previous example.

复制

void RGB32_To_YV12(
    BYTE*       pDest,
    LONG        lDestStride,
    const BYTE* pSrc,
    LONG        lSrcStride,
    DWORD       dwWidthInPixels,
    DWORD       dwHeightInPixels
    )
{
    assert(dwWidthInPixels % 2 == 0);
    assert(dwHeightInPixels % 2 == 0);

    const BYTE *pSrcRow = pSrc;

    BYTE *pDestY = pDest;

    // Calculate the offsets for the V and U planes.

    // In YV12, each chroma plane has half the stride and half the height
    // as the Y plane.
    BYTE *pDestV = pDest + (lDestStride * dwHeightInPixels);
    BYTE *pDestU = pDest +
                   (lDestStride * dwHeightInPixels) +
                   ((lDestStride * dwHeightInPixels) / 4);

    // Convert the Y plane.
    for (DWORD y = 0; y < dwHeightInPixels; y++)
    {
        RGBQUAD *pSrcPixel = (RGBQUAD*)pSrcRow;

        for (DWORD x = 0; x < dwWidthInPixels; x++)
        {
            pDestY[x] = RGBtoY(pSrcPixel[x]);    // Y0
        }
        pDestY += lDestStride;
        pSrcRow += lSrcStride;
    }

    // Convert the V and U planes.

    // YV12 is a 4:2:0 format, so each chroma sample is derived from four
    // RGB pixels.
    pSrcRow = pSrc;
    for (DWORD y = 0; y < dwHeightInPixels; y += 2)
    {
        RGBQUAD *pSrcPixel = (RGBQUAD*)pSrcRow;
        RGBQUAD *pNextSrcRow = (RGBQUAD*)(pSrcRow + lSrcStride);

        BYTE *pbV = pDestV;
        BYTE *pbU = pDestU;

        for (DWORD x = 0; x < dwWidthInPixels; x += 2)
        {
            // Use a simple average to downsample the chroma.

            *pbV++ = ( RGBtoV(pSrcPixel[x]) +
                       RGBtoV(pSrcPixel[x + 1]) +
                       RGBtoV(pNextSrcRow[x]) +
                       RGBtoV(pNextSrcRow[x + 1]) ) / 4;        

            *pbU++ = ( RGBtoU(pSrcPixel[x]) +
                       RGBtoU(pSrcPixel[x + 1]) +
                       RGBtoU(pNextSrcRow[x]) +
                       RGBtoU(pNextSrcRow[x + 1]) ) / 4;
        }
        pDestV += lDestStride / 2;
        pDestU += lDestStride / 2;

        // Skip two lines on the source image.
        pSrcRow += (lSrcStride * 2);
    }
}

In all of these examples, it is assumed that the application has already determined the image stride. You can sometimes get this information from the media buffer. Otherwise, you must calculate it based on the video format. For more information about calculating image stride and working with media buffers for video, see Uncompressed Video Buffers.

时间: 2024-09-08 05:14:05

Image Stride (Windows)的相关文章

借助C++进行Windows开发:探索高性能算法

在并发空间中,诸如协调.异步行为.响应性和可伸缩性等问题会成为关注的焦点.这些都是开发人员在设计应用程序时必须考虑的一些比较深奥的主题.但是,也许是由于缺乏经验或缺乏合适的性能工具,一些同样重要的主题却常常被忽略.高性能算法就是其中一例. 在企业级别,开发人员会仔细斟酌分布式文件系统和缓存.群集.消息队列和数据库等问题.但是如果最核心的算法和数据结构效率低下,考虑这些又有什么用呢? 算法效率并不像您认为的那样简单.单处理器上设计良好的算法通常可以胜过多处理器上的低效实现.但是现在,当多处理器已经

Kinect for Windows SDK开发入门(三)基础知识 下

1. 性能改进 上文的代码中,对于每一个彩色图像帧,都会创建一个新的Bitmap对象.由于Kinect视频摄像头默认采集频率为每秒30幅,所以应用程序每秒会创建30个bitmap对象,产生30次的Bitmap内存创建,对象初始化,填充像素数据等操作.这些对象很快就会变成垃圾等待垃圾回收器进行回收.对数据量小的程序来说可能影响不是很明显,但当数据量很大时,其缺点就会显现出来. 改进方法是使用WriteableBitmap对象.它位于System.Windows.Media.Imaging命名空间下

互联网企业安全高级指南3.8 STRIDE威胁建模

3.8 STRIDE威胁建模 STRIDE是微软开发的用于威胁建模的工具,或者是说一套方法论吧,它把外部威胁分成6个维度来考察系统设计时存在的风险点,这6个维度首字母的缩写就是STRIDE,分别为: Spoofing(假冒).Tampering(篡改).Repudiation(否认).Information Disclosure(信息泄漏).Denial of Service(拒绝服务)和 Elevation of Privilege(权限提升),如表3-1所示. 表3-1 STRIDE威胁建模

Windows 8应用开发之异步调用

 不论是桌面客户端还是Web应用通常会出现处理时间较长的操作,为了在这段时间内不影响用户与应用之间的交互体验,开发人员通常会使用异步调用技术,使得比较复杂的逻辑操作由异步进行,用户仍然可以继续使用应用,不会有无响应的等待情况出现. 本篇将通过一个简单的实例演示如何在Windows 8 应用中使用异步编程.首先我们来编写一个"Get Blogs"按钮,点击它可以从Windows Blog中获取博客列表.当然获取博客信息的过程是由异步进行的,这个过程中为了测试用户仍然可以与应用交互,我们再

硬盘安装Windows 8系统图文教程

没有光驱.没有光盘.没有U盘,照样安装一个全新的Windows 8!什么?你不信?那就看看软件小品如何教你使用硬盘安装一个全新的Windows 8!看了这篇图文并茂的硬盘安装Window8详细教程,我就不信你学不会!好了,开始动手吧! 一.准备工作: 可以正常工作的Windows xp/7操作系统以及容量大于3.5G的非系统分区; Windows 8 硬盘安装引导工具 nt6 hdd installer ; Windows 8 微软官方安装镜像(以下称Windows 8 镜像). 二.开始安装:

将Tunnelier注册成Windows服务

  最近硬盘坏道了,没有过保,HP可给换了块新的,重装了x64版的win7,下载Tunnelier的时候意外发现,官网上有Running Tunnelier as a Windows Service条目,之前一直以为只有MyEnTunnel可以注册成Windows服务,原来通过工具可以将任何程序注册成服务.文章中提到了三个工具: srvany(windows Resource Kits中的工具) FireDaemon 一个比srvany更易用的工具 Non-Sucking Service Man

Windows Server 2012 Server Core中安装活动目录

在Windows Sever 2012中,我们可以自由的切换Server Core和GUI图形界面,相信在今后会有更多的服务我们会运行在Server Core当中.下面本文将对在Server Core中对网络配置到修改计算机名,最后创建一个域进行一次叙述. www.2cto.com 1. 配置网络 ? 登陆到Server Core中,在命令提示符输入Sconfig ? 在Sconfig中选择8>网络设置. ? 选择需要进行修改的网络适配器编号,这里为10 ? 根据向导依次对IP地址.子网掩码.默

保护Windows注册表

保护注册表是很重要的,有很多不同的工具可以实现这一目的.当没有安全设置时,用户可能的错误会更多.幸运的是,他们可以有几中方法来保护Windows注册表,在注册表失败时他们可以用额外的拷贝来恢复注册表.下面就是其中的一些方法:   1.使用windows备份软件   注:Win95和Win98备份程序有部分区别,在这里只讲Win98的备份程序.   Win98中包括一个备份程序.当安装Win98时如果你选择"自定义安装",或者你可以在控制面板中的添加/删除程序里安装它.当你安装了这个备份

Windows 7正版系统验证方法

  方法一:通过微软网站在线验证,点击此处进入进行验证. 1. 打开网址,选择"在线验证",如下图红框所示: 2. 点击下方出现的"在线验证"按钮; 3. 点击"下载"按钮,下载安装必要的软件,注意如果不能正常运行,请看浏览器加载项是否正常运行,如下图上方红框所示: 4. 可以选择"运行"按钮直接运行安装软件,或者点击"保存"按钮将软件安装程序先保存在本地,再执行安装. 5. 软件安装完成后,点击步骤3图中