Создание кода для распаковки байтово-ориентированного изображения RLE - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь создать код для распаковки байтово-ориентированного изображения RLE из файла PostScript. Я уже пробовал решения, найденные в Интернете, а также пытался создать свой собственный;но ни один из них не дал нужного мне результата.

После распаковки изображения rle у меня должно быть изображение RAW, которое я могу открыть в фотошопе (с указанием ширины, высоты и количества каналов).Однако, когда я пытаюсь открыть извлеченное изображение, это не работает;показывается только черный вывод.

Мои входные данные - это двоичный файл в кодировке ASCII (закодированный в виде шестнадцатеричной строки) и двоичный файл;оба сжатых RLE Byte-Oriented (в случае шестнадцатеричного файла, это просто вопрос преобразования его в байты перед попыткой декомпрессии rle).

https://drive.google.com/drive/u/0/folders/1Q476HB9SvOG_RDwK6J7PPycbw94zjPYU Я разместил здесь образцы.

WorkingSample.raw -> Образец изображения, полученный с помощью другого программного обеспечения, а также его размеры.

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 Filter.

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 Compressed - это только недействительные файлы RAW, которые невозможно просмотреть даже в фотошопе или IrfanViewer.

Любой вклад приветствуется.Спасибо.

EDIT1 : застрял на этой части

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

Это логика, которой я следую.До того, как оно вызывало Исключение, но я понял это (это потому, что я забыл добавить завершающий байт; без разницы в конечном результате).

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Попробуйте эту базовую схему:

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 голосов
/ 11 апреля 2019

Хотя это явно не указано, я полагаю, что вы пытаетесь извлечь кодированное изображение RunLength из файла Postscript и сохранить его в формате TIFF в оттенках серого.

В качестве отправной точки для чего-то подобного вы пробовалипросто сохраняя несжатое изображение из файла Postscript в формате TIFF в оттенках серого, чтобы гарантировать, что логика вашего приложения, ответственная за построение данных изображения TIFF, действительно работает так, как вы этого ожидаете?Я хотел бы предостеречь, что это был бы хороший первый шаг, прежде чем перейти к поддержке поддержки распаковки данных RLE, чтобы затем превратить их в TIFF.

Причина, по которой я считаю это важным, заключается в том, что ваша проблема может не иметь ничего общего с как вы распаковываете данные RLE, а скорее как вы создаете свой выходной TIFF из предположительно правильно декодированных данных.

...