Bitmap files map three 8-bit (1-byte) color channels per pixel. A pixel is a light-emitting "dot" on your screen. Whenever you buy a new monitor, you will see the pixel configuration by its width and height, such as 1920 x 1080 (1080p) or 3840x2160 (4K). This tells us that we have 1080 rows (height), and each row has 1920 (width) pixels.
The bitmap file format is fairly straight forward where we tell the file what our width and height are. When we write this file, we can open it with an image viewer on Windows, Mac, or Linux to view our rendered image.
Writing bitmap files requires us to open a file as a binary file for writing. We won't be inputting any data from a bitmap file, instead, we will just be writing our rendered image into a bitmap file so we can view it.
class BitmapFile: def __init__(self, width, height): self.width = width self.height = height # There are 3 color channels per pixel # and there are width * height pixels. self.pixels = [] for row in range(self.height): for col in range(self.width): self.pixels.append([0, 0, 0])
You can see our initialization function will take a width and a height and set up a list of pixels. Each pixel is a list of three values, as you can see when [0, 0, 0] is appended. Do not think you can do something like the repetition function with this ([0, 0, 0] * (width * height)). Remember that lists are references. This will cause all of your pixels to reflect one single color since each pixel refers to the same one!
def set_pixel(self, row, col, pixel): # row and col are integers # pixel is a sub-list of three values: [red, green, blue] loc = row * self.width + col self.pixels[loc][0] = pixel[2] self.pixels[loc][1] = pixel[1] self.pixels[loc][2] = pixel[0]
Here we are using set_pixel to take a row and a column. Remember that rows run height-wise and columns run width-wise. The final parameter, pixel, is a list (or tuple) of three values. The bitmap file requires that the pixel colors be in the format blue first, green second, red last. However, we usually logically think of pixels in red first, green second, and blue last. This is why you can see that I flip the red and blue channels so that we can provide pixel in the RGB order, but internally, it stores it in the BGR order.
def get_pixel(self, row, col): loc = row * self.width + col return self.pixels[loc]
Getting a pixel will be important when we write the file. Recall that the BMP file has a table of pixels, so we need to know what values to store. Since set_pixel already put these in the correct order for us, we don't have to mess around to make sure it is in the right order when we write to our BMP file.
def write(self, file_name): bmpfile = open(file_name, "wb") # Write Bitmap File Header # Write Bitmap Info Header # Write pixels in BGR (blue, green red) # You can use self.get_pixel to get the # color values as a list.
I've put comments for the sequence of things we need. I will show you below what the "headers" are. For now, we can't do anything until we build these headers.
The BitmapFile class stores the width of the picture and the height. Then it stores a list of pixels. Each pixel is a sub-list that contains three color channel values: red, green, blue. These will also be integer values between 0 and 255. 0 is color off or black, whereas 255 is full color on. For example, 255, 0, 0 would be full red, no green, and no blue, so you will get a red pixel, whereas 255 255 255 would be full red, full green, and full blue, which will give you a white pixel.
The set_pixel function will take a row (recall that there are height number of rows) and a column (recall that there are width number of columns) and set the color value of that pixel to pixel. The pixel parameter is a sub-list that contains three values in order: red, green, then blue. Since the bitmap file stores in the order of blue, green, red, we have to swap the blue and red channels. We can either do this when we write to the bitmap file, or we can do this when we set the pixel. The shell code I show you above does it with set_pixel. That's why you see [0] = [2], and [pixel][2] = pixel[0].
The bitmap data type has two headers, which give any program wanting to read your bitmap file information about how to actually read the file. The bitmap file is laid out as shown below:

