DOURNAC.ORG
Français  English
Home
Astronomy
Sciences
Philosophy
Coding
Cv

Coding > Image Compression and Decompression with N-Ary and Quaternary trees



Table of contents

  • Specifications of N-Ary generic package
    • Representation
    • Operations
      • Creation
      • Consultation
      • Modification

  • Conception of N-Ary generic package
    • Structuration of data
    • Algorithmic refining
      • function Nt_Create_Empty
      • function Nt_Create_Leaf
      • function Nt_Empty
      • function Nt_Value
      • function Nt_Father
      • function Nt_Child
      • function Nt_Brother
      • procedure Nt_Display
      • function Nt_Search
      • function Nt_Number_Children
      • function Nt_Is_Leaf
      • function Nt_Is_Root
      • procedure Nt_Change_Value
      • procedure Nt_Insert_Child
      • procedure Nt_Insert_Brother
      • procedure Nt_Delete_Child
      • procedure Nt_Delete_Brother
      • procedure Nt_Change

  • Specifications of Quaternary generic package
    • Representation
    • Operations

  • Conception of Quaternay tree generic package
    • Structuration of data
    • Algorithmic refining
      • procedure Qt_Build
      • function Qt_North_West

  • Specifications of pimage package with compression
  • Conception of pimage package
    • Structuration of data
    • Algorithmic refining
      • procedure im_to_tree
      • function is_homogeneous
      • procedure save_imagec
      • procedure tree_to_imc
    • Algorithmic refining for decompression
      • procedure load_im_encod
      • function imc_to_tree
      • procedure tree_to_im
      • procedure thresh_im

  • Validation of packages
    • n-ary and quaternary packages
    • pimage package

Introduction

The aim of this project is to develop generic packages on n-ary and quaternary trees. These packages will be reused to implement another package allowing to achieve image compression and decompression.

Specifications of N-Ary generic package

A n-ary tree is a rooted tree in which each node has no more than n children.

Representation

it can be represented by :

  • A value at the root of tree
  • A father tree
  • A children tree
  • A brother tree

This structure will be implemented thanks to pointers.

Operations

Operations that one has to operate on n-ary tree are grouped into 3 categories : creation, consultation and modification. Here are the list of procedures to code.

Creation

  • Nt_Create_Empty: create an empty n-ary tree.
  • Nt_Create_Leaf: create a n-ary tree with a value, without brother or father.

Consultation

  • Nt_Empty: check if tree is empty or not.
  • Nt_Value: return value at the root of tree.
  • Nt_Father: return father tree of tree.
  • Nt_Child: return the n-th children tree of tree.
  • Nt_Brother: return the n-th brother tree of tree.
  • Nt_Display: display all content of tree.
  • Nt_Search: search for a value into tree and return tree whose root value is found. If nothing is found, return an empty tree.
  • Nt_Number_Children: return the number of chidren tree at first level. d'un arbre.
  • Nt_Is_Leaf: check if tree is a leaf (no child).
  • Nt_Is_Root: check if tree has no father.

Modification

  • Nt_Change_Value: change value at the root of tree.
  • Nt_Insert_Child: insert a tree without brother at position of first child. Old child becomes the first brother of inserted tree.
  • Nt_Insert_Brother: insert a tree without brother at position of first brother.
  • Nt_Delete_Child: delete the n-th child of tree.
  • Nt_Delete_Brother: delete the n-th brother of tree.
  • Nt_Change: apply a function to each element of tree.

Conception of N-Ary generic package

Structuration of data

A node is represented by a record type containing the value of the root, a pointer on the first child, a pointer on the brother and another one on the father tree. The tree_nr type is set to private for hiding from user package the data structure chosen to represent the n-ary tree.

\begin{lstlisting}[language=ada]
	   type node;
	   type tree_nr is access node;
	   type no...
	   ...ild: tree_nr;
brother: tree_nr;
father: tree_nr;
end record;
\end{lstlisting}

We chose to pass as generic parameters the type of value of the root, the procedure which displays element and the function that will be applied to each element.

\begin{lstlisting}[language=ada]
generic
type T is private;
with procedure write ( a: in T );
with function main_function ( a: in T) return T;
\end{lstlisting}

Algorithmic refining

We describe now procedures and functions that we have coded.

function Nt_Create_Empty

\begin{lstlisting}[language=ada]
function Nt_Create_Empty return tree_nr isbeginreturn null;end Nt_Create_Empty;
\end{lstlisting}

function Nt_Create_Leaf

