Additional information about this format and some examples can be found at:
http://paulbourke.net/dataformats/ppm/.
The compressed file will contain the results of the compression process:
- image_size - unsigned int type - which specifies the size of the image (remember that we have square images);
- For each node in the breadth first traversal applied to the compression tree we will write in the file the following informations:
- If the node is an internal node:
- node__type - unsigned char type – which will have the value 0 in this case.
- If the node is a leaf node:
- node__type - unsigned char type – which will have the value 1 in this case;
- value__of__red - unsigned char type – which will indicate the value the component responsible for the Red color for the pixels in the area described by that node;
- value__of__green - unsigned char type – which will indicate the value the component responsible for the Green color for the pixels in the area described by that node;
- value__of__blue - unsigned char type – which will indicate the value of the component responsible for the Blue color for the pixels in the area described by that node.
The decompressed file is a standard file in .PPM format and contains the information extracted from the file, the compressed file given for decompression.
After the mean color has been determined, a similarity score is computed for the current block, using the following formula:
where red, green, blue represent the components for the average color. If the obtained value for the score is less than or equal to the imposed factor, then there will be no need for division. After we have built the compression tree, we want to determine the following informations:
- the number of levels in the quadtree;
- the number of blocks in the image for which the pixel similarity score is higher less than or equal to the supplied factor;
- the size of the side of the square for the largest area in the image that remained undivided.
This information will be written in the file, each text on one line. The file name is supplied as an argument in the command line.
quadtree.out:
4
16
16
For the tree above, these are the values we will write into the binary file for each level:
In this representation, I specified the level index at the beginning and then the values. To make it easier to follow, we have delimited by { and } the 4 values for the leaf nodes (node__type, red, green, blue).
Starting from the next picture, we will see how the given factor affects the quadtree and, by default, the compression operation.
1. If the given factor is 0, then the compression tree will be this:
For this quadtree, the image after decompression will look like this:
Figure 2: Image with factor 0
2. If the given factor is higher, then the compression tree might look like
this. Each leaf node will account for the average color of the block.
For this quadtree, the image would look like this:
Figure 3: Image with a bigger factor
- ~the format of the binary file;
- ~two values representing the width and height (size) of the image;
- ~the maximum value that a color can take;
- ~the end of the line;
- to then read size x size x 3 unsigned char values, representing in order, red, green, blue, and add them to a RGB pixel type matrix.
(node1: start_x -> same as before, start_y -> same as before, end_x -> mean of start_x + end_x, end_y -> mean of start_y + end_y)
(node2: start_x -> same as before, start_y -> mean of start_y + end_y, end_x -> mean of start_x + end_x, end_y -> same as before)
(node3: start_x -> start_x + (end_x - start_x) / 2, start_y -> start_y + (end_y - start_y) / 2, end_x -> same as before, end_y -> same as before)
(node4: start_x -> start_x + (end_x - start_x) / 2, start_y -> same as before, end_x -> same as before, end_y -> start_y + (end_y - start_y) / 2)
If the score is lower, then it means that the node is a leaf (external) and the RGB (red, green, blue) values found earlier are added to it by the formulas provided. Finally, that cell is returned. I had to display the number of levels (a simple recursive function), the number of blocks in the image for which the similarity score of the pixels is less than or equal to the provided factor, the number of leaves (a recursive function that checks if the children are NULL and adds to the sum) and the side size of the square for the largest area in the image that remained unsplit, the size halved by n times (n := the level on which the nearest leaf is of root). Finally, I have freed memory for all allocated structures and the pixel array and closed the files.
- ~the format of the binary file;
- ~two values representing the width and height (size) of the image;
- ~the maximum value that a color can take;
- ~the end of the line.
make
in your terminal to compile all of the .c files.
(you can view make rules in the Makefile)
Your program will receive as arguments in the command line, the filename of the input file and output file, and an option, in the following way:
./quadtree [-c1 factor | -c2 factor | -d] [input__file__name] [output__file__name]
- -c1 factor for solving option 1 (factor = threshold for the compression);
- -c2 factor for solving option 2 (factor = threshold for the compression);
- -d for option 3;
- input__file__name represents the name of the input file (the one that contains the image);
- output__file__name represents the name of the output file, in which it will be written, according to the command received, the result of the program.
If you want to try this program, you can use images from tests/ folder. Just type:
make
// for option 1
./quadtree -c1 [factor] tests/input/test"$1".ppm tests/output/test.out
// compare result with tests/ref/test"$i"_c1.txt
make
// for option 2
./quadtree -c2 [factor] tests/input/test"$i".ppm tests/output/test.out
// compare result with tests/ref/test"$i"_c2.out
make
// for option 2
./quadtree -d tests/input/test"$i"_c2.out tests/output/test.ppm
// compare result with tests/ref/test"$i"_c3.ppm
where you can replace "$i" with the number of the image you are testing.