【问题标题】:What's wrong with this decoder? (in C#) - Help with padding extra bytes这个解码器有什么问题? (在 C# 中) - 帮助填充额外的字节
【发布时间】:2011-04-16 01:33:13
【问题描述】:

我这里有一个 PCX 解码器,用 C# 编写,旨在返回一个 IntPtr,它指向一个未压缩字节数组(PCX 文件使用 RLE 压缩,但我的解码器应该能够处理这个问题)。我已经从文件中读取了宽度、尺寸和调色板,对于大多数图像,图像只会将文件渲染为位图,但有些无法正确渲染。图像在那里,颜色也在那里,但实际的位图看起来像是被对角线切割了 4 或 5 次并重新排列。我检查了图像中的飞机数量,bpp也很好。

我认为我的代码有问题,所以如果有人看到错误,请告诉我。


编辑 2:

正如 Guffa 指出的那样,我没有处理任何填充。谁能指出我正确的方向?


代码(抱歉,这里有很多,但它是实际的像素处理器):

IntPtr pBits;
Boolean bRepeat;
Int32 RepeatCount;
Byte ReadByte;
Int32 Row = 0;
Int32 Col = 0;

Byte[] PCXData = new Byte[BytesPerScanline * ScanLines]; //BytesPerScanline * ScanLines);

BinaryReader r = new BinaryReader(file);
r.BaseStream.Seek(128, SeekOrigin.Begin);

while (Row < ScanLines)
{
    ReadByte = r.ReadByte();
    bRepeat = (0xc0 == (ReadByte & 0xC0));
    RepeatCount = (ReadByte & 0x3f);

    if (!(Col >= BytesPerScanline))
    {
        if (bRepeat)
        {
            ReadByte = r.ReadByte();
            while (RepeatCount > 0)
            {
                PCXData[(Row * BytesPerScanline) + Col] = ReadByte;
                RepeatCount -= 1;
                Col += 1;
            }
        }
        else
        {
            PCXData[(Row * BytesPerScanline) + Col] = ReadByte;
            Col += 1;
        }
    }

    if (Col >= BytesPerScanline)
    {
        Col = 0;
        Row += 1;
    }
}

pBits = System.Runtime.InteropServices.Marshal.AllocHGlobal(PCXData.Length);
System.Runtime.InteropServices.Marshal.Copy(PCXData, 0, pBits, PCXData.Length);

return pBits;

【问题讨论】:

  • 您的命名约定(或缺少命名约定)使代码更难阅读。您正在用匈牙利符号命名一些局部变量(在 .NET 中不鼓励这样做),以及其他局部变量,例如它们是方法。例如查看代码ReadByte = r.Readyte(),其中对方法ReadByte 的调用结果放在变量ReadByte...
  • 当您知道每行的迭代次数和要迭代的行数时,您使用while 循环的任何特殊原因?您应该使用 for 循环。
  • 哦,很抱歉匈牙利符号,我不熟悉它,我不知道它不鼓励。至于循环,它不就是和'for'循环做同样的事情吗?
  • @Danel DiPaolo:这完全值得商榷,取决于具体情况、偏好和简洁性。
  • 你如何使用解压后的字节?根据您对问题的描述,听起来您需要在扫描线之间进行一些填充以将每条扫描线放置在均匀的偏移量上。

标签: c# image image-processing


【解决方案1】:

一方面,您没有正确处理非托管资源(例如 BinaryReader)。 完成后调用r.Dispose(),或者将其包装在 using 块中,如下所示:

using(BinaryReader r = new BinaryReader(file))
{
  ...
}

并且始终对实现IDisposable 的任何对象执行此操作。

【讨论】:

  • 好的,我想我需要处理掉它,但是我有一段时间没有做太多的二进制读取了。
  • 事实并非如此。 BinaryReader/Writer 和 StreamReader/Writer 一样是用于解码原始 Stream 字节的辅助类。当您 Dispose 一个助手时,它将释放(关闭)关联的流。这实际上可能不是期望的行为。一个人可能想要独立控制相关流的生命周期。我的建议是仅在助手创建关联流时 Dispose 一个助手,否则 Dispose 流,而不是助手。
  • @Tergiver:是的,我收集到了,因为当我尝试它时,它关闭了流,并且我将同一流用于多个功能,所以它不适合这个。
  • [附录] 我的建议是仅在助手创建关联的 Stream 时才 Dispose 一个助手,或者您已将 Stream 引用的所有权转移给助手,否则 Dispose流,而不是助手。
  • 我不同意。如果它实现了 IDisposable,则将其包装在 using 块中。
猜你喜欢
  • 2018-07-20
  • 2021-12-07
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
相关资源
最近更新 更多