Table of Contents
cs19s23as08: Bitmap Image Modification
Goals
- Practice working with explicitly binary data in C++.
- Learn a bit about one of the simplest image file formats.
Prerequisites
This assignment requires familiarity with the lecture materials presented in class through week 08.
Background: The BMP File Format
The BMP file format is among the simplest image representation formats; possibly the simplest. There are various versions of the format, and the format is able to support several kinds of color values and compression. But the simplest and most common bitmap files are not compressed.
For our purposes, assume that a BMP file consists of 24-bit RGB pixels and is composed of the following “structures” (i.e., segments of data) in the following order:
Structure name | Size | Contents |
---|---|---|
BMP file header | 14 bytes | General information about the file |
DIB header | Varies | Information about the image, e.g. width and height |
Pixel array | Based on image dimensions and pixel type | Component values for each pixel |
The Wikipedia article linked above has a lot more information on the format. However, here is a thorough description of what you need to know about each structure for this assignment:
BMP File Header
This structure consists of 14 bytes, as follows:
File offset | Size (bytes) | Purpose |
---|---|---|
0x00 | 2 | The bytes 0x42 and 0x4d (characters 'B ' and 'M ') identify this file as a bitmap image |
0x02 | 4 | The size of the BMP file in bytes (should match the actual file size) |
0x06 | 2 | Reserved; actual value depends on the application that creates the image |
0x08 | 2 | Reserved; actual value depends on the application that creates the image |
0x0a | 4 | The offset, i.e. starting address, of the byte where the bitmap image data (pixel array) can be found. |
DIB Header
This structure immediately follows the BMP header and consists of a variable number of bytes, as follows:
File Offset | Size (bytes) | Description |
---|---|---|
0x0e | 4 | The size of this header. |
0x12 | 4 | The bitmap width in pixels (signed 32-bit integer) |
0x16 | 4 | The bitmap height in pixels (signed 32-bit integer) |
0x1a | 2 | The number of color planes (must be 1) |
0x1c | 2 | The number of bits per pixel. In our case, this should be 24. |
0x1e | 4 | The compression method being used. In our case, this should be 0. |
0x22 | 4 | The image size. This is the size of the raw bitmap data (pixel array). |
0x26 | 4 | The horizontal resolution of the image (pixels per meter), as a signed 32-bit integer. |
0x2a | 4 | The vertical resolution of the image (pixels per meter), as a signed 32-bit integer. |
0x2e | 4 | The number of colors in the color palette. In our case, this should be 0. |
0x32 | 4 | The number of important colors used, or 0 when every color is important. In our case, this should be 0. |
Pixel Array
This structure contains component values for every pixel in the image.
- The pixel array begins at the file offset specified in the BMP file header.
- Each pixel value is composed of 3 bytes, which represent a 24-bit RGB color, i.e. 3 8-bit unsigned integers.
- Pixel values are presented row-by-row starting with the bottom row1), i.e. the entire bottom row of pixels, then the row second from the bottom, etc.
- Each row is padded to a multiple of 4 bytes in size, if necessary.
Example
A very small (2×2-pixel) BMP file is available at /srv/datasets/simple.bmp
, or via HTTP. (This is the same image described in Example 1 of Wikipedia's article.)
Here it is, surrounded by a 10-pixel padded bordering box (you probably can't see the image very easily!):
And here is how it would look if it were resized to 200×200 pixels:
On the command line, we could inspect the contents of this file as 1-byte hexadecimal values using the hexdump
utility:
hexdump -C /srv/datasets/simple.bmp
hexdump
gives the following output, in which each line displays the file offset in hexadecimal, followed by sixteen space-separated, two column, hexadecimal bytes, followed by the same sixteen bytes presented as printable characters (or periods if not printable), enclosed in |
characters.:
00000000 42 4d 46 00 00 00 00 00 00 00 36 00 00 00 28 00 |BMF.......6...(.| 00000010 00 00 02 00 00 00 02 00 00 00 01 00 18 00 00 00 |................| 00000020 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 ff ff ff ff 00 00 ff 00 |................| 00000040 00 00 ff 00 00 00 |......| 00000046
The first 14 bytes constitute the BMP File Header: 42 4d 46 00 00 00 00 00 00 00 36 00 00 00
Note the bytes 42 4d
initially, i.e. the characters B
and M
. The next 4 bytes (46 00 00 00
) are the file size. While this looks to be (and is) the value 0x46000000
, note that this does not mean the file is size 1174405120
, which is how we would normally interpret 0x46000000. This is because BMP files (and most modern CPUs) represent integers in "little-endian" format, meaning that the bytes are ordered from least significant to most significant, unlike how we usually write integers for human benefit. This means the way we would normally write that value in hexadecimal is 0x00000046
, which is 70 in decimal. The size of this file is indeed 70 bytes:
$ stat -c '%s' /srv/datasets/simple.bmp 70
The next 40 bytes constitute the DIB Header: 28 00 00 00 02 00 00 00 02 00 00 00 01 00 18 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Note that 0x28000000
is the header size (little-endian 40), and the next 8 bytes are the image width and height, both 2 in this case: 0x02000000 0x02000000
.
From offset 0x36
to the end of the file is the pixel array: 00 00 ff ff ff ff 00 00 ff 00 00 00 ff 00 00 00
The first row of pixels: 00 00 ff ff ff ff 00 00
The second row of pixels: ff 00 00 00 ff 00 00 00
Note that first-row pixel values 00 00 ff
and ff ff ff
are the colors red (255, 0, 0)
and white (255, 255, 255)
, respectively, and that even pixel values are stored as little-endian integers, i.e. BGR instead of RGB.
Assignment
You shall write a C++ program that applies one of six different modifications to an existing 24-bit RGB BMP image file and produces another BMP image file containing the result. The resulting image shall only differ in pixel values, i.e. all header and other metadata shall pass through unchanged. The general syntax shall be:
executable input_file output_file modification
The six available modifications are described below, using sample executable cs19_bmp_mod
(which is available on the server) as an example, and file /srv/datasets/cabrillo-logo.bmp
as input.
Perform these modifications by working with the raw contents of the file. Use only standard C++ and the C++ standard library. Do not use any image-specific third-party code!
Modification -brighten
-brighten
increases the intensity of each pixel component by a factor given as a subsequent command-line argument, e.g in the following that increases the intensity by 25%:
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-brighten-25.bmp -brighten 25
Original image:
Modified image:
Modification -darken
-darken
decreases the intensity of each pixel component by a factor given as a subsequent command-line argument, e.g in the following that decreases the intensity by 25%:
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-darken-25.bmp -darken 25
Original image:
Modified image:
Modification -desaturate
-desaturate
converts all colors in the image to corresponding shades of gray, where each component in each pixel is assigned the average of all of the pixel's original components, e.g in the following:
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-desaturate.bmp -desaturate
Original image:
Modified image:
Modification -invert
-invert
inverts all pixel components, e.g in the following:
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-invert.bmp -invert
Original image:
Modified image:
Modification -hflip
-hflip
flips the image horizontally.
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-hflip.bmp -hflip
Original image:
Modified image:
Modification -vflip
-vflip
flips the image vertically.
cs19_bmp_mod /srv/datasets/cabrillo-logo.bmp cabrillo-logo-vflip.bmp -vflip
Original image:
Modified image:
Leaderboard
As submissions are received, this leaderboard will be updated with the top-performing fully/nearly functional solutions, with regard to execution speed.
Rank | Test Time (s) | Memory Usage (kB) | SLOC (lines) | User |
---|
Submission
Submit your source-code file(s) via turnin.
Feedback Robot
This project has a feedback robot that will run some tests on your submission and provide you with a feedback report via email within roughly one minute.
Please read the feedback carefully.
Due Date and Point Value
Due at 23:59:59 on the date listed on the syllabus.
Assignment 08
is worth 60 points of extra credit!
Possible point values per category: --------------------------------------- Modifications (must work perfectly): -brighten 10 -darken 10 -desaturate 10 -invert 10 -hflip 10 -vflip 10 Possible deductions: Style and practices 10–20% ---------------------------------------