Starting from:

$30

SE334-Module 3 Image Processing Solved

: In this homework, you will be implementing a program that loads an image le, applies a simple lter to it, and saves it back to disk. You will also learn how to read and write real-world binary le formats, speci cally BMP and PPM.

1         Background
In this assignment you will write a program that applies a        lter to an image. The image will be loaded from a local BMP or PPM           le, speci ed by the user, and then be transformed using a color shift also speci ed by the user. The resulting           le will be saved back to a BMP or PPM      le that can be viewed on the host system.

This document is separated into four sections: Background, Requirements, Loading Binary Files, Include Files, and Submission. You have almost nished reading the Background section already. In Requirements, we will discuss what is expected of you in this homework. In Loading Binary Files, we will discuss the BMP and PPM le formats and how to interact with binary les. Lastly, Submission discusses how your source code should be submitted on Canvas.

2         Requirements
Your program needs to implement loading a binary BMP or PPM le, applying a color shift to its pixel data, and saving the modi ed image back into a BMP or PPM le. The width and height may be of any size, but you can assume that you will be capable of storing the image data in memory. Assume that all BMP les are 24-bit uncompressed les[1] (i.e., compression method is BI_RGB), which have a 14-bit bmp header, a 40-bit dib header, and a variable length pixel array. This is shown in Figure 2. PPM les will also be in 24-bit. For testing, please only use the PPM and BMP les attached to the assignment.

As a base requirement, your program must compile and run under Xubuntu (or another variant of Ubuntu) 18.04. Sample output for this program is shown in Figure 1.

• Speci c Requirements:

BMP Headers IO: Create structures for the headers of a BMP le (BMP header struct and DIB header struct) and functions which read and write them.

PPM Headers IO: Create structures for the headers of a PPM le (PPM header struct) and functions which read and write them.

Pixel IO: Create a structure which represents a single pixel (24-bit pixel struct) and the functions for reading and writing all pixels in both PPM and BMP les.

Input and output le names: Read the input le name and output le name from the command line arguments. The user should be required to enter the input le name and this should be the rst argument. The output le name is an option, it is not required and it can be in any place in the option list. The output le option is speci ed by -o followed by the output le name. Validate that the input le exists and that both les are of the correct type (either bmp or ppm).

 

                         ∗ The input      le is the     le to read and copy.

                         ∗ The output      le name is the       le to write to and copy to (the new       le created).

RGB Color Shift input: Accept options for red, green, or blue color shift. These are speci ed by -r -g or -b followed by an integer. Validate that these are integers. Like the -o option described above, these can come in any order in the option list and are optional for the user to enter.

∗ Note: -o -r -g and -b are all options. All for of these can come in any order (-r -g -n -b, for example) and none of them are required.

Copy images: Correctly copy images from a BMP   le to a new BMP  le and from a PPM     le to a new PPM  le.

Convert images: Correctly copy images from a BMP             le to a new PPM  le and from a PPM             le to a new BMP  le.

Color Shift calculation: Shift the color of the new image before saving it, according to the options the user entered.

∗ Color shift refers to increasing or decreasing the color in a pixel by the speci ed amount. So, if the user entered -b -98 all of the blue values in a pixel would be decreased by 98.

∗ If no color shift option was entered for a color, do not shift it.

∗ After color shift, color should be clamped to 0 ~ 255. For example, color R = 100, shift = 200. The color R after shift should be 255 (300 clamped to 255).

Modular Programming: Use the provided header les correctly and create corresponding C les, along with a main le. You do not have to create any more header les or C les than this but you may if it helps you. Do not modify the header les given except to ll in any TODOs.

Figure 1 shows an example of how the          nished program should function.

 

Figure 1: Example of running the program with example output.

