欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#合并BitMap图像生成超大bitmap

程序员文章站 2022-06-15 18:42:14
当只需要两个图像合并的时候,可以简单的使用gdi+,把两个图像画到一个画布上面实现合并bitmap.当需要将许多bitmap合并时,由于bitmap类限制,长度或宽度太大时会报异常,前面这种方法就行不...

当只需要两个图像合并的时候,可以简单的使用gdi+,把两个图像画到一个画布上面实现合并bitmap.

当需要将许多bitmap合并时,由于bitmap类限制,长度或宽度太大时会报异常,前面这种方法就行不通了。

由于bitmapp属于位图格式,了解图像格式后,发现,bitmap文件的第3-8位存储了文件大小信息,第19-22位存储了高度信息,第23-26位存储了宽度信息。文件头后面都是像素的argb,并无其它信息。于是,试想一下,如果把第二张图像的像素argb放到第一张后面,并修改第一张的文件头信息,是不是就可以实现文件合并了呢。事实证明:yes。

//设置文件头里面文件大小信息

public void setbitmapfilesizeinfo(string filepath)
        {
            fileinfo fileinfo = new fileinfo(filepath);
            long le = fileinfo.length;
            string hexsize = le.tostring("x").padleft(8, '0');
            int size1 = convert.toint32(hexsize.substring(0, 2), 16);
            int size2 = convert.toint32(hexsize.substring(2, 2), 16);
            int size3 = convert.toint32(hexsize.substring(4, 2), 16);
            int size4 = convert.toint32(hexsize.substring(6, 2), 16);
            byte[] sizebytes = new byte[] { (byte)size4, (byte)size3, (byte)size2, (byte)size1 };
            using (filestream fs = new filestream(filepath, filemode.open, fileaccess.write))
            {
                using (binarywriter r = new binarywriter(fs))
                {
                    r.seek(2, 0);
                    r.write(sizebytes, 0, sizebytes.length);
                }
            }
        }

设置文件头里面文件长度和宽度信息

 public void setbitmapsizeinfo(string filepath,int width=0,int height=0)
        {
            if (height != 0)
            {
                string hexheight = height.tostring("x").padleft(8, '0');
                int h1 = convert.toint32(hexheight.substring(0, 2), 16);
                int h2 = convert.toint32(hexheight.substring(2, 2), 16);
                int h3 = convert.toint32(hexheight.substring(4, 2), 16);
                int h4 = convert.toint32(hexheight.substring(6, 2), 16);
                byte[] sizeheight = new byte[] { (byte)h4, (byte)h3, (byte)h2, (byte)h1 };
                using (filestream fs = new filestream(filepath, filemode.open, fileaccess.readwrite))
                {
                    using (binarywriter r = new binarywriter(fs))
                    {
                        r.seek(22, 0);//高度保存位置
                        r.write(sizeheight, 0, sizeheight.length);
                    }
                }
            }
            if (width != 0)
            {
                string hexwidth = height.tostring("x").padleft(8, '0');
                int w1 = convert.toint32(hexwidth.substring(0, 2), 16);
                int w2 = convert.toint32(hexwidth.substring(2, 2), 16);
                int w3 = convert.toint32(hexwidth.substring(4, 2), 16);
                int w4 = convert.toint32(hexwidth.substring(6, 2), 16);
                byte[] sizewidth = new byte[] { (byte)w4, (byte)w3, (byte)w2, (byte)w1 };
                using (filestream fs = new filestream(filepath, filemode.open, fileaccess.readwrite))
                {
                    using (binarywriter r = new binarywriter(fs))
                    {
                        r.seek(18, 0);//高度保存位置
                        r.write(sizewidth, 0, sizewidth.length);
                    }
                }
            }
        }

合并多个bitmap文件,并生成一个最终文件

private void createbitmap(string temppath,string imagepath)
        {
            string[] files = directory.getfiles(temppath, "*.png");
            bitmap bmp;
            int height=0;
            for (int i = files.length-1; i >0; i--)
            {
                string filename = files[i];
                bmp = new bitmap(filename);
                if (i == files.length - 1)
                {
                    bmp.save(imagepath, imageformat.bmp);
                    height += bmp.height;
                    bmp.dispose();
                    continue;
                }
                else
                {
                    byte[] bytes = getimagerasterbytes(bmp, pixelformat.format32bpprgb);
                    using (filestream fs = new filestream(imagepath, filemode.open, fileaccess.write))
                    {
                        fs.seek(fs.length, 0);
                        fs.write(bytes, 0, bytes.length);
                    }
                    height += bmp.height;
                    bmp.dispose();
                }
            }
            setbitmapfilesizeinfo(imagepath);
            setbitmapsizeinfo(imagepath, height: height);
            //messagebox.show("合并成功");
        }
         private static byte[] getimagerasterbytes(bitmap bmp, pixelformat format)
        {
            rectangle rect = new rectangle(0, 0, bmp.width, bmp.height);
            byte[] bits = null;
            try
            {
                // lock the managed memory
                bitmapdata bmpdata = bmp.lockbits(rect, imagelockmode.readwrite, format);
                // declare an array to hold the bytes of the bitmap.
                bits = new byte[bmpdata.stride * bmpdata.height];
                // copy the values into the array.
                system.runtime.interopservices.marshal.copy(bmpdata.scan0, bits, 0, bits.length);
                // release managed memory
                bmp.unlockbits(bmpdata);
            }
            catch
            {
                return null;
            }
            return bits;
        }

到此这篇关于c#合并bitmap图像生成超大bitmap的文章就介绍到这了,更多相关c#合并bitmap内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关标签: C# 合并 BitMap