首先,我想为您提供一些背景信息。

我需要合并两种图像。第一张图片是背景图片,格式为8BppGrey,分辨率为320x240。第二张图像是前景图像,格式为32BppRGBA,分辨率为64x48。

更新
带有MVP的github仓库是问题的底部。

为此,我使用双线性插值将第二张图像的大小调整为与第一张图像相同的大小,然后使用混合将两者合并为一张图像。仅当第二张图像的Alpha值大于0时才发生混合。

我需要尽快执行此操作,因此我的想法是结合调整大小和合并/混合过程。

为此,我使用了writeablebitmapex repository的resize函数,并添加了合并/混合功能。

一切都按预期工作,但我想减少执行时间。

这是当前的调试时间:

// CPU: Intel(R) Core(TM) i7-4810MQ CPU @ 2.80GHz

MediaServer: Execution time in c++ 5 ms
MediaServer: Resizing took 4 ms.
MediaServer: Execution time in c++ 5 ms
MediaServer: Resizing took 5 ms.
MediaServer: Execution time in c++ 4 ms
MediaServer: Resizing took 4 ms.
MediaServer: Execution time in c++ 3 ms
MediaServer: Resizing took 3 ms.
MediaServer: Execution time in c++ 4 ms
MediaServer: Resizing took 4 ms.
MediaServer: Execution time in c++ 5 ms
MediaServer: Resizing took 4 ms.
MediaServer: Execution time in c++ 6 ms
MediaServer: Resizing took 6 ms.
MediaServer: Execution time in c++ 3 ms
MediaServer: Resizing took 3 ms.

我是否有机会提高大小/合并/混合过程的性能并降低执行时间?

有一些我可能可以并行化的部分吗?

我是否有机会使用某些处理器功能?

嵌套循环对性能有很大的影响,但是我不知道如何更好地编写它。

我希望整个过程达到1或2毫秒。这有可能吗?

这是我使用的修改后的可视c++函数。
  • pd是可写位图的后缓冲区,用于显示
    导致WPF。我使用的格式是默认的32BppRGBA。
  • 像素是64x48 32BppRGBA图像
  • 的int []数组
  • widthSource和heightSource是像素图像
  • 的大小
  • 的宽度和高度是输出图像的目标尺寸
  • baseImage是320x240 8BppGray图像
  • 的int []数组

    VC++代码:
    unsigned int Resize(int* pd, int* pixels, int widthSource, int heightSource, int width, int height, byte* baseImage)
    {
        unsigned int start = clock();
    
        float xs = (float)widthSource / width;
        float ys = (float)heightSource / height;
    
        float fracx, fracy, ifracx, ifracy, sx, sy, l0, l1, rf, gf, bf;
        int c, x0, x1, y0, y1;
        byte c1a, c1r, c1g, c1b, c2a, c2r, c2g, c2b, c3a, c3r, c3g, c3b, c4a, c4r, c4g, c4b;
        byte a, r, g, b;
    
        // Bilinear
        int srcIdx = 0;
    
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                sx = x * xs;
                sy = y * ys;
                x0 = (int)sx;
                y0 = (int)sy;
    
                // Calculate coordinates of the 4 interpolation points
                fracx = sx - x0;
                fracy = sy - y0;
                ifracx = 1.0f - fracx;
                ifracy = 1.0f - fracy;
                x1 = x0 + 1;
                if (x1 >= widthSource)
                {
                    x1 = x0;
                }
                y1 = y0 + 1;
                if (y1 >= heightSource)
                {
                    y1 = y0;
                }
    
                // Read source color
                c = pixels[y0 * widthSource + x0];
                c1a = (byte)(c >> 24);
                c1r = (byte)(c >> 16);
                c1g = (byte)(c >> 8);
                c1b = (byte)(c);
    
                c = pixels[y0 * widthSource + x1];
                c2a = (byte)(c >> 24);
                c2r = (byte)(c >> 16);
                c2g = (byte)(c >> 8);
                c2b = (byte)(c);
    
                c = pixels[y1 * widthSource + x0];
                c3a = (byte)(c >> 24);
                c3r = (byte)(c >> 16);
                c3g = (byte)(c >> 8);
                c3b = (byte)(c);
    
                c = pixels[y1 * widthSource + x1];
                c4a = (byte)(c >> 24);
                c4r = (byte)(c >> 16);
                c4g = (byte)(c >> 8);
                c4b = (byte)(c);
    
                // Calculate colors
                // Alpha
                l0 = ifracx * c1a + fracx * c2a;
                l1 = ifracx * c3a + fracx * c4a;
                a = (byte)(ifracy * l0 + fracy * l1);
    
                // Write destination
                if (a > 0)
                {
                    // Red
                    l0 = ifracx * c1r + fracx * c2r;
                    l1 = ifracx * c3r + fracx * c4r;
                    rf = ifracy * l0 + fracy * l1;
    
                    // Green
                    l0 = ifracx * c1g + fracx * c2g;
                    l1 = ifracx * c3g + fracx * c4g;
                    gf = ifracy * l0 + fracy * l1;
    
                    // Blue
                    l0 = ifracx * c1b + fracx * c2b;
                    l1 = ifracx * c3b + fracx * c4b;
                    bf = ifracy * l0 + fracy * l1;
    
                    // Cast to byte
                    float alpha = a / 255.0f;
                    r = (byte)((rf * alpha) + (baseImage[srcIdx] * (1.0f - alpha)));
                    g = (byte)((gf * alpha) + (baseImage[srcIdx] * (1.0f - alpha)));
                    b = (byte)((bf * alpha) + (baseImage[srcIdx] * (1.0f - alpha)));
    
                    pd[srcIdx++] = (255 << 24) | (r << 16) | (g << 8) | b;
                }
                else
                {
                    // Alpha, Red, Green, Blue
                    pd[srcIdx++] = (255 << 24) | (baseImage[srcIdx] << 16) | (baseImage[srcIdx] << 8) | baseImage[srcIdx];
                }
            }
        }
    
        unsigned int end = clock() - start;
        return end;
    }
    

    Github repo

    最佳答案

    可以加快代码速度的一种措施是避免类型从整数转换为浮点数,反之亦然。这可以通过使int值在合适的范围内而不是在0..1范围内的浮点数来实现。

    像这样:

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            int sx1 = x * widthSource ;
            int x0 = sx1 / width;
            int fracx = (sx1 % width) ; // range 0..width - 1
    

    变成类似
            l0 = (fracx * c2a + (width - fracx) * c1a) / width ;
    

    等等。有点棘手但可行

    09-07 08:36