将位图数组合并到单个位图中

时间:2012-11-06 10:19:01

标签: c# .net image-processing

我正在尝试将Bitmap的数组合并为一个Bitmap。给定Bitmap[,]数组b,如下所示(假设这些图像看起来像字符):

b[0,0] = 1
b[1,0] = 2
b[0,1] = 3
b[1,1] = 4

我想生成

result = 12
         34

例如,给出以下四个Bitmap s:

b[0,0] = Image 0,0 ;

b[1,0] = Image 1,1 ;

b[0,1] = Image 0,1 ;

b[1,1] = Image 1,1 ;

我想生成 result = result ;

到目前为止,这是我的代码:

    public static Bitmap Moisac(ref Bitmap[,] b)
    {
        BitmapData[,] bmData = new BitmapData[b.GetUpperBound(0) + 1, b.GetUpperBound(1) + 1];
        IntPtr[,] scan0 = new IntPtr[b.GetUpperBound(0) + 1, b.GetUpperBound(1) + 1];
        unsafe
        {
            byte*[,] p = new byte*[b.GetUpperBound(0) + 1,b.GetUpperBound(1) + 1];
            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                    if (b[i, j].Width != b[0, 0].Width | b[i, j].Height != b[0, 0].Height)
                        throw new ArgumentException(
                            "Width and Height properties of all elements of b must be equal.",
                            "b");

            int oneW = b[0, 0].Width;
            int oneH = b[0, 0].Height;
            int overallWidth = oneW * (b.GetUpperBound(0) + 1);
            int overallHeight = oneH * (b.GetUpperBound(1) + 1);
            Bitmap result = new Bitmap(b[0, 0], overallWidth, overallHeight);

            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                {
                    bmData[i, j] = b[i, j].LockBits(new Rectangle(0, 0, oneW, oneH),
                                                    ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                    scan0[i, j] = bmData[i, j].Scan0;
                    p[i, j] = (byte*)(void*)scan0[i, j];
                }

            BitmapData rbmData = result.LockBits(new Rectangle(0, 0, overallWidth, overallHeight),
                                                 ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData[0, 0].Stride;
            int nOffset = stride - 3*b[0, 0].Width;

            int rStride = rbmData.Stride;
            IntPtr rScan0 = rbmData.Scan0;
            byte* rp = (byte*) (void*) rScan0;

            for (int imgY = 0; imgY < b.GetUpperBound(1); ++imgY)
            {
                for (int imgX = 0; imgX <= b.GetUpperBound(0); ++imgX)
                {
                    byte* currp = p[imgX, imgY];
                    for (int y = 0; y < oneH; ++y)
                    {
                        for (int x = 0; x < 3*oneW; ++x)
                        {
                            rp[rStride*(imgY*oneH + y) + 3*imgX*oneW + x] = currp[0];
                            ++currp;
                        }
                        currp += nOffset;
                    }
                }
            }

            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                    b[i, j].UnlockBits(bmData[i,j]);


            result.UnlockBits(rbmData);
            return result;
        }
    }

查看相册here中的图片。所有这些都不会在这里显示。

2 个答案:

答案 0 :(得分:1)

我犯了最愚蠢的错误。但是,如果它可以帮助任何人,请更改

for (int imgY = 0; imgY < b.GetUpperBound(1); ++imgY)

for (int imgY = 0; imgY <= b.GetUpperBound(1); ++imgY)

<应为<=)。

答案 1 :(得分:0)

我根据你的代码创建了一个版本,它复制像素行而不是像素。似乎至少在我的盒子上工作(更快)。也许你喜欢它。每个循环内的最小变化。 我使用它真的只是为了连接......在将图像变形为甜甜圈之前,可以360度简单地查看多个摄像机图像......

 public static Bitmap Mosaic(ref Bitmap[,] b)
    {
        BitmapData[,] bmData = new BitmapData[b.GetUpperBound(0) + 1, b.GetUpperBound(1) + 1];
        IntPtr[,] scan0 = new IntPtr[b.GetUpperBound(0) + 1, b.GetUpperBound(1) + 1];
        unsafe
        {
            byte*[,] p = new byte*[b.GetUpperBound(0) + 1, b.GetUpperBound(1) + 1];
            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                    if (b[i, j].Width != b[0, 0].Width | b[i, j].Height != b[0, 0].Height)
                        throw new ArgumentException(
                            "Width and Height properties of all elements of b must be equal.",
                            "b");

            int oneW = b[0, 0].Width;
            int oneH = b[0, 0].Height;
            int overallWidth = oneW * (b.GetUpperBound(0) + 1);
            int overallHeight = oneH * (b.GetUpperBound(1) + 1);
            Bitmap result = new Bitmap(b[0, 0], overallWidth, overallHeight);

            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                {
                    bmData[i, j] = b[i, j].LockBits(new Rectangle(0, 0, oneW, oneH),
                                                    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    scan0[i, j] = bmData[i, j].Scan0;
                    p[i, j] = (byte*)(void*)scan0[i, j];
                }

            BitmapData rbmData = result.LockBits(new Rectangle(0, 0, overallWidth, overallHeight),
                                                 ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            int stride = bmData[0, 0].Stride;
            int nOffset = stride - 4 * b[0, 0].Width;

            int rStride = rbmData.Stride;
            IntPtr rScan0 = rbmData.Scan0;
            byte* rp = (byte*)(void*)rScan0;



            for (int imgY = 0; imgY <= b.GetUpperBound(1); ++imgY)
            {
                    for (int y = 0; y < oneH; ++y)
                    {
                        byte* currp = p[0, imgY];
                        for (int imgX = 0; imgX <= b.GetUpperBound(0); ++imgX)
                        {
                            currp = p[imgX, imgY];
                            currp += stride*y;
                        byte[] buffer = new byte[stride];
                        Marshal.Copy(new IntPtr(currp), buffer, 0, buffer.Length);
                        Marshal.Copy(buffer, 0, new IntPtr(rp), buffer.Length);

                        rp += stride;

                        }



                   }



            }

            for (int i = 0; i <= b.GetUpperBound(0); i++)
                for (int j = 0; j <= b.GetUpperBound(1); j++)
                    b[i, j].UnlockBits(bmData[i, j]);


            result.UnlockBits(rbmData);
            return result;
        }
    }