2013-03-27 54 views
2

我需要將幾個BMP圖像附加在一起。您可能知道,BMP圖像具有一個54字節的標題。我會將自己的新頭文件寫入一個新文件,然後我需要遍歷BMP文件列表並將它們附加到對方,但我需要跳過每個文件的前54個字節。讀取文件A並追加到文件B,跳過一些字節

這是一個千兆像素圖像拼接項目。我會使用已存在的軟件,但圖像中沒有重疊(但我知道拼貼布局)。我需要能夠將一些非常大的BMP文件(192,000x1080)作爲行並將它們附加到另一個之下以創建最終圖像,即20.7 gigapixels。雖然我有32GB的內存,但最終的20.7千萬像素圖像將會是62.2GB(然後我將轉換爲PNG)。

鑑於這些巨大的內存要求,我如何讀取每個BMP並將它們追加到最終文件而不使用我所有的內存?如果可能,我想使用字節數組;因爲這些是非壓縮的BMP,它們可以像這樣讀取並保存到另一個文件,而不使用任何GDI對象。

+2

>如何讀取每個BMP並將它們追加到最終文件而不使用我所有的內存? 流式傳輸文件。 – Romoku 2013-03-27 12:55:29

回答

4

您可以寫入文件中的任意位置。以:

using(var s = new FileStream("myBigImage.bmp", FileMode.Create, FileAccess.Write)) { 
    //assume that you write out the header here 
    foreach(var tileFile in tiles) { 
     byte[] imgData = /*read image data into a byte[]*/; 
     long y = /*obtain the correct y offset*/; 

     s.Position = y * pixelWidth * imageWidth + 58; 
     s.Write(imgData, 0, imgData.Length); 

    } 
} 

基本上,你可以跳過文件來填寫任何你想要的。 Position是一個很長的值,所以你不必擔心碰到32位整數的限制。

幸運的是,因爲你的圖片基本上只是一大堆瓷磚,所以你不必擔心處理每一行。在這種情況下,爲了保持內存不變,你必須單獨寫出每個瓦片的線條。

+0

我的回答有幫助嗎?如果是這樣,一個接受的答案將不勝感激! – 2013-10-22 21:34:53

1

您不需要將所有生成的文件數據保存在內存中。只需打開FileStream並將數據寫入文件即可。即使您寫入千兆字節的數據,FileStream也不會使用太多的內存。

0

如果有人在我之後有興趣,這裏是我的發現工作:

for (int i = 0; i < reverseImageFiles.Length; i++) 
     { 
      string curBMP = reverseImageFiles[i]; 

      using(Stream inStream = File.OpenRead(curBMP)) 
      using (Stream writeStream = new FileStream(outputBMP,FileMode.Append,FileAccess.Write,FileShare.None)) 
      { 
       BinaryReader reader = new BinaryReader(inStream); 
       BinaryWriter writer = new BinaryWriter(writeStream); 

       byte[] buffer = new Byte[134217728]; 
       int bytesRead; 
       int totalBytes = 0; 

       while ((bytesRead = inStream.Read(buffer, 0, 134217728)) > 0) 
       { 
        totalBytes += bytesRead; 

        if (totalBytes <= 134217729) //if it's the first round of reading to the buffer, you need to get rid of 54-byte BMP header 
        { 
         writeStream.Write(buffer, 54, bytesRead - 54); 
        } 
        else 
        { 
         writeStream.Write(buffer, 0, bytesRead); 
        } 
       } 

      } 
     } 

兩件事情:

專門爲BMP的,我發現,你需要扭轉的文件列表追加時。例如,如果要附加的三個文件標記爲001.bmp,002.bmp,003.bmp,其中001.bmp應位於最上方,則您需要實際從003.bmp開始並逐漸減少。顯然BMP是向後編碼的。

正如您所看到的,我使用了一個128MB緩衝區。如果我想降低硬盤驅動器的搜索速度,使用不同的大小會更好嗎?我的驅動器最近進行了整理。感謝所有的幫助!