Кодування довжин серій (англ. Run-length encoding, RLE) або Кодування повторів — простий алгоритм стиснення даних, який оперує серіями даних, тобто послідовностями, в яких один і той же символ зустрічається кілька разів поспіль. При кодуванні рядок однакових символів, що становлять серію, замінюється рядком, який містить сам повторюваний символ і кількість його повторів.

Приклад використання

Розглянемо зображення, що містить простий чорний текст на суцільному білому фоні. Тут буде багато серій білих пікселів в порожніх місцях, і багато коротких серій чорних пікселів в тексті. Нехай, наприклад, дано довільний рядок чорно-білого зображення. Тут B (англ. Black) позначає чорний піксель, а W (англ. White) - білий:

WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW

Якщо ми застосуємо просте кодування довжин серій до цього рядка, то отримаємо таке:

12W1B12W3B24W1B14W

Останній запис інтерпретується як «дванадцять W», «одна B», «дванадцять W», «три B» і т. д. Таким чином, код подає вихідні 67 символів у вигляді всього лише 18.


Однак, у випадку, якщо рядок містить велику кількість неповторюваних символів, його обсяг може зрости.

ABCABCABCDDDFFFFFF
1A1B1C1A1B1C1A1B1C3D6F

Проблема вирішується досить просто. Алфавіт, в якому записані довжини серій, розділяється на дві (зазвичай рівні) частини. Алфавіт цілих чисел можна, наприклад, розділити на дві частини: додатні і від'ємні. Додатні використовують для запису кількості повторюваних однакових символів, а від'ємні — для запису кількості неоднакових.

-9ABCABCABC3D6F

Оскільки чисельні типи даних на комп'ютері завжди мають певну межу, виникає ще одна проблема. Припустимо, ми використовуємо тип signed char для запису довжин серій. Тоді ми не можемо записати серію, довшу ніж 127 символів, однією парою «довжина-символ». Якщо поспіль записано 256 символів A, їх розділяють на мінімальну кількість груп:

127A127A2A

Реалізація на конкретній мові програмування алгоритму RLE з урахуванням цих обмежень може бути нетривіальною.

Звичайно, кодування, яке використовується для зберігання зображень, оперує з двійковими даними, а не з символами ASCII, як у розглянутому прикладі, однак принцип залишається таким самим.

Застосування

Вочевидь, що таке кодування ефективно для даних, що містять велику кількість серій, наприклад, для простих графічних зображень, таких як іконки та графічні малюнки. Однак це кодування погано підходить для зображень з плавним переходом тонів, таких як фотографії.

Поширені формати для упаковки даних за допомогою RLE включають в себе PackBits, PCX і ILBM.

Методом кодування довжин серій можуть бути стиснуті довільні файли з двійковими даними, оскільки специфікації на формати файлів часто включають в себе повторювані байти в області вирівнювання даних. Проте, сучасні системи стиснення (наприклад, DEFLATE) частіше використовують алгоритми на основі LZ77, які є узагальненням методу кодування довжин серій і оперують з послідовностями символів виду «BWWBWWBWWBWW».

Звукові дані, які мають довгі послідовні серії байт (такі як низькоякісні звукові семпли) можуть бути стиснуті за допомогою RLE після того, як до них буде застосовано Дельта-кодування.

Реалізація алгоритму мовою C/C++

#include <stdio.h>
 #include <string.h>
 
 int main()
 {
     int cnt;
     char smb;
     char *code = new char [80];
     char *encode = new char [80];
     char *str = new char [80];
 
     scanf("%s", code);
 
     strcpy(encode, "");
     smb = code[0];
     cnt = 0;
 
     for (int i = 0; i <= strlen(code); i++) {
         if (code[i]==smb) {
             cnt++;
         }
         else {
             sprintf(str, "%d", cnt);
             strcat(encode, str);
             sprintf(str, "%c", smb);
             strcat(encode, str);
             smb = code[i];
             cnt = 1;
         }
     }
 
     printf("%s\n", encode);
 
     return 0;
 }
 

Реалізація алгоритму мовою PHP

<?php
 $code = 'fafaaaaaaaaaaaaa';
 $encode = '';
 
 for ($i = 0; $i < strlen($code);$i++){
 	$smb = $code[$i] ;
 	$count = 1 ;
 	for ($b = $i; $b < strlen($code);$b++){
 		if ($code[$b + 1] != $smb) break ;
 		$count++ ;
 
 		$i++ ;
 	}
 	$encode .= $count . $smb ;
 }
 print 'Рядок: ' . $code . ' вдалося стиснути до ' . $encode . '.<br /> і ми заощадили ' . (strlen($code) - strlen($encode)) . ' байтів.' 
 ?>
 

Реалізації алгоритму мовою Delphi/Pascal

function encode(s:string):string;
 var i,k:integer; c:char;
 begin
   Result:='';
   if s='' then exit;
   c:=s[1]; 
   k:=1;
   for i:=2 to length(s)+1 do
     if s[i]=c then inc(k) else
       begin
         if k>1 then Result:=Result+IntToStr(k);
         Result:=Result+c;
         c:=s[i];
         k:=1;
       end;
 end;
  
 function decode(s:string):string;
 var i,j,c:integer;
     newS:string;
 begin
 i:=1;
 while i <= length(s) do
   begin
     j:=i;
     while s[j] in ['0'..'9'] do inc(j);
     if j-i > 0 then
     begin
       for c:=1 to strtoint(copy(s,i,j-i)) do newS := newS + s[j];
       delete(s,i,j-i+1);
     end else
     begin
       newS := newS + s[i];
       inc(i);
     end;
   end;
   result:= newS;
 end;
 

Реалізації алгоритму на Visual Basic 6

Public Function Encode(ByVal SrcString As String) As String
     Dim I As Long, N As Long, sResult As String
     N = 1
     
     For I = 1 To Len(SrcString)
         If Not Mid(SrcString, I, 1) = Mid(SrcString, I + 1, 1) Then
             sResult = sResult & IIf(I - N + 1 > 1, CStr(I - N + 1), CStr("")) & Mid(SrcString, I, 1)
             N = I + 1
         End If
     Next
     
     Encode = sResult
 End Function
 

Див. також



Інформація

Стаття RLE в українській Вікіпедії посіла такі місця в місцевому рейтингу популярності:

Представлений вміст статті Вікіпедії було вилучено в 2020-11-09 на основі https://uk.wikipedia.org/?curid=1709922