【问题标题】:Reading file in reverse反向读取文件
【发布时间】:2013-04-01 13:13:46
【问题描述】:

因为 BMP 文件是从下到上(以像素为单位)写入的,所以我需要反向读取 BMP 文件(并去掉 54 字节的标头)。到目前为止我的代码:

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;
    }

由于某种原因,它无法完全完成这项工作,这导致图像右侧的一部分位于左侧。为什么不完全反转文件?此外,这些 BMP 文件非常大(600MB),所以我不能使用简单的内存流进行查找和交换操作,因为我会得到“内存不足”异常。

【问题讨论】:

  • 为什么你提到你不能阅读整个文件,而你却读了?此外,永远不要像您那样对数组的值进行硬编码。不保证会有 138 字节的标头数据。
  • 如果使用 MemoryStream 会给您带来 OOM 异常,您如何为 fullBMP 数组分配空间而不会收到相同的异常?
  • MemoryStream 和 Byte[] 本质上是一样的,MS 有一些额外的包装器可以使它更容易处理...见stackoverflow.com/questions/16939/…stackoverflow.com/questions/11828599/…

标签: c# filestream reverse


【解决方案1】:

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

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

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

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

将右侧图像的一部分显示在左侧的原因是,您不能只反转位图的字节并期望它正确显示。另外,你画的时候可能扫描线的长度不对。

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

【讨论】:

    【解决方案2】:

    我发布了一个答案 here 用于反转大文件而不将其存储在 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多