0

okay so yesterday I started resize and made a bit of progress, today I played around with it to try and fix the alignment issues I had and somehow totally screwed it up and now I'm getting colours which are not even in the original image.

here is what I got to yesterday: https://snag.gy/phJsSL.jpg

and this is what I'm getting now: https://snag.gy/GbFrBM.jpg

before i had a rough idea that the black was misplaced padding which was offsetting the white to not be centered and i just needed to fix that. now i actually dont know whats wrong and am pretty stressed out.

I even used undo to get it back to the point where I added the code from but didn't make any difference here's the code I really don't understand where the blue and red pixels are coming from.

// Copies a BMP file

#include <stdio.h>
#include <stdlib.h>

#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
    fprintf(stderr, "Usage: copy infile outfile\n");
    return 1;
}

// remember filenames
char *s = argv[1];
char *infile = argv[2];
char *outfile = argv[3];

int n = atoi(s);

// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
    fprintf(stderr, "Could not open %s.\n", infile);
    return 2;
}

// open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
    fclose(inptr);
    fprintf(stderr, "Could not create %s.\n", outfile);
    return 3;
}

// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
    bi.biBitCount != 24 || bi.biCompression != 0)
{
    fclose(outptr);
    fclose(inptr);
    fprintf(stderr, "Unsupported file format.\n");
    return 4;
}
else
{
bi.biWidth *= n ;
bi.biHeight *= n;
int wpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bi.biSizeImage = ((sizeof(RGBTRIPLE)* bi.biWidth) + wpadding) * 
abs(bi.biHeight);
bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + 
sizeof(BITMAPINFOHEADER);


// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);

// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

// determine padding for scanlines
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    // iterate over pixels in scanline
    for (int j = 0; j < bi.biWidth; j++)
    {
        // temporary storage
        RGBTRIPLE triple;

        // read RGB triple from infile
        fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

        //loop to write rgbtriple N amount of times
        for (int x = 0 ; x < n ; x++){



        // write RGB triple to outfile
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }}

            for (int k = 0; k < wpadding; k++)
    {
        fputc(0x00, outptr);
    }

    // skip over padding, if any
    fseek(inptr, padding, SEEK_CUR);

    // then add it back (to demonstrate how)

}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}}
1

You've clearly looked at the images generated, but have you looked at the raw image data using the xxd tool? It's a lot more revealing because you can see patterns in the raw data!

There are a couple major issues. First, padding is based on biWidth of the particular file. In the code above, both the input and output file's padding values are based on the output file's biWidth, so most of the time, the padding will be wrong for one file or the other.

Next, the for loop that reads from the input file is based on biHeight of the output file.

In general, make sure that you are using input file parameters and values for reads and output file values for writes or to control for loops!

Then, there's no code to repeat processing of the individual line more than once.

As a side note, look at the if/else setup at around line 50. If the if statement is true, then the program terminates, otherwise, the code will continue to run, so there's no need to encapsulate the rest of the program in an else clause. (Else clauses are optional. They are only required when one path OR another MUST be taken, and then more code follows both paths.)

While technically correct, this else clause is a bad practice. It can lead to confusion and bugs later if the code ever has to be updated and the programmer doesn't fully understand what's going on. It's also unnecessary and excess code.

There may be more issues, but this will get you going.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

2
  • thankks alot but what is xxd is it the right click to see hex code or something else
    – aoc
    Jul 20 '18 at 0:09
  • Sorry. I wasn't aware that the xxd tool was no longer being taught. Instead, from the whodunit problem, there's this: Within CS50 IDE’s file browser, right- or control-click smiley.bmp and select Open as hexadecimal in order to view the file’s bytes in hexadecimal (i.e., base-16). In the tab that appears, change Start with byte to 54, change Bytes per row to 24, change Bytes per column to 3. Then click Set. If unable to change these values, try clicking View > Night Mode and try again. You should see the below, byte 54 onward of smiley.bmp.
    – Cliff B
    Jul 20 '18 at 1:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .