Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

C++: In this assignment you will be writing code to read and write from bitmap files. Bitmap files are a common format, and use a

C++: In this assignment you will be writing code to read and write from bitmap files. Bitmap files are a common format, and use a relatively simple file format.

Starter Code:

The following zip file includes the following:

  • main.cpp - Testing code to help validate that you are loading and saving images properly. This doesn't need to be modified unless you are doing the extra credit.
  • BitMap.h - Header file with structure declaration and function prototypes.
  • BitMap.cpp - Your code goes in this file. You need to fill in the function definitions according to the comments provided in the functions and in the header file.

Representation:

Bitmap images are a common uncompressed format, and are stored in a relatively simple format that is widely documented. In this assignment you will write code to read and write from bitmap files. While there are many options required for full bitmap support, you will only be required to support a subset of those options. In particular, your code should be able to read uncompressed 24-bit and 32-bit bitmap files.

Structs and Functions Provided in Collection:

The following structs and functions are provided for you to help you complete the function that generates the maze:

  • struct BitMapHeader contains a majority of the header information that you will read/write from a bitmap file. This header is only used when reading or writing to a bitmap file.
  • struct BitMap: this struct holds the raw data for an image. Each set of four bytes in the array should store blue, green, red, and alpha bytes respectively. The first four bytes store the color data for (0, 0) [bottom left corner] in the image, and the last four bytes should store the color data for the upper right corner of the image.

Structs and Functions to Implement:

The following functions should be implemented by the student.

  • BitMap *CreateBitMapPic(int width, int height);
  • void Free(BitMapPointer &bm);
  • BitMap *Load(const char *file);
  • void Save(BitMap *bm, const char *file);
  • void GetPixel(BitMap *bm, int x, int y, uint8_t &redByte, uint8_t &greenByte, uint8_t &blueByte, uint8_t &alphaByte);
  • void SetPixel(BitMap *bm, int x, int y, uint8_t redByte, uint8_t greenByte, uint8_t blueByte, uint8_t alphaByte );

Bitmap Files

A bitmap file consists of two parts: header and image data. The header stores information about the file including dimension, color depth..etc. You can find the complete list in the link provided in overview. The first two bytes of the header determine if the file is a bitmap or not. The two bytes will have the ascii values of BM or (0x424D). The rest of the header is stored in the struct provided for you. The value bfoffBits determines the offset from the start of the file you will need to advance before you reach the image data. Image data for each pixel contains the value for blue, green, red as well as alpha if the file is 32 bit color or no alpha if it's 24 bit color. When the height of the bitmap in the header is negative then the image data starts at pixel (0, 0) so the upper left corner is pixel (0, 0) while a positive bitmap height means pixel (0, 0) is the lower left corner of the image.

Starter code:

#include "BitMap.h"

#include

#include

BitMap *CreateBitMapPic(int width, int height)

{

}

void Free(BitMapPointer &bm)

{

}

void SetPixel(BitMap *bm, int x, int y, uint8_t redByte, uint8_t greenByte, uint8_t blueByte, uint8_t alphaByte)

{

}

void GetPixel(BitMap *bm, int x, int y, uint8_t &redByte, uint8_t &greenByte, uint8_t &blueByte, uint8_t &alphaByte)

{

}

void Save(BitMap *bm, const char *file)

{

// 1. Open the file

// 2. Create a header and write it to the file

// 3. Write the bitmap data to the file

// 4. Close the file

}

BitMap *Load(const char *file)

{

// 0. If any of the operations fail, free any memory and return 0

// 1. Open the file

// 2a. Read the initial fields of the header; verify that the file type (BM) is correct.

// 2b. Read the rest of the header.

// 3. Verify if the file is 24 or 32 bits.

// 4. Check if the rows are stored in reverse order (due to negative height)

// 5. Make sure the file isn't compressed (compression should be 0)

// 6. Load the file if it is 32 bits

// 6a. If the file is 32 bits, you can read one row at a time.

// 6b. If the height is negative, you need to read from disk into the rows in memory in reverse order

// 6c. 32-bit files are never padded.

// 7. Load the file if it is 24 bits

// 7a. If the file is 24 bits, you need to read 3 bytes at a time and make space in memory for

// the extra byte. (Since your internal storage should always be 32 bits.)

// 7b. If the height is negative, you need to read from disk into the rows in memory in reverse order

// 7c. If the length of each line isn't divisible by 4, you need to read extra padding from the file.

// This padding shouldn't be stored in the bitmap data in memory.

// 8. Close the file.

// 9. Return a pointer to the bitmap.

}

#ifndef BITMAPPIC_H

#define BITMAPPIC_H

#include

#include

#include

struct BitMapHeader {

BitMapHeader()

:zero(0), bfOffBits(sizeof(BitMapHeader)+2), biSize(40), biPlanes(1),

biBitCount(32), biCompression(0), biSizeImage(0), biXPelsPerMeter(2835), biYPelsPerMeter(2835),

biClrUsed(0), biClrImportant(0) {}

uint32_t bfSize;

uint32_t zero;

uint32_t bfOffBits;

uint32_t biSize;

uint32_t biWidth;

uint32_t biHeight;

uint16_t biPlanes;

uint16_t biBitCount;

uint32_t biCompression;

uint32_t biSizeImage;

uint32_t biXPelsPerMeter;

uint32_t biYPelsPerMeter;

uint32_t biClrUsed;

uint32_t biClrImportant;

};

struct BitMap {

uint32_t width, height;

uint8_t *image;

};

typedef BitMap* BitMapPointer;

/* CreateBitMapPic

* Create a new Bit Map of the desired height and width. Both the height and

* width should be positive.

*/

BitMap *CreateBitMapPic(int width, int height);

/* Free

* Free the memory associated with a bit map and set the pointer to 0.

*/

void Free(BitMapPointer &bm);

/* Load

* Load a bitmap from the specified file.

* Code should support 24- and 32-bit bitmaps. Internally, the code should use

* 32-bit bitmaps.

* If the height is negative, the file has the rows reversed; they should be reversed

* upon loading, so that all bitmaps will be stored in the same way.

* Returns 0 if the loading failed.

*/

BitMap *Load(const char *file);

/* Save

* Write a bitmap to the specified file.

* Code should write 32-bit bitmaps with positive height.

*/

void Save(BitMap *bm, const char *file);

/* GetPixel

* Load the RGB values from a given pixel. (0, 0) is the bottom left of the image.

*/

void GetPixel(BitMap *bm, int x, int y, uint8_t &redByte, uint8_t &greenByte, uint8_t &blueByte, uint8_t &alphaByte);

/* SetPixel

* Write the RGB values to a given pixel. (0, 0) is the bottom left of the image.

*/

void SetPixel(BitMap *bm, int x, int y, uint8_t redByte, uint8_t greenByte, uint8_t blueByte, uint8_t alphaByte );

#endif

#include

#include "BitMap.h"

int main(int argc, const char * argv[])

{

/* This code tests your bitmap implementation on 24-bit and 32-bit files. The desired output

* files are included for comparison purposes.

*/

/** Test #1: Create a new file with a gradient from yellow to green to cyan (bottom to top) */

BitMap *bm = CreateBitMapPic(255, 255);

for (int x = 0; x < 255; x++)

{

for (int y = 0; y < 255; y++)

{

SetPixel(bm, x, y, 255-y, 255, y, 255);

}

}

std::cout << "Processing test.bmp ";

Save(bm, "test.bmp");

Free(bm);

/** Test #2: A 24-bit file with reversed height; add a 40x40 red square in the lower right corner */

std::cout << "Processing picture.bmp ";

bm = Load("picture.bmp");

if (bm == 0)

{

std::cout << "Load of 'picture.bmp' failed ";

}

else {

for (int x = 0; x < 40; x++)

{

for (int y = 0; y < 40; y++)

{

SetPixel(bm, bm->width-x-1, y, 255, 0, 0, 255);

}

}

Save(bm, "picture new.bmp");

free(bm);

}

/** Test #3: A 24-bit file; add a 40x40 blue square in the upper right corner */

std::cout << "Processing train.bmp ";

bm = Load("train.bmp");

if (bm == 0)

{

std::cout << "Load of 'train.bmp' failed ";

}

else {

for (int x = 0; x < 40; x++)

{

for (int y = 0; y < 40; y++)

{

SetPixel(bm, bm->width-x-1, bm->height-y-1, 0, 0, 255, 255);

}

}

Save(bm, "train new.bmp");

free(bm);

}

/** Test #4: A 24-bit file with padding; add a 40x40 blue square in the upper right corner */

std::cout << "Processing mountain.bmp ";

bm = Load("mountain.bmp");

if (bm == 0)

{

std::cout << "Load of 'mountain.bmp' failed ";

}

else {

// Convert to grayscale

for (int x = 0; x < bm->width; x++)

{

for (int y = 0; y < bm->height; y++)

{

uint8_t r, g, b, a;

GetPixel(bm, x, y, r, g, b, a);

uint8_t average = (r+g+b)/3;

SetPixel(bm, x, y, average, average, average, a);

}

}

Save(bm, "mountain new.bmp");

free(bm);

}

/** Test #4: A 32-bit file with reversed height; extract the green channel */

std::cout << "Processing canmore.bmp ";

bm = Load("canmore.bmp");

if (bm == 0)

{

std::cout << "Load of 'canmore.bmp' failed ";

}

else {

for (int x = 0; x < bm->width; x++)

{

for (int y = 0; y < bm->height; y++)

{

uint8_t r, g, b, a;

GetPixel(bm, x, y, r, g, b, a);

SetPixel(bm, x, y, 0, g, 0, a);

}

}

Save(bm, "canmore new.bmp");

free(bm);

}

return 0;

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions