Everything went good so far until this pset and the resize exercise, it seems that I'm stuck and need help!
Everything works perfectly when the factor is a whole number (eg. 2).
In my code, the factor is declared as a float number.
According to ~cs50/hacker4/peek student.bmp staff.bmp
, every single line of my headers matches green with the staff ones.
The outputted resized picture is identical to the bitmap image created by the ~cs50/hacker4/resize factor infile outfile
command.
Headers still match perfectly when I set the factor to a decimal number (eg. 2,6). However, my outputted resized image gets completely messed up while the staff's one looks great.
If it's all about math, I'm wondering why am I crunching numbers right when it comes to set the new values in my outfile's headers if these same values lead to a visual mess once they are represented in my outputted image?
I've read many other topics on this exercise but none of them are talking about how to manage decimal factors. I guess I have to fix a few details but I can't figure out where in my code.
Thanks for your tips!
EDIT #1
I've worked on my code and started to figure out how to downscale a picture but something is still missing.
For more convenience, I've resized the smiley.bmp (8 x 8 pixels) with a factor of 10 to get a bigger image. Then, I've tried to resize my 80 x 80 pixels smiley.bmp with a factor of 0.5
Using staff's code, the smiley is perfectly outputted in a picture of 40 x 40 pixels. In my case, it doesn't as only the top half of the smiley is outputted in a picture of 40 x 40 pixels.
My pseudo looks like this:
//check if factor is less than 1
//set a float called ratio to original width divided by new width
//set a float called pixelposition to 0
//loop through the original height
//loop through the original width
//set temporary storage for RGBTRIPLE
//read each pixels in the current row using temporary storage
//if abs(pixelposition) == the position of the current pixel
//write the pixel read in temporary storage
//add ratio to pixelposition
//end of width loop
//reset pixelposition
//end of height loop
//else
//...etc
I also outputted a 40 x 40 pixels picture with two smileys drawn next to each others! This happened when I divided the number of elements in fread() by the factor.
To me, it seems that I select the right pixel in the original picture but I write each of them twice (sort of fwrite() / factor
) in a picture frame half smaller. I don't figure out to reduce this frequency of writing as when I set a number of elements in fwrite() inferior to 1, it outputs only black pixels.
Last detail: when i change the factor to something more complex (eg. 0,7), it outputs something very messy, a picture with a lot of black pixels. As smiley.bmp only deals with white & red pixels, I guess garbage values are the cause for any other colors outputted. For the moment, I don't know how this happens but I'll have to think about it at some point...
EDIT #2
Here are two parts of my code in pseudo:
if factor less than one
malloc an array called scanline sizeof RGBTRIPLE * newWidth * abs(oldWith/newWidth)
else
malloc an array called scanline sizeof RGBTRIPLE * newWidth * factor
Here I malloc an array in which I'll store the pixels I keep in infile before writing them in outfile. To do so:
declare an integer called index (to count my array positions)
iterate over infile's scanlines
set index to 0
iterate over pixels in scanlines
set temporary storage for RGBTRIPLE
read RGB from infile
declare a loop of length equals to factor
scanline[index] = current RGB read
index++
close for loop
stop iterating over pixels
declare a for loop of length equals to factor
write the scanline index with a number of elements equals to newWidth
add new padding
close for loop
skip over old padding
stop iterating over scanlines
free scanline
Here I'm sure there's something missing as this piece of code is never told when to keep or dump the pixel read. Same remark for the scanlines. To know which ones must be kept, I've written a very short program, here it is:
#include <stdio.h>
#include <cs50.h>
float width;
float height;
float factor;
int main (void)
{
printf("Width please: ");
width = GetInt();
printf("Height please: ");
height = GetInt();
printf("Factor please: ");
factor = GetFloat();
float newWidth = abs(width * factor);
float newHeight = abs(height * factor);
float pixratioW = width/newWidth;
float pixratioH = height/newHeight;
float pixposW = 0;
float pixposH = 0;
//rows to keep
for (int j = 0; j < newHeight; j++)
{
printf("Row %d kept!\n", abs(pixposH));
pixposH += pixratioH;
//columns to keep
for (int i = 0; i < newWidth; i++)
{
printf("Column %d kept!\n", abs(pixposW));
pixposW += pixratioW;
}
pixposW = 0;
}
}
When I transcript this logic to my code, everything goes wrong. I use if conditions to check the pixposW and pixposH and if conditions are met successfully, I fill my scanline array.
Talking about the scanline array, I modify the malloc if factor is inferior to 1:
malloc an array called scanline sizeof RGBTRIPLE * newWidth * pixratioW
Multiplying by 0,xx creates this error:
*** Error in `./resize': free(): invalid next size (fast): 0x08df52d8 ***
Aborted (core dumped)
So to sum everything up: my code written above in pseudo works perfectly when the factor is a whole non number or a decimal number superior to 1. I'm sure I'm close to solve it, I'll soon do a full GDB run to track my code and see when it goes wrong.