There is a lot of information here, but let's break it down into simpler components.
The file is laid out as follows: BitmapFileHeader followed by BitmapInfoHeader followed by the Pixel Array
The BitmapFileHeader contains 14 bytes of information in the following order:
signature - 2 bytes
size - 4 bytes
reserved - 4 bytes
offset - 4 bytes
The signature is a constant and is two characters 'BM'. Recall that one character is exactly 1 byte. You can write 'B' as integer value 66 and 'M' as integer 77.
The BitmapInfoHeader contains 40 bytes of information in the following order:
size - 4 bytes
width - 4 bytes
height - 4 bytes
planes - 2 bytes
bits per pixel - 2 bytes
compression - 4 bytes
bmp_size - 4 bytes
horizontal_resolution - 4 bytes
vertical_resolution - 4 bytes
colors - 4 bytes
colors_used - 4 bytes
You won't be using all of the fields above, and most of them will be set to 0, but you can see this is where we get the width and the height of our picture from!
The pixel array is stored from bottom to top. So, the first row that you will store in the pixel array is actually the bottom row in the picture.
PADDING: There is one issue with BMP files, and that is that the row must be a multiple of four bytes. Recall that we are storing three bytes per pixel. So, if our width * 3 bytes is not a multiple of four, we have to add what is called padding. Padding is unused data just to move the subsequent data further into the binary file.
Padding is fairly straightforward to calculate, and you only need to do it when you know the number of bytes per pixel and the number of pixels in a row. First, we multiply the width with the number of bytes per pixel, which in our case will be 3. So row_bytes = width * 3. Now, we need to determine if this is a multiple of four bytes before going any farther. So, we can use the mod operator (%) to see what the remainder is after division. So, row_bytes % 4 will give us one of four values: 0, 1, 2, or 3. If the value is 0, then width * 3 is a multiple of four, and our job is done. However, if the value is 1, 2, or 3, that means we need to add padding bytes. However, the number of bytes we need is the inverse of the result. For example, if our remainder is 1, that means there are three more bytes we need to add before we get to a multiple of four: 1 % 4 = 1, 2 % 4 = 2, 3 % 4 = 3, 4 % 4 = 0. So, we can do this by 4 - row_bytes % 4. Notice we only do this if our row_bytes % 4 gives us anything other than 0. If it is 0, we would get 4 - 0, which would add 4 padding bytes. WE DO NOT WANT THIS. The whole point is to make each row a multiple of four bytes.
We can use the bytearray data type to help us get the bytes in the correct order. Recall that the header is 14 bytes for the file header + 40 bytes for the info header. So we need a byte array of 54 bytes. We can create one by writing ba = bytearray(54). This will give us an array of bytes that we can manipulate like a list. We also need to transform our data, such as the width and height into bytes. Luckily, there is a helpful function for an integer called to_bytes():
Create a class that stores the bitmap file header and bitmap info header to make it easier when you write to your file. For example,
class BitmapHeaders: def make_headers(self): ba = bytearray() # First the bitmap file header: signature (2 bytes), size (4 bytes), reserved (4 bytes), offset (4 bytes) # signature is always 'BM' ba += b'BM' # size is the total size of the file. We have 54 bytes in of header, followed by self.width * self.height pixels padding = 0 row_bytes = (self.width * 3) % 4 if row_bytes > 0: padding = 4 - row_bytes size = 54 + (self.width * 3 + padding) * self.height # We have to specify "little" byte order since BMP files require that the "little" end of # the four bytes go first. ba += size.to_bytes(length=4, byteorder='little') # 4 bytes of reserved. bytearray() automatically initializes these to 0, so we shouldn't have to do anything ba += int(0).to_bytes(length=4, byteorder='little') # Offset comes next. This is how far we have to jump to get to the pixel array, which means we have to # skip the file and info header, so we need to skip exactly 54 bytes offset = 54 ba += offset.to_bytes(length=4, byteorder='little')
Everything we've done above was done to write the 14 byte file header. Notice that to_bytes is our helpful friend here! Also, notice that I use += for ba (bytearray). We could make the byte array 54 bytes, however, it gets a tiny bit more cumbersome to write into specific places in the byte array even with using slices. In the case above, we write in the proper order, and everything fills out. When we're done, we have a 14 byte bytearray.
Now, we have to write the info header. This comes directly after the file header and is the next 40 bytes to make a 54 byte header.
# Now we get to the info header: # size (4 bytes), width (4 bytes), height (4 bytes), planes (2 bytes), bits per pixel (2 bytes), # compression (4 bytes), bmp_size (4 bytes), horizontal resolution (4 bytes), vertical resolution (4 bytes), # colors (4 bytes), colors used (4 bytes) size = 40 # The info header is 40 bytes ba += size.to_bytes(length=4, byteorder='little') # Width ba += self.width.to_bytes(length=4, byteorder='little') # Height ba += self.height.to_bytes(length=4, byteorder='little') # Planes is 1 ba += int(1).to_bytes(length=2, byteorder='little') # Bits per pixel is 24, we use 3 bytes per pixel which is 3 * 8 = 24 bits bpp = 3 * 8 ba += bpp.to_bytes(length=2, byteorder='little') # Compression is 0 ba += int(0).to_bytes(length=4, byteorder='little') # BMP size we can set to 0. This tells programs to figure it out with the width and height ba += int(0).to_bytes(length=4, byteorder='little') # horizontal and vertical resolutions can be set to 1 hres = 96 ba += hres.to_bytes(length=4, byteorder='little') vres = 96 ba += vres.to_bytes(length=4, byteorder='little') # Colors and colors used can be set to 0 to signify the program should "figure it out" ba += int(0).to_bytes(length=4, byteorder='little') ba += int(0).to_bytes(length=4, byteorder='little') # We can only write the immutable bytes() version to a file, so we can convert the bytes # using the bytes() type caster. return bytes(ba)
The info header has now been added to the byte array. I use return bytes(ba) because we don't want the bytes to change when it leaves our make_headers() function. Plus it is better for binary files to be written.
Now that we have the headers being produced, we can finish the write function in the BitmapFile class:
padding = 0 if (self.width * 3) % 4 != 0: padding = 4 - (self.width * 3) % 4 headers = BitmapHeaders(self.width, self.height) bmpfile.write(headers.make_headers()) # Recall we count backwards for the rows for row in range(self.height-1, -1, -1): for col in range(self.width): px = self.get_pixel(row, col) bmpfile.write(bytes(px)) bmpfile.write(bytes(padding)) bmpfile.close()
As you can see, by making the headers class, we simply call it and build the headers for us. After both headers are written, we are 54 bytes into the file. Here is where the pixel table comes into play. The pixel table starts bottom to top, but from left to right. This means that the row needs to count backwards whereas the columns count forwards. As you can see, I use our get_pixel() function to get the value, then convert those pixel values into bytes before writing them to the file. Finally, don't forget about the padding!
You can test by writing a main() function that puts in RGB values based on width and height to see if they are writing correctly. For example,
def main():
width = 255
height = 255
bmf = BitmapFile(width, height)
for row in range(height):
for col in range(width):
px = [row % 256, row % 256, col % 256]
bmf.set_pixel(row, col, px)
bmf.write("test.bmp")
if __name__ == "__main__":
main()this should produce a small picture that looks like the following:
We need at least 10 more requests to produce the answer.
0 / 10 have requested this problem solution
The more requests, the faster the answer.
Problem1: BMPmain.c, BMPfns.c, BMPfns.h, Makefile The file 'BMPmain.c' contains a main() function which is already written for you and attached with this homework. When appropriate functions are provided, main() will create a .bmp image file. Your job is to write 'BMPfns.c' which contains the functions which main() uses to create .bmp image files. You must also write the header file 'BMPfns.h' to #include in BMPmain.c and which contains prototypes of the functions defined in BMPfns.c . Problem2: BMPcheckerboard.c, BMPfns.c, BMPfns.h,...
the following python code edits BMP image file to negative but I need help with modifying this code so it turns it the same BMP image file into a black and white instead of a negative. heres python code I have so far [pasted below] ## # This program processes a digital image by creating a negative of a BMP image. # from io import SEEK_CUR from sys import exit def main() : filename = input("Please enter the file name:...
Please write a code in python! Define and test a function named posterize. This function expects an image and a tuple of RGB values as arguments. The function modifies the image like the blackAndWhite function, but it uses the given RGB values instead of black. images.py import tkinter import os, os.path tk = tkinter _root = None class ImageView(tk.Canvas): def __init__(self, image, title = "New Image", autoflush=False): master = tk.Toplevel(_root) master.protocol("WM_DELETE_WINDOW", self.close) tk.Canvas.__init__(self, master, width = image.getWidth(), height = image.getHeight())...
Encoding and Decoding PPM image
3 & 4 are parts of question 2
Code for a09q1:
We were unable to transcribe this image3 Encoding an Image in a09q2.py In the next four sections, you will no longer write class methods but rather functions. In each of the next four parts, you should be importing the PPM class from a09q1.py to use with the command from a09q1 import PPM Note that this is similar to how the check module was imported...
Please design the function in
version 3 of python
4. Write a function extract(pixels, rmin, rmax, cmin, cmax) that takes the 2-D list pixels containing pixels for an image, and that creates and returns a new 2-D list that represents the portion of the original image that is specified by the other four parameters. The extracted portion of the image should consist of the pixels that fall in the intersection of the rows of pixels that begin with row rmin...
% BACKGROUND:Image processing is the generation of a new image from one or more existing images. % MATLAB makes it easy to work with images by providing some basic functions % that allow you to read and write images in standard image -file formats, such as JPEG % Locate the attached photo of a blue bird stored in JPEG format, bbird.jpg (must be on same folder as script). % Fill in the ? in the code with correct values to...
WRITE A C++ PROGRAM TO ANSWER THE QUESTIONS BELOW. You are provided with an image in a new file format called JBC Here is an example of the format: 2 3 100 50 40 200 66 56 12 45 65 23 67 210 0 255 100 45 32 123 The first line means that this is a 2 (width) by 3 (height) image of pixels. Then, each line represents the color of a pixel. The numbers are from 0 to...
Please assist. I keep getting the error message in the middle
screen when I run the program on the left. The image on the right
is the section of images.py where it's indicating the issue with
the .split is. How do I fix this?
images.cy - /Users/carrietarpy Downloads/lab9-3/images.py 12.7.18) Python 2.7.18 Shell Python 2.7.15 (v2.7.18:542 102112, Apr 19 2820, 29:48:48) [GCC 4.7.1 Compatible Apple II w 6.3 Clong-FA3.0.57)] on der in Type "help", "copyright', 'credits' or "license()' for more inforyotion...
Can you please assist me with this HTML? Below is what I have but it isn't working. Filename: jpf_sudoku.css /* Table Styles */ table.spuzzle { border-collapse: collapse; margin-top: 0px; margin-bottom: 0px; margin-left: auto; margin-right: auto; width: 90%; } table.spuzzle td { border: 5px outset gray; width: 33.3%; } table.spuzzle th { font color: gray; padding-right: 10px; padding-bottom: 10px; } /* Inner Table Styles */ table.subTable { border-collapse: collapse; width: 100%; } table.subTable td { box-shadow: 0px 0px 15px inset; border:...
We are given a color picture consisting of an m?n array AŒ1::m;1::n? of pixels, where each pixel specifies a triple of red, green, and blue (RGB) intensities. Sup- pose that we wish to compress this picture slightly. Specifically, we wish to remove one pixel from each of the m rows, so that the whole picture becomes one pixel narrower. To avoid disturbing visual effects, however, we require that the pixels removed in two adjacent rows be in the same or...