Time to play with data! We get our first taste in image manipulation and then we get to practice file read and write procedures in C Programming.
N A V I G A T I O N
Basically, this is a simple bits operation with a cute backstory.
Essentially, there is an image file and it needs to be "flipped" right side up. It is a BMP file, so we need to take its headers into account before manipulating the image. I am going to attempt to breakdown the process this week instead of just putting in my code so you can get a clearer picture of what is happening. Bottom UpThe Image
We begin with this image. It is a vertically-inverted image of one of the buildings on Harvard's campus. Ultimately, it is our job to correct this inversion while accounting for the BMP header data.
The accompanying bmp.h includes some helpful BMP structs and other BMP metadata that will be helpful in our deconstruction and reconstruction of this image. Inside there are some URLs that our assignment specifically tells us to visit: https://msdn.microsoft.com/en-us/library/cc230309.aspx https://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/dd183376(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx
The request of the assignment is that our program be executed from the command line and take in two arguments. The Arguments should take in the original name of the BMP file and the intended new name of the output BMP (as to not overwrite the original).
EXAMPLE: ./bottomup harvard_bottomup.bmp harvard_topdown.bmp This should account for the BMP header data and then collect the BMP data - from bottom right to top left (pixel rows) and write it out to the new BMP. It should write out the header information first, and then write the same pixel data from top left to bottom right in the same order in which it was read in the previous step from bottom right to top left. BITMAPINFOHEADER
Most of the code is already written by the CS50 team in bottomup.c. The important part we need to pay attention to is the BITMAPINFOHEADER struct in bmp.h. Namely, the LONG variable biHeight. As per the Microsoft documentation, biHeight is:
Code Changes
All of the important code is already in place for this program to work. It reads the file, get the header and header info, then gets the bits. After that, it outputs the header, header info, and bits back out to the new file. All done, right? Not quite. At the moment it just writes another upside-down BMP.
In order to make this program work the way that we want it to we are going to have to tweak it ever so slightly. In the wording of the assignment outline, "the code in question needn't be very complicated." This being said, let's take a close look at the struct in BITMAPINFOHEADER as mentioned above.
On lines 42 to 44 of the current code provided by the CS50 team we have:
Starting on line 59, we also have:
This means that the BITMAPINFOHEADER is open between these two lines in memory and assigned to bi. In order to manipulate our output image, we are going to want to alter the value of biHeight as described in the Microsoft documentation to a negative value to change the vertical orientation of our output image.
Between these two sections of code, directly before writing the BITMAPINFOHEADER to the file, I added these lines:
All this does is take the current integer that exists in the BITMAPINFOHEADER and multiply it by (-1) to turn it into a negative value. As per the Microsoft documentation, making this a negative value indicates that it should be upside-down. That is the entirety of our changes! Now when we compile our program and run it, our output is the BMP below:
Quick and easy fix for a wonderful picture! On to the next practice problem...
The idea seems simple. Your software needs to read a file of license plate numbers and write them out. However, when you compile and execute the code it is only printing out the last line of the license plate file recursively. It is our job to determine what the problem is in the code and fix it.
This one really made me think much harder than I needed to. After trying lots of different combinations of codes and methods to copy char *. I was just about to give up. I really wanted to do this without importing string functions. However, this is what I ended up doing... and it made it so easy it wasn't funny.
First, the original program assigns the lines to the array as:
This assigns the address for buffer to plates. So, the last plate that gets put into this buffer is the only one that exists, so when we go to print it later, that is the only plate that prints!
The best answer is to import the memory and string headers, allocate memory to our array value, then use strcpy to copy the string literals to our array's new memory areas.
Our #include <stdlib.h>, and #include <string.h> bring in the libraries we need to handle memory functions and string functions in C. By using MALLOC we are then able to define some space somewhere in memory to move the buffer variable information into plates. We then utilize the string.h function STRCPY to copy the character data from the buffer to our empty array value. Finally, when done we clean out that memory data when we are done printing it using FREE and close the file with FCLOSE. Everything is now done! We passed check50 and valgrind. That's it for the week's practice problems. Here is the complete code for License:
#include <stdio.h>
#include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { // Check for command line args if (argc != 2) { printf("Usage: ./read infile\n"); return 1; } // Create buffer to read into char buffer[7]; // Create array to store plate numbers char *plates[8]; FILE *infile = fopen(argv[1], "r"); int idx = 0; while (fread(buffer, 1, 7, infile) == 7) { // Replace '\n' with '\0' buffer[6] = '\0'; // Save plate number in array plates[idx] = (char *) malloc(sizeof(buffer)); strcpy(plates[idx], buffer); idx++; } for (int i = 0; i < 8; i++) { printf("%s\n", plates[i]); free(plates[i]); } fclose(infile); } I'm posting this on Thanksgiving evening of 2023. If anyone is reading this, have a Happy Thanksgiving!
0 Comments
Leave a Reply. |
Weeks navWeek 0AuthorJonathan Styles (4verageGamer) is just a simple student of all things IT-related during this pursuit of completing the CS50 class from Harvard. Archives |