0

Because BMP files are written from bottom to top (in terms of pixels), I need to read a BMP file in reverse (and get rid of the 54-byte header). My code so far:

public string createNoHeaderBMP(string curBMP)  //copies everything but the header    from the curBMP to the tempBMP
    {
        string tempBMP = "C:\\TEMP.bmp";

        Stream inStream = File.OpenRead(curBMP);
        BinaryReader br = new BinaryReader(inStream);

        byte[] fullBMP = new byte[(width * height * 3) + 138];
        byte[] buffer = new Byte[1];
        long bytesRead;
        long totalBytes = 0;

        while ((bytesRead = br.Read(buffer, 0, 1)) > 0)
        {
            fullBMP[fullBMP.Length - 1 - totalBytes] = buffer[0];
            totalBytes++;
        }

        FileStream fs = new FileStream(tempBMP, FileMode.Create, FileAccess.Write);
        fs.Write(fullBMP, 54, fullBMP.Length - 54);
        fs.Close();
        fs.Dispose();

        return tempBMP;
    }

for some reason it fails to do the job completely, and this results in an image with part of the right side placed on the left. Why isn't it completely reversing the file? Also, these BMP files are very large (600MB), so I can't use a simple memorystream and do a seek and swap operation because I'll get the "Out of Memory" exception.

4

2 回答 2

2

我没有检查 BMP 规范,我对此一无所知。我只是假设你说的是真的。

大多数显示位图的程序只是读取标题以找出图像有多大,然后从上到下读取数据,而不是从下到上绘制位图。您还可以在大多数文件中查找。因此,您可以在其中使用inStream和查找,而无需将整个文件保存在内存中。

然后,如果您可以分配一个 600 MiB 的字节数组(即内存中的 600 MiB 结构),那么您肯定可以分配一个MemoryStream占用 600 MiB 内存空间的字节数组。或者,如果你得到一个OutOfMemoryException,那么无论你使用 abyte[]还是 a ,你都会得到它MemoryStream。后者更容易使用。

除非您意识到您还将每个像素的颜色从 RGB 格式(或目前的任何格式)反转为 BGR,否则您仅反转一切的想法将失败。而且我不确定 BMP 扫描线的方向,但如果它们从左到右运行,那么您的反转位图将使图像水平翻转。

将右侧图像的一部分显示在左侧的原因是因为您不能只反转位图的字节并期望它正确显示。此外,您可能在绘制时扫描线的长度错误。

此外,您说标头是 54 字节,但您将 138 字节添加到fullBMP. 检查你的常量:它们是否保证永远不会改变,然后让它们const. 他们可以改变吗?然后从位图中读取它们。

于 2013-04-01T13:42:49.230 回答
0

我在这里发布了一个答案,用于反转大文件而不将其存储在 RAM 中。

你可以用它来做这样的事情(可能需要调整以获得正确的位图,如丹尼尔所说):

using (var inputFile = File.OpenRead("input.bmp"))
using (var inputFileReversed = new ReverseStream(inputFile))
using (var outputFile = File.Open("output.bmp", FileMode.Create, FileAccess.Write))
{
    inputFile.Seek(headerSize, SeekOrigin.Begin); //skip the header
    inputFileReversed.CopyTo(outputFile);
}
于 2021-07-09T15:50:32.650 回答