\begin{lstlisting}[language=ada]
function Nt_Create_Leaf ( value : in T ) return...
...a.brother:=null;
a.father:=null;
return a;end Nt_Create_Leaf;
\end{lstlisting}

function Nt_Empty

\begin{lstlisting}[language=ada]
function Nt_Empty ( a: in tree_nr ) return boolean isbeginreturn (a=null);end Nt_Empty;
\end{lstlisting}

function Nt_Value

\begin{lstlisting}[language=ada]
function Nt_Value ( a: in tree_nr ) return T is...
...ption
when constraint_error => raise tree_empty;end Nt_Value;
\end{lstlisting}

We raise tree_empty exception if there is a constraint_error. We let it propagate up to test program where it is processed.

function Nt_Father

\begin{lstlisting}[language=ada]
function Nt_Father ( a: in tree_nr ) return tre...
...empty;
else
return a.father;
end if;
end if;end Nt_Father;
\end{lstlisting}

If tree has no father, we raise relation_empty exception.

function Nt_Child

\begin{lstlisting}[language=ada]
function Nt_Child ( a: in tree_nr; n: in intege...
  ...n
  when constraint_error => raise relation_empty;
  end Nt_Child;
  \end{lstlisting}

We raise relation_empty exception if there is a constraint error.

function Nt_Brother

\begin{lstlisting}[language=ada]
function Nt_Brother ( a: in tree_nr; n: in inte...
  ... when constraint_error => raise relation_empty;
  end Nt_Brother;
  \end{lstlisting}

procedure Nt_Display

For displaying the tree, we use a recursive auxiliary procedure which will allow to browse tree.

\begin{lstlisting}[language=ada]
  procedure Nt_Display( a: in tree_nr ) isbegin...
  ... put('' '');
Nt_Display_Aux(a,'' '');
end if;end Nt_Display;
\end{lstlisting}

Auxiliay procedure is as follow:

\begin{lstlisting}[language=ada]
procedure Nt_Display_Aux( a: in tree_nr ; str_s...
  ...(a.brother,str_shift);
  end if;end if;end Nt_Display_Aux;
  \end{lstlisting}

We browse firstly along the first children with a shift on display and along the brothers keeping the same shift for all brothers.

function Nt_Search

We use also here an auxiliary procedure that make browse the tree along two ways of recursivity, the children one and the brothers one.

\begin{lstlisting}[language=ada]
function Nt_Search ( a: in tree_nr; e: in T ) r...
...curr,stop);
return tree_curr;
end if;
end if;end Nt_Search;
\end{lstlisting}

The auxiliary procedure is as follow : we use a boolean, passed as data/results parameters, to finish the recursive calls if value is found. If it is found, tree_curr is set to a null pointer.

\begin{lstlisting}[language=ada]
procedure Nt_Search_Aux ( tree :in tree_nr ; e:...
  ...p);
else null;
end if;
end if;
end if;end Nt_Search_Aux;
\end{lstlisting}

function Nt_Number_Children

We count the number of children of a tree passed as parameter.

\begin{lstlisting}[language=ada]
function Nt_Number_Children( a: in tree_nr ) re...
... n;
else
return 1;
end if;
end if;end Nt_Number_Children;
\end{lstlisting}

function Nt_Is_Leaf

\begin{lstlisting}[language=ada]
function Nt_Is_Leaf( a: in tree_nr )return bool...
...on
when constraint_error => raise tree_empty;end Nt_Is_Leaf;
\end{lstlisting}

function Nt_Is_Root

\begin{lstlisting}[language=ada]
function Nt_Is_Root( a: in tree_nr )return bool...
...on
when constraint_error => raise tree_empty;end Nt_Is_Root;
\end{lstlisting}

procedure Nt_Change_Value

\begin{lstlisting}[language=ada]
procedure Nt_Change_Value( a:in out tree_nr; e:...
  ...hen constraint_error => raise tree_empty;end Nt_Change_Value;
  \end{lstlisting}

procedure Nt_Insert_Child

\begin{lstlisting}[language=ada]
  procedure Nt_Insert_Child ( tree: in out tree_n...
   ..._child:=tree_i;
   end if;
   end if;
   end if;end Nt_Insert_Child;
   \end{lstlisting}

procedure Nt_Insert_Brother

\begin{lstlisting}[language=ada]
   procedure Nt_Insert_Brother( tree: in out tree_...
    ... tree.brother:=tree_i;
    end if;
    end if;end Nt_Insert_Brother;
    \end{lstlisting}

procedure Nt_Delete_Child

\begin{lstlisting}[language=ada]
    procedure Nt_Delete_Child ( a: in out tree_nr ;...
     ...rother:=a_next;
     end if;
     end if;
     end if;end Nt_Delete_Child;
     \end{lstlisting}

procedure Nt_Delete_Brother

\begin{lstlisting}[language=ada]
     procedure Nt_Delete_Brother ( a :in out tree_nr...
      ... noting
      when constraint_error => null;end Nt_Delete_Brother;
      \end{lstlisting}

procedure Nt_Change

The main function "main_function" is passed as generic parameter when tree_nary package is instancied.

\begin{lstlisting}[language=ada]
      procedure Nt_Change( a: in out tree_nr ) isbe...
     ...a.first_child);
     Nt_Change(a.brother);
     end if;end Nt_Change;
     \end{lstlisting}

Specifications of Quaternary generic package

Representation

A quaternary tree is a tree with 0 or 4 children. These 4 children are called north-west, north-east, south-west and south-east child.

Operations

The following operations are the same as the implemented ones for tree_nary package:

Qt_Create_Empty, Qt_Create_Leaf, Qt_Empty, Qt_Value, Qt_Father, Qt_Display, Qt_Search, Qt_Is_Leaf, Qt_Is_Root, Qt_Change_Value, Qt_Change.

New functions to code are:

  • Qt_Build: create a quaternary tree from one value and 4 children.
  • Qt_North_West: returns the north-west child of quaternary tree.
  • Qt_North_East: returns the north-east child of quaternary tree.
  • Qt_South_West: returns the south-west child of quaternary tree.
  • Qt_South_East: returns the south-east child of quaternary tree.

Conception of Quaternay tree generic package

Structuration of data

Quaternary tree being a subcategory of n-ary tree, we declare a type "quaternary tree", which is a subtype of n-ary tree. The generic parameters are the same as parameters of n-ary tree package.

Algorithmic refining

We use "renames" ADA directive in specification part. This will allow to reuse all procedures and functions implemented into n-ary tree package. Example :

\begin{lstlisting}[language=ada]
     function Qt_Create_Empty return quat_tree renames Nt_Create_Empty;
     \end{lstlisting}

We do the same thing for exceptions :

\begin{lstlisting}[language=ada]
     -- empty tree
     treeq_empty: exception renames tr...
     ... no relation
     relationq_empty: exception renames relation_empty;
     \end{lstlisting}

We define a childq_empty exception for Qt_Build procedure.

procedure Qt_Build

\begin{lstlisting}[language=ada]
     -----------------------------------------------...
     ...t_ne);
     Nt_Insert_Child(tree_res,t_nw);end if;end Qt_Build;
     \end{lstlisting}

function Qt_North_West

We use here Nt_Child function which returns the n-th child of a tree.

\begin{lstlisting}[language=ada]
     function Qt_North_West( a: in tree_quat ) return tree_quat isbeginreturn Nt_Child(a,1);end Qt_North_West;
     \end{lstlisting}

We do the same thing for Qt_North_East (return Nt_Child(a,2)), Qt_South_West (return Nt_Child(a,3)), Qt_South_East (return Nt_Child(a,4)).

Specifications of pimage package with compression

The aim est to carry out compression and decompression on an image using a quaternary tree. The images that we use are squares and their dimension is a power of 2. A color is defined from the 3 primary colors (red, green, blue) and is integer coded.

The recursive compression algorithm of a image with dimension n is as follows : if image is homogeneous, then we create a leaf whose root value is the color of image. If image is not homogeneous, we split it into 4 sub-images of dimension n/2, and we create a quaternary tree whose the four children are the 4 encoded sub-images.

Browsing all the quaternary tree, we get a set of values representing the compressed image.

It is specified that pimage package allows to :

  • create a test image from a dimension and a matrix.
  • load an image from a file.
  • save an image into a file.
  • display an image.
  • load an encoded image from a file.
  • save an encoded image into a file.
  • achieve an operation on an image.

Conception of pimage package

Structuration of data

We choose to define a color by a 32 bits value (pixel). Image is a matrix of pixels. We use dynamic arrays.

\begin{lstlisting}[language=ada]
 -- subtype tree_im
 subtype tree_im is tree_qua...
 ...pe image is array (integer range <>,integer range <>) of pixel;
 \end{lstlisting}

Algorithmic refining

procedure im_to_tree

This procedure is building a tree from an image. We follows the encoding algorithm :

\begin{lstlisting}[language=ada]
 -----------------------------------------------...
 ...(-1,a_nw,a_ne,a_sw,a_se,a);end if;
 end if;end im_to_tree;
 \end{lstlisting}

One has to browse all the tree and save the sequence into a file. That is done with save_imagec and tree_to_imc.

function is_homogeneous

We explain here how is_homogeneous function deals with 3 possibles cases : tolerance is minimal (0), maximal (100), or between these two values. If it is maximal, then we return a boolean set to true and a leaf is created with the average value of the image (see procedure im_to_tree). If it is minimal, we check that all pixels have the same value. Finally, for the middle case, we test the inequality abs(primary_color-average) <= tolerance on each pixel.

\begin{lstlisting}[language=ada]
 -----------------------------------------------...
 ...i+1;
 end loop;
 return result;
 end case;end is_homogeneous;
 \end{lstlisting}

procedure save_imagec

\begin{lstlisting}[language=ada]
 -----------------------------------------------...
 ...me);
 write(f,n);
 tree_to_imc(a,f);
 close(f);end save_imagec;
 \end{lstlisting}

We call the recursive procedure tree_to_imc which browses all the tree.

procedure tree_to_imc

\begin{lstlisting}[language=ada]
 -----------------------------------------------...
 ...f);
 tree_to_imc(Qt_Brother(a,1),f);
 end if;end tree_to_imc;
 \end{lstlisting}

Algorithmic refining for decompression

Firstly, we must build a tree from encoded sequence (procedure load_im_encod and imc_to__tree) and then rebuild image from this tree (procedure tree_to_im).

procedure load_im_encod

\begin{lstlisting}[language=ada]
 -----------------------------------------------...
 ...,dim);
n:=dim;
a:=imc_to_tree(f);
close(f);end load_im_encod;
\end{lstlisting}

Here we use auxiliary function imc_to_tree.

function imc_to_tree

This function allows to build a tree from encoded sequence of a compressed image.

\begin{lstlisting}[language=ada]
-----------------------------------------------...
...-1,a_nw,a_ne,a_sw,a_se,a);
end if;
return a;end imc_to_tree;
\end{lstlisting}

procedure tree_to_im

Image can be rebuilt from tree. Tree is tree_im and output image is im. We use i_b, i_f, j_b, j_f to get the shift between recursive calls.

\begin{lstlisting}[language=ada]
-----------------------------------------------...
..._f,j_f-(j_f-j_b+1)/2+1,j_f);
end if;
end if;end tree_to_im;
\end{lstlisting}

