使用VB.Net合并大图像

时间:2017-05-30 02:36:00

标签: vb.net image large-files image-stitching

我希望有人可以帮我合并几张大图(PNG)。我有多达30个20000x2000的图像,想要合并它们。输出是可以加载到GIS软件中的图像。

我遇到的问题是关于第4张照片后我失去记忆。

我下面的代码基本上将整个图像保存在内存中,就像缝合一样。有没有办法有效地拼接图像而不将其全部加载到内存中,或者,增加内存容量并使用我的所有RAM和/或虚拟内存?

    Public Function stitchAllImagesOnXAxis(imageDirectoryPath As String, outputImagePath As String) As Boolean
    Try
        Dim evolvingImage As Bitmap
        Dim filenames() As String = IO.Directory.GetFiles(imageDirectoryPath)

        For i As Integer = 0 To filenames.Count - 1

            If Not filenames(i).EndsWith(".png") Then filenames = filenames.RemoveAt(i)

        Next i

        If filenames.Count = 0 Then Return False

        Dim FS As New IO.FileStream(filenames(0), IO.FileMode.Open)
        evolvingImage = Bitmap.FromStream(FS)
        FS.Close()



        For i As Integer = 1 To filenames.Count - 1

            FS = New IO.FileStream(filenames(i), IO.FileMode.Open)
            evolvingImage = stitchImagesOnXAxis(evolvingImage, Bitmap.FromStream(FS), 5)
            FS.Close()

        Next

        evolvingImage.Save(outputImagePath, Imaging.ImageFormat.Png)
        evolvingImage.Dispose()

        Return True
    Catch ex As Exception
        Debug.WriteLine(ex.Message)
        Return False
    End Try

1 个答案:

答案 0 :(得分:0)

 Public Function stitchAllImagesOnXAxisSO(imageDirectoryPath As String, outputImagePath As String, tolerance As Integer) As Boolean

    Try
        'blank 54 byte header for BMP
        Dim headerBytes() As Byte = blankHeader()

        'track the total width of the bmp for the header information
        Dim totalWidth As Integer = 0

        'the height of the BMP (assumes all images being joined are the same height)
        Dim height As Integer = 0

        'the files in the directory specified
        Dim filenames() As String = IO.Directory.GetFiles(imageDirectoryPath)

        'the filestream used to read each file
        Dim FS As IO.FileStream

        'a class to read the header information of the BMP files
        Dim dynamicHeaderInfo As BMPHeaderInformation

        'byte array to copy the bytes read to
        Dim copyBuffer() As Byte

        'ensure each file is a bmp file
        For i As Integer = 1 To filenames.Count - 1

            If Not filenames(i).EndsWith(".bmp") Then filenames = filenames.RemoveAt(i)

        Next i

        'if there isn't more than one image available then exit
        If filenames.Count < 2 Then Return False

        'if the output image exists than delete it
        If IO.File.Exists(outputImagePath) Then IO.File.Delete(outputImagePath)

        'and open it as new 
        Dim evolvingImageFS As New IO.FileStream(outputImagePath, IO.FileMode.OpenOrCreate)

        'write a blank header
        evolvingImageFS.Write(headerBytes, 0, headerBytes.Length)

        'set the height of the overall image (all images assumed the same height)
        dynamicHeaderInfo = New BMPHeaderInformation(filenames(0))
        height = dynamicHeaderInfo.width

        'writing one row at a time from one image at a time

        For row As Integer = 0 To height - 1

            For i As Integer = 0 To filenames.Count - 1

                'get the header data
                dynamicHeaderInfo = New BMPHeaderInformation(filenames(i))

                'open the file
                FS = New IO.FileStream(filenames(i), IO.FileMode.Open)



                'each time we are looking at the first row of an image add that width to the overall width
                If row = 0 Then totalWidth += dynamicHeaderInfo.width

                'set the position of the stream
                FS.Position = dynamicHeaderInfo.headerLength + (row * dynamicHeaderInfo.width * 3) + (row * dynamicHeaderInfo.rowPaddingLength)

                'set up the byte array to read in the bytes
                ReDim copyBuffer((dynamicHeaderInfo.width * 3) - 1)
                FS.Read(copyBuffer, 0, dynamicHeaderInfo.width * 3)
                'write the bytes to the new stream
                evolvingImageFS.Write(copyBuffer, 0, dynamicHeaderInfo.width * 3)

                'if we are at the last image and the total width is less than 500, write the trailing zeros on the row
                If i = filenames.Count - 1 Then padRowFromStream(totalWidth, evolvingImageFS)

                'close the stream
                FS.Close()
                FS.Dispose()

            Next

        Next

        'set the new header information
        setNewWidth(totalWidth, evolvingImageFS)
        setNewheight(height, evolvingImageFS)
        setNewImageFileSize(evolvingImageFS.Length, evolvingImageFS)
        setNewImageAreaSize(evolvingImageFS.Length - headerBytes.Length, evolvingImageFS)

        'close off the stream
        evolvingImageFS.Close()
        evolvingImageFS.Dispose()

        Return True
    Catch ex As Exception
        Debug.WriteLine(ex.Message)
        Return False
    End Try
End Function

对于任何有兴趣的人,我已发布我的解决方案。这对我很有用,但可能需要对个别用途进行一些调整。这也受到bmp文件的理论限制为16 ^ 8字节的限制。