When bi.Width * sizeof(RGBTRIPLE) is a multiple of 4, the expression
(bi.biWidth * sizeof(RGBTRIPLE)) % 4
gets evaluated to 0 which, it turn, gets the expression
4 - [(bi.biWidth * sizeof(RGBTRIPLE)) % 4]
evaluated to 4. And since you don't wanna add/seek 4 bytes in case the scanline is already a multiple of 4, you take the remainder of dividing by 4 to ...
Your approach is correct, but you have three errors to deal with, one of which is irrelevant.
First, as you guessed, your calculation for fseek is in error. In simple terms, you've placed parentheses incorrectly. Hint: padding only exists once on each line of pixels. Look carefully at how you laid out the line and you should be able to resolve it.
Let's say that the biWidth is 4. As such, the padding must be 0. Let's say we don't use that last %4
padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4);
padding = (4 - (4 * 3) % 4)
padding = (4 - (12%4)
padding = 4 - 0 = 4 !!
You need that last %4 to handle the case where the pixel width is a multiple of 4.
You are calculating the new bi.biSizeImage incorrectly.
bi.biSizeImage is the size in bytes of the raw bmp data, that means the size in bytes of the pixels information plus the padding.
bi.biSizeImage = (width * height * sizeofpixel) + (padding * height *
Notice that the height can be a negative value, so you need to use it's ...
A subtle problem. You probably realized that it had something to do with padding, but couldn't track it down. The problem is that you forgot to account for the padding of the input file when repositioning the file pointer after processing each line of pixels. Look at the code block at the beginning of the for loop that resets the pointer (btw, very creative....
It's the fact that your biSizeImage calculation is not correct, so whenever there is padding, you get the wrong value in your header
bi.biSizeImage = ((bi.biWidth)* abs(bi.biHeight) * sizeof(RGBTRIPLE)) + paddingOutfile;
For example, a 5x5 bitmap should have 1 byte of padding, using your calculation:
(5*5*3) + 1 = 76
But biSizeImage should be the number ...
For the strange xxd output, it's because you have given a wrong value for the columns -c flag. Since the small.bmp image has a width of 3 pixels, it has as -c
3 pixels * 3 bytes each pixel == 9 bytes
+ 3 bytes of padding to be a multiple of 4
we have 12 bytes
That's why the command for the xxd on small is
xxd -c 12 -g 3 -s 54 small.bmp
Now If you resize ...
as explained per the specs, the size of each scanline in a BMP has to be multiple of 4. padding bytes are appended to each scanline in case its size wasn't multiple of 4 in order to achieve the rule above (i.e., make the size multiple of 4).
for example, in a 3 × 3 BMP, the size of each scanline is 3 pixels × sizeof(RGBTRIPLE) which is equal to 9 bytes (...
In the demo code that merely copies a bitmap, they are demonstrating how to strip off the padding and then add it back when writing to the outfile because that ability will be needed later.
Yes, every scan line has padding at the end because each line needs to end on a 4-byte boundary. Keep that in mind because when you are scaling the image up to a ...
Row size is a DWORD ie 32 bits/4 bytes. So a the 24 bit pixels must be padded to fit. See also this answer in Stack Overflow...
"Because 24 bits is an odd number of bytes (3) and for a variety of reasons all the image rows are required to start at an address which is a multiple of 4 bytes."
Your padding calculation is fine (I believe). I think the problem lies on the "logic". Once you've completed scanning the first line, you force the file cursor to skip the infile padding:
for (int j = 0; j < bi.biWidth; j++)
// read RGB triple from infile
// write RGB triple to outfile w/ magnification
// skip over ...
Remember, each RGB triple is 3 bytes.
If the image is 3 pixels wide, it takes 9 bytes per row. The padding is therefore 3 bytes per row, bringing it to 12.
If you look further down you'll see they write the padding one byte at a time.
The issue is with your fseeks. To understand how this program should work, let's assume the original picture (I’ll call this infile for now) is the following:
G G G padding
G W G padding
G G G padding
Each "G" or "W" represents 1 green or white pixel or size RGB triple.
Think about if we had a cursor for where we are in the original picture (infile). We ...
You have two problems, one with the header and one with image processing.
In the header, you have calculated all the values correctly. (BTW, that was the most unique way I've seen to date to add the size of the headers to the image size to get bfSize. ;-) It's correct, but I'd find a simpler way to do it that isn't so confusing to anyone that would have to ...
Your code has a number of problems. Based on what you have said, and what is in the code, I think you'd benefit more from some guidance on how to work through this pset and some general advice.
When attacking a project like this, it's best to break a problem down into smaller and smaller pieces and to do them one at a time. If you're working on something ...
OK there are two definite mistakes, (could be more but can't tell without the full code).
First, the following lines:
// skip over padding, if any
fseek(inptr, scan_padding, SEEK_CUR);
should be on the line bellow them, so outside the inner for loop. That's because, when you iterate over the pixels of the scanline, the padding is only at the end of the ...
Two small problems with significant impact. First, the code calculates the output padding before calculating the output file width. This is disrupting the size of the output padding and two header values.
Second, when vertically scaling, the code outputs the current line as many times as necessary, but each time it does, it also skips forward over padding ...
If you look at the actual data of the output file, certain patterns become obvious. Say that the input file is being scaled up to 2. The first line from the input file is being scaled up correctly, and is being done twice correctly. But the first problem appears next. If you look at the output for the second line from the input file (the third line in the ...
It's not needed for a padding of 1, 2, or 3 bytes.
But imagine what happened if bi.biWidth were a multiple of 4.
bi.biWidth * sizeof(RGBTRIPLE) would be a multiple of 4.
(bi.biWidth * sizeof(RGBTRIPLE)) % 4 would be 0.
4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4 would be 4, but should be 0. You'd fix that by applying another %4.
You change bi.biWidth and bi.biHeight to new scale using
bi.biWidth = bi.biWidth * enlarge;
bi.biHeight = bi.biHeight * enlarge;
and then use code that relies on the values to represent the input file
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) //iterate for each scanline
for (int k = 0; k < bi....
Yes, the fseek and padding loop are absolutely necessary.
Think about it mathematically. The image portion is composed of 36 bytes (3 lines with 3 3-byte pixels per line plus 3 bytes of padding per line). The i loop (height) will execute 3 times and the j loop (width) will execute three times (and read/write 9 bytes). For a total of 27 bytes. The output ...
This code is far from perfect. It incorrectly calculates biSizeImage. biSizeImage cannot simply be raised to a power. The biSizeImage of the new file must be calculated using the new padding size, height and width.
Next, the image scaling requires the use of the original biHeight and biWidth to track the input file, which have been overwritten and lost. ...
It would be easy to say what the problem is, but what fun would that be for you? ;-)
The problem is only indirectly related to padding. You still don't have your header calculations right. When you work on them, think carefully about the units of measure used by each variable in the calculations.
It sounds vague, but when you figure it out, it'll make ...
You should run the staff's version for a couple of files and different values of resize and then run peek on those files to see which are the headers that actually change.
Also, take a closer look at the code. bi.biSize is one of the headers used to make sure the file is a bmp. Do you think that one should really change?
Other than that, you're not ...
You could use
fseek(inptr, -bi.biWidth * sizeof(RGBTRIPLE), SEEK_CUR);
(no padding, as you never read some) to go back to the start of the line where you fseek at the moment, and after that loop, use
fseek(inptr, bi.biWidth * sizeof(RGBTRIPLE) + padding_inp, SEEK_CUR);
to jump to the next line.
You have two problems, neither is related to the padding. Look at this line:
fseek(inptr, -(bi.biHeight * sizeof(RGBTRIPLE) + inptr_padding ), SEEK_CUR);
This line is designed to reposition the input file pointer at the beginning of the next line to be processed in the image. To do this, you need to go forward, and you need to go forward by the width of a ...
It does have to do with the padding. There are two issues with it - one is a typo and the other is about program structure.
First, look at the following:
if (j % resize != 0)
fseek(inptr, -(crntWidth * sizeof(RGBTRIPLE) + newPadding), SEEK_CUR);
You are repositioning the cursor at the beginning of the current line in the INPUT file. Why then, ...
One of the problems is that you're not resizing vertically. What you're doing is:
1) read one triple and write it as many times as needed by resize factor. Repeat this until a whole scanline has been read and written. (All this is correct)
2)Then you skip the infile's padding.
3) You repeat steps 1 and 2 n amount of times. But each time you start the ...