Dynamic allocation and memory
We want to make an application that processes images. The program must be able to read an image of any size in TGA format, eliminate the empty parts, and display the image and its size. Description of structures: For simplicity, we only support a certain specific type of TGA in shades of gray. The image is represented by a series of width × height bytes giving the intensity of the pixels (word coming from "picture element", which are the small dots composing an image), line by line, starting from the lower left corner. For example, for a width = 4 and a height = 3, the intensity sequence 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 represents an image of 4 by 3 having the following intensities: An intensity of 0 means black, and a maximum intensity (ie 255, on 8 bits) means white. The function allowing to read the TGA format is already partially written (see comments // TODO in the code). If you're interested, format details are at Wikipedia http://en.wikipedia.org/wiki/Truevision_TGA#Header. The complete image will be represented with the following structure, containing the width and height in pixels of the image, as well as a pointer to an array of lines: struct Image { int largeur, hauteur; LigneImage * lignes; }; In memory, in the Image structure, the lines will be in order from top to bottom, to correspond to the order in which the characters are displayed on the console, contrary to the order in the file. Reading the file therefore iterates from the end of the row array (the loop header is already written). http://en.wikipedia.org/wiki/Truevision_TGA%23Header. To avoid unnecessarily keeping the empty parts of the image (we consider the intensity 0 as a n empty part), we will use a structure allowing to specify the beginning and the length of the lines of the image. We will have the following structure for each line of the image: struct LigneImage { int debut, longueur; uint8_t * intensites; }; For example, the following 4 × 4 image: Will be loaded to an Image structure like this (the values in the diagram are in the same order as in the definition of the structures above): Then the vacuum will then be cut like this: The pointer in the Image structure (to the left of the figure) indicates where an array of LigneImage is located (in the center of the figure), where each element indicates a beginning (the horizontal position where the first non-empty value is, in the first line), a length (the number of values necessary to have all the non-empty values of the line), as well as a pointer to an array having length bytes to specify the intensities (to the right of the figure). For a completely empty line, the length is zero, and a nullptr pointer indicates that no memory is allocated for this line. (Note that the positioning of the boxes on the right does not represent a specific positioning in memory, but only so that we can see clearly on the diagram the correspondence between the representation and the original image.) Work to be done: The main program must: - Load an image. - Cut the empty spaces. Ensures that none of the intensity tables start or end with blank pixels, adjusting the length and position of the lines. - Display the size of the image. Displays the sum of the sizes of the intensity tables, to find out how much memory has been allocated for these tables. - Display the image. - Exit the program without any memory leaks. To do this, you must write the following functions (the headers of certain functions are already given, but not all): void desallouerImage (Image & image) must free all dynamically allocated memory for the image (i.e. the row array and all intensity arrays) and set the row pointer to nullptr to know that the image has no memory allocated. bool chargerImage (Image & image, string nomImage) must start by freeing the memory of the old image, if there was one, then allocate the memory needed to load the new image. For each line of the image, this function must allocate the intensity table for this line and load the line at full without checking for empty pixels. The lines will therefore all have a position of 0, and the same length than the width of the image. This function is already partially written. void decouperVide (Image & image) must make sure that there are no empty pixels at the beginning or at the end of a line. For each line, the empty pixels at the beginning and at the end are counted. The new position will be the old one increased by the number of empty pixels at the beginning of the line, and the new length will be the old one reduced by the number of empty pixels at the start and end of the line. If there is at least one empty pixel, you must allocate a smaller array, of new length, and copy the pixels to keep there (skipping the empty pixels of the beginning). You must then deallocate the old table and replace the pointer with that of the new table. tailleImage must calculate and return the sum of the lengths of the lines of the image, i.e. the sum length fields, for each element of the row array. afficherImage must display the image for it to be properly visible. Each pixel will be a character to the screen, the displayGray function allows you to display a "gray" character of a certain intensity. Each line should be displayed in order, leaving blank lines if the image contains blank lines, and leaving the lots of empty characters (spaces) at the start of each line depending on the start field. As constraint, your inner loop must not contain triple dereference (each *, -> or [ ] is a dereference, and access to a reference too). Main must take care of loading, cutting and displaying the image, as said before. You can add other sub-functions, if it is to improve the readability of the code. The solutionaire contains some additional functions. Each function should be tested and debugged. To test the general functionality of your program, display the image before and after cutting, and it should look exactly the same. For rond.tga (see files below), the size should be 800 before cutting and 172 after. As stated in the separate directives, your program should not generate any warning when compilation. Your program should also not have memory leaks (i.e. elements allocated which are never deallocated); an automatic report will be produced by the debugging tool after execution to let you know if there are any leaks. Files provided: td5.cpp The program to complete. td5.sln,… .vcxproj * The Visual Studio project. debogageMemoire.h To get the report of memory leaks. cppitertools, gsl The libraries used. example4x4.tga The image corresponding to the example above, with intensities of 128 and 255 at instead of 1 and 2. rond.tga A circle on a black background, with gradual outline and a white pixel. turing.tga A photograph of Alan Turing. APPENDIX: Use of programming and debugging tools. Use of Unicode: To display accented characters, you must use the "wide" versions of cout, string, and char, which are respectively wcout, wstring, and wchar_t. Strings and characters "wide" are written with an L capital letter in front, such as L "Allô" and L'ô '. Regular strings and characters can also be displayed on wcout but must not contain accented characters. A sample display is in the hand. Report on memory leaks and corruption around allocated blocks: The program includes debug versions of "new" and "delete", which allow to detect if a block has never been deallocated, and display at the end of the execution the line of the program which made the allocation. 4/4 Memory allocation is also configured to check for corruption on each allocation, allowing to intercept out-of-bounds writes from an allocated array. If corruption is detected, the debugger will display a message indicating a possible "heap failure", and the "Call Stack" window will prompt you will see where the detection was made (look at the bottom of the call stack for the item the top which corresponds to your program, and not those above which correspond to the functions of C ++). If you have a corruption problem, you can use "_CrtCheckMemory ()" anywhere which line to check if corruption occurs before or after this line (the function returns false if there is corruption). Using the to-do list: The code contains "TODO" comments that Visual Studio recognizes. You must first activate the option, in the Tools> Options ... menu, go to Text editor> C / C ++> Formatting> Miscellaneous> List comment tasks, to set this option to "True", then OK. To display the list, go to the View menu, submenu Other windows, click on Task list. Choose then in this window to use the comments. You can double-click on the “TODO” to go to where it is in the code. You can add your own TODOs in the