创建代码以解压缩面向字节的RLE图像

问题描述 投票:0回答:2

我正在尝试创建一个代码来解压缩PostScript文件中的RLE Byte-Oriented图像我已经尝试过在网络上找到的解决方案,并且还尝试构建自己的解决方案;但他们都没有产生我需要的结果。

解压缩rle图像后,我应该有一个RAW图像,我可以在photoshop上打开(通知宽度,高度和通道数)。但是,当我尝试打开提取的图像时,它不起作用;只显示黑色输出。

我的输入是二进制ASCII编码文件(编码为十六进制字符串)和二进制文件; RLE Byte-Oriented都是压缩的(在hex文件的情况下,它只是在尝试rle解压缩之前将其转换为字节的问题)。

https://drive.google.com/drive/u/0/folders/1Q476HB9SvOG_RDwK6J7PPycbw94zjPYU我在这里发布了样品。

WorkingSample.raw - > Image Sample我使用了另一个软件及其尺寸。

MySample.raw - >我使用我的代码构建的图像示例及其尺寸。

OriginalFile.ppf - >包含原始图像数据和其他所有内容的文件。

ExtractedBinary.bin - >只有来自OriginalFile.ppf的二进制部分 - 使得更容易阅读和使用数据。

此代码由用户nyerguds提供,他是SO社区的一部分。原始来源:http://www.shikadi.net/moddingwiki/RLE_Compression#Types_of_RLE我尝试使用的那个,但结果不正确。说实话,我很难理解他的代码(他告诉我改变一些东西,以便让它适用于我的情况,但我无法做到)。

以下是我在PostScript红皮书之后尝试做的事情:书:https://www.adobe.com/content/dam/acom/en/devnet/actionscript/articles/PLRM.pdf部分:“RunLengthEncode过滤器根据运行长度以简单字节定向格式对数据进行编码。压缩数据格式是一系列运行,每次运行由一个长度字节后跟1到128个字节的数据组成。如果长度字节在0到127范围内,则在解压缩时将按字面复制以下长度+ 1个字节(1到128个字节)。如果长度为在129到255的范围内,下一个单字节将被复制257 - 解压缩时的长度(2到128次)。页面142,RunLengthEncode过滤器。

List<byte> final = new List<byte>();
                var split01 = ArraySplit(bytefile, 2);
                foreach (var binPart in split01)
                {                    
                    try
                    {
                        if (binPart.ElementAt(0) <= 127)
                        {
                            int currLen = binPart[0] + 1;
                            for (int i = 0; i <= binPart[0]; i++)
                            {
                                final.Add(binPart[1]);
                                //Console.WriteLine(binPart[1]);
                            }
                        }
                        else if (binPart[0] >= 128)
                        {
                            int currLen = 257 - binPart[0];
                            for (int i = 0; i < currLen; i++)
                            {
                                final.Add(binPart[1]);
                                // Console.WriteLine(binPart[1]);
                            }
                        }
                    }
                    catch(Exception)
                    {
                        break;
                    }


                }

                File.WriteAllBytes(@"C:\test\again.raw", final.ToArray());

 private static IEnumerable<byte[]> ArraySplit(byte[] bArray, int intBufforLengt)
        {
            int bArrayLenght = bArray.Length;
            byte[] bReturn = null;

            int i = 0;
            for (; bArrayLenght > (i + 1) * intBufforLengt; i++)
            {
                bReturn = new byte[intBufforLengt];
                Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLengt);
                yield return bReturn;
            }

            int intBufforLeft = bArrayLenght - i * intBufforLengt;
            if (intBufforLeft > 0)
            {
                bReturn = new byte[intBufforLeft];
                Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLeft);
                yield return bReturn;
            }
        }

  private static byte[] StringToByteArray(String hex)
        {
            int iValue = 0;
            int NumberChars = hex.Length;
            if (NumberChars % 2 != 0)
            {
                string m = string.Empty;
            }
            byte[] bytes = new byte[NumberChars / 2];
            try
            {

                for (int i = 0; i < NumberChars; i += 2)
                {
                    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
                    iValue = i;
                }

            }
            catch (Exception e)
            {
                var value = iValue;
                Console.WriteLine(e.Message);
            }


            return bytes;
        }

所需的输出将是TIFF灰度。但是,我也可以处理PNG。我已经设法从这种文件中提取未压缩的数据;使用Emgu(OpenCV Wrapper),我能够创建一个可视图像并在其上执行我的逻辑。

我从RLE压缩的实际结果只是无效的RAW文件,即使在photoshop或IrfanViewer上也无法查看。

任何输入都表示赞赏。谢谢。

编辑1:坚持这一部分

for(int i=0; i < bytefile.Length; i+=2)
            {
                try
                {
                    var lengthByte = bytefile[i];
                    if (lengthByte <= 127)
                    {
                        int currLen = lengthByte + 1;
                        for (int j = 0; j < currLen; j++)
                        {
                            final.Add(bytefile[i]);
                            i++;
                        }

                    }
                    if (bytefile[i] >= 128)
                    {
                        int currLen = 257 - bytefile[i];
                        for (int k = 0; k < currLen; k++)
                        {
                            final.Add(bytefile[i + 1]);
                        }
                    }
                }
                catch(Exception)
                {
                    break;
                }          
            }

这是我遵循的逻辑。在它提出异常之前,但我想出来了(这是因为我忘了添加结束字节;在最终结果中没有任何区别)。

c# postscript image-compression run-length-encoding
2个回答
1
投票

试试这个基本大纲:

int i = 0;
while (i < bytefile.length)    
{
    var lengthByte = bytefile[i++];
    if (lengthByte <= 127)
    {
        int currLen = lengthByte + 1;
        for (int j = 0; j < currLen; j++)
            final.Add(bytefile[i++]);
    }
    else
    {
        int currLen = 257 - lengthByte;
        byte byteToCopy = bytefile[i++];
        for (int j = 0; j < currLen; j++)
            final.Add(byteToCopy);
    }
}

无论如何,这就是我理解上面指出的内容的方式。


0
投票

虽然没有明确说明,但我相信您正在尝试从Postscript文件中提取RunLength编码图像并将其保存为灰度TIFF。

作为这样的起点,您是否尝试将Postscript文件中的未压缩图像保存为灰度TIFF,以确保负责构建TIFF图像数据的应用程序逻辑确实按预期工作?我要提醒一下,在进入现在支持解压缩RLE数据然后变成TIFF之前,这将是一个很好的第一步。

我认为这很重要的原因是因为你的问题可能与你如何解压缩RLE数据无关,而是你如何从大概正确解码的数据创建输出TIFF。

© www.soinside.com 2019 - 2024. All rights reserved.