procedure thresh_im

For an example of operation, we choose to do a binary threshold.

\begin{lstlisting}[language=ada]
-----------------------------------------------...
...1;
end if;
end loop;
end loop;end thresh_im;end pimage;
\end{lstlisting}

Validation of packages

n-ary and quaternary packages

Test program main_tree_nary.adb and main_tree_quater.adb use respectively tree_nary.adb and tree_quater.adb package. It is possible to make a tree for checking the good operating of all main above procedures and functions.

pimage package

Tets program main_pimage.adb allows to create an image and validate compression and decompression. An example of image is displayed as :


Figure 1 : Content of test image 8x8

Its size equals to 260 bytes (64*4+4) because we save also the dimension. We take into account a tolerance to see if image is homogeneous. The tree built with a minimal tolerance (0) is represented on the following figure :


Figure 2 : Content of tree for compression with minimal tolerance

Image compressed size equals to 104 bytes (25*4+4) with 4 bytes for dimension, which was expected. With a maximal tolerance (100), we get a leaf with the average color of image (161) because this one is considered as homogeneous from criterion into is_homogeneous function.


with a tolerance equal to 80, we get this tree :


Figure 3 : Content of tree for compression with a tolerance equal to 80

We can notice that there will be a loss of information regards to test image with compression. Indeed, the north-west part of image is seen as homogeneous with this tolerance. This is illustrated on this figure :


Figure 4 : Content of decompressed image 8x8 with a tolerance equal to 80

For each case, we save compressed image and check decompression.

Conclusion

This project has enabled us to create a package to make compression and decompression of images. The operations implemented for quaternary trees were reused and validated for encoding algorithm.


Archive of this project :pimage.tar

À propos de ce document...

This document was generated using the LaTeX2HTML translator Version 2008 (1.71)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

ps : join like me the Cosmology@Home project whose aim is to refine the model that best describes our Universe

    Home | Astronomy | Sciences | Philosophy | Coding | Cv    
- dournac.org © 2003 by fab -

Back to Top