3         Loading Binary Files
3.1         The BMP File Format
For reference, use the BMP speci cation on Wikipedia: https://en.wikipedia.org/wiki/BMP_ le_format. In Figure 2, a graphical overview of a BMP le’s layout is shown. The layout is literally the meaning of the bits/bytes in the le starting at 0 and going to the end of the le. The rst (green) region shows the BMP header information in 14 bytes: 2 for the signature, 4 for the le size, 2 for reserved1, 2 for reserved2, and 4 for le o set. Details on each of these (such as their data format, and contents) can be found on the Wikipedia page. For example, the area labeled Signature should contain the characters BM to con rm that the le is in BMP format. The second (blue region) shows the DIP header information in 40 bytes: 4 for header size, 4 for width, 4 for height, and so on. The last region (yellow) forms a 2D array of pixels. It stores columns from left to right, but rows are inverted to be bottom to top. Note that each row of pixels in this section is padded to be a multiple of four bytes. For example, if a line contains two pixels (24-bits or 3-bytes each), then an addition 2-bytes of blank data will be appended.

 

Figure 2: BMP le format structure for 24-bit les without compression. Image modi ed from https://en.wikipedia.org/wiki/File:BMP leFormat.png.

Review the following struct called BMP_Header which holds the bmp header information. (You should also consider creating structs to hold the dib header, and pixel data.) Notice that the entries in BMP_Header correspond to the pieces of data listed in the le format. In general, a chunk of 8-bits should be represented as a char, a chunk of 16-bits as a short, and 32-bits as a int. (Optionally: consider using unsigned types.)

struct BMP_Header {
 
                     char       signature [ 2 ] ;
//ID      f i e l d
                     int      size ;
// Size       of         the BMP f i l e
                     short       reserved1 ;
// Application           s p e c i f i c
                     short       reserved2 ;
// Application           s p e c i f i c
                      int           offset_pixel_array ;               // Offset      where    the      pixel       array       can be found

};

Plan to review Example 1 on the Wikipedia page to get a feel for the contents of each of these regions. A recreated version of that image is provided as the attached test2.bmp le. A good exercise would be to view the le in a hex editor like HxD.

3.2         The PPM File Format
The PPM le format is a much simpler format. For reference, please visit the o cial speci cation here: http://netpbm.sourceforge.net/doc/ppm.html. The header of a PPM le consists of the signature P6 , follow by white space, the width of the le (in ASCII characters, not binary), white space, and the height of the image (in ASCII characters, not binary). After the header, there is a single white space character followed by the pixel array. The pixels are 3 bytes each, with each color being represented by a single byte. The columns are stored left to right and the rows top to bottom. Do not use the Plain PPM format that is described in the spec, use the regular one. From top to bottom, each PPM image text le consists of the following:

1.   A "magic number" for identifying the le type. A ppm image’s magic number is the two characters "P6". Whitespace (blanks, TABs, CRs, LFs).

2.   A width, formatted as ASCII characters in decimal. Whitespace.

3.   A height, again in ASCII decimal. Whitespace.

4.   The maximum color value (maxval), again in ASCII decimal. Must be less than 65536 and more than zero. A single whitespace character (usually a newline).

5.   A raster of height rows, in order from top to bottom. Each row consists of width pixels, in order from left to right. Each pixel is a triplet of red, green, and blue samples, in that order. Each sample is represented in pure binary by either 1 or 2 bytes. If the maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes. The most signi cant byte is rst.

Plan to review examples of PPM on PPM Wikipedia page (https://en.wikipedia.org/wiki/Netpbm_format#PPM_example)

to get a feel for the contents of each of these regions. Some PPM header examples are available on http://paulbourke.net/dataformats/ppm/. You should include all necessary information of the header in the PPM struct.

3.3         Loading the BMP header
This is example of code to load the BMP            le header (the    rst 14 bits). Figure 3 shows the output.

 

                                                            Figure 3: Output of base       le on test2.bmp.

                      //sample      code    to     read     f i r s t    14    bytes       of BMP f i l e       format

FILE∗ f i l e = fopen (" test2 .bmp" , "rb "); struct BMP_Header header ;

//read bitmap f i l e header (14 bytes ) fread(&header . signature , sizeof ( char )∗2 , 1 , f i l e ); fread(&header . size , sizeof ( int ) , 1 , f i l e ); fread(&header . reserved1 , sizeof ( short ) , 1 , f i l e ); fread(&header . reserved2 , sizeof ( short ) , 1 , f i l e ); fread(&header . offset_pixel_array , sizeof ( int ) , 1 , f i l e );

printf (" signature : %c%c\n" , header . signature [0] , header . signature [ 1 ] ) ; printf (" size : %d\n" , header . size ); printf (" reserved1 : %d\n" , header . reserved1 ); printf (" reserved2 : %d\n" , header . reserved2 );

printf (" offset_pixel_array : %d\n" , header . offset_pixel_array ); fclose ( f i l e ); The key functions here are:

•    FILE ∗fopen ( const  char ∗filename ,   const      char ∗mode)

This creates a new le stream. fopen is used with the rb mode to indicate we are r eading a le in b inary mode. To read a le, use the mode wb instead of rb .

•    size_t         fread ( void ∗ptr , size_t     size ,       size_t     nitems , FILE ∗stream )

For each call to fread, we give it rst a pointer to an element of struct containing the BMP header, then the number of bytes to read, the number of times to read (typically 1), and the le stream to use. Note that order of the calls to fread de ne the order in which we read data so the order must match the le layout. (There is also a function called fwrite which works in exactly the opposite manner. The rst won’t be a pointer though.)

One function not used here but which may be useful, is fseek:

•    int              fseek      ( FILE ∗ stream ,   long        int          offset ,   int          origin    )

The purpose of fseek is to move the reading head of the FILE object by some number of bytes. It can used to skip a number of bytes. The rst parameter to fseek is the le pointer, followed by a number of bytes to move, and an origin. For origin, SEEK_CUR is a relative repositioning while SEEK_SET is global repositioning.

The basic idea to support loading a BMP le will be to parse it by byte-byte (using fread) into a set of structs. Later, you can use fwrite to write out the contents of those structs to a le stream to save the ltered image.

3.4         Creating le headers
When copying from BMP to BMP or PPM to PPM, you could easily copy the original               le’s header into the new one. But when copying from BMP to PPM, or PPM to BMP, you will need to        ll in the header of the new le yourself. For example, you will need to  ll in the compression type, the number of color planes, etc for BMP      les. The following de nes default values you should use when creating an image. All values that are not de ned here, you should calculate based on the input image.

•    BMP Header:

                    Signature:    BM

Reserved 1: 0

Reserved 2: 0

•    DIB Header:

Planes: 1

Compression: 0

Horizontal resolution: 3780

Vertical resolution: 3780

Color number: 0 Important color number: 0

•    PPM Header:

                     Magic Number:    P6

                     Maximum color value:    255

4         Include Files
To complete this assignment, you may          nd the following include      les and functions useful:

•    stdio.h: De nes standard IO functions.

•    stdlib.h: De nes memory allocation functions.

•    string.h: De nes string manipulation functions.

char* strcat(char* dest, const char* src): The strcat() function appends the string pointed to by src to the end of the string pointed to by dest.

char* strcpy(char* dest, const char* src): The strcpy() function copies the string pointed to, by src to dest.

size_t strlen(const char* str): The strlen() function computes the length of the string str up to, but not including the terminating null character.

char* strtok_r(char* str, const char* delim, char** saveptr): The strtok_r function parses a string into a sequence of tokens.

•    unistd.h: De nes POSIX operating system API functions.

int getopt(int argc, char *const argv[], const char *optstring): The getopt() function is a builtin function in C and is used to parse command line arguments.

Your solution may not include all of these include les or functions, they are only suggestions. If you want to include any other les, please check with the instructor or TA before doing so. Note: Since PPM les are in ASCII (not binary), you should write and read them di erently. fprint and fscanf would be a good choice to write and read PPM les.


 
[1] 1In case you think this is making the assignment unrealistic, think again: this is the default Windows 10 BMP                le format.

More products