-3

Here is the check50 output:

:) edges correctly filters middle pixel
:( edges correctly filters pixel on edge expected "213 228 255\n", not "213 228 140\n"
:( edges correctly filters pixel in corner expected "76 117 255\n", not "76 117 66\n"
:( edges correctly filters 3x3 image expected "76 117 255\n21...", not "76 117 66\n213..."
:( edges correctly filters 4x4 image expected "76 117 255\n21...", not "76 117 66

Helpers.c (My problem is here, the rest of the code was provided by cs50, I include to to make a minimal reproducible example, and just in case you want to check any of the structs)

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int sobel[3][3] =
    {
        {-1, 0, 1},
        {-2, 0, 2},
        {-1, 0, 1}
    };
    RGBTRIPLE edged[height][width];

    for (int i = 0; i<height; i++){
        for (int j = 0; j<width; j++){
            double GxRed = 0 , GxGreen = 0 , GxBlue = 0 , GyRed = 0 , GyGreen = 0 , GyBlue = 0;
            int boxRow[3][3] = {{i-1, i-1, i-1}, {i, i, i}, {i+1, i+1, i+1}}, boxCol[3][3] = {{j-1, j, j+1}, {j-1, j, j+1}, {j-1, j, j+1}};

            for (int x = 0; x<3; x++){
                for (int y = 0; y<3; y++){
                    if (boxRow[x][y] >= 0 && boxRow[x][y] < height && boxCol[x][y] >= 0 && boxCol[x][y] < width){
                        GxRed += image[boxRow[x][y]][boxCol[x][y]].rgbtRed * sobel[x][y];
                        GxGreen += image[boxRow[x][y]][boxCol[x][y]].rgbtGreen * sobel[x][y];
                        GxBlue += image[boxRow[x][y]][boxCol[x][y]].rgbtBlue * sobel[x][y];

                        GyRed += image[boxRow[x][y]][boxCol[x][y]].rgbtRed * sobel[y][x];
                        GyGreen += image[boxRow[x][y]][boxCol[x][y]].rgbtGreen * sobel[y][x];
                        GyBlue += image[boxRow[x][y]][boxCol[x][y]].rgbtBlue * sobel[y][x];
                    }
                }
            }
            edged[i][j].rgbtRed = round(sqrt(pow(GxRed, 2) + pow(GyRed, 2)));
            if (edged[i][j].rgbtRed > 255) {edged[i][j].rgbtRed = 255;}
            if (edged[i][j].rgbtRed < 0) {edged[i][j].rgbtRed = 0;}

            edged[i][j].rgbtGreen = round(sqrt(pow(GxGreen, 2) + pow(GyGreen, 2)));
            if (edged[i][j].rgbtGreen > 255) {edged[i][j].rgbtGreen = 255;}
            if (edged[i][j].rgbtGreen < 0) {edged[i][j].rgbtGreen = 0;}

            edged[i][j].rgbtBlue = round(sqrt(pow(GxBlue, 2) + pow(GyBlue, 2)));
            if (edged[i][j].rgbtBlue > 255) {edged[i][j].rgbtBlue = 255;}
            if (edged[i][j].rgbtBlue < 0) {edged[i][j].rgbtBlue = 0;}
        }
    }
    for (int i = 0; i<height; i++){
        for (int j = 0; j<width; j++){
            image[i][j] = edged[i][j];
        }
    }
    return;
}

This is helpers.h

// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width]);

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width]);

// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width]);

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]);

This is bmp.h

#include <stdint.h>

/**
 * Common Data Types
 *
 * The data types in this section are essentially aliases for C/C++
 * primitive data types.
 *
 * Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
 * See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
 */
typedef uint8_t  BYTE;
typedef uint32_t DWORD;
typedef int32_t  LONG;
typedef uint16_t WORD;

/**
 * BITMAPFILEHEADER
 *
 * The BITMAPFILEHEADER structure contains information about the type, size,
 * and layout of a file that contains a DIB [device-independent bitmap].
 *
 * Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
 */
typedef struct
{
    WORD   bfType;
    DWORD  bfSize;
    WORD   bfReserved1;
    WORD   bfReserved2;
    DWORD  bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;

/**
 * BITMAPINFOHEADER
 *
 * The BITMAPINFOHEADER structure contains information about the
 * dimensions and color format of a DIB [device-independent bitmap].
 *
 * Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
 */
typedef struct
{
    DWORD  biSize;
    LONG   biWidth;
    LONG   biHeight;
    WORD   biPlanes;
    WORD   biBitCount;
    DWORD  biCompression;
    DWORD  biSizeImage;
    LONG   biXPelsPerMeter;
    LONG   biYPelsPerMeter;
    DWORD  biClrUsed;
    DWORD  biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;

/**
 * RGBTRIPLE
 *
 * This structure describes a color consisting of relative intensities of
 * red, green, and blue.
 *
 * Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
 */
typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

This is filter.c

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

#include "helpers.h"

int main(int argc, char *argv[])
{
    // Define allowable filters
    char *filters = "begr";

    // Get filter flag and check validity
    char filter = getopt(argc, argv, filters);
    if (filter == '?')
    {
        printf("Invalid filter.\n");
        return 1;
    }

    // Ensure only one filter
    if (getopt(argc, argv, filters) != -1)
    {
        printf("Only one filter allowed.\n");
        return 2;
    }

    // Ensure proper usage
    if (argc != optind + 2)
    {
        printf("Usage: ./filter [flag] infile outfile\n");
        return 3;
    }

    // Remember filenames
    char *infile = argv[optind];
    char *outfile = argv[optind + 1];

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

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

    // 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);
        printf("Unsupported file format.\n");
        return 6;
    }

    // Get image's dimensions
    int height = abs(bi.biHeight);
    int width = bi.biWidth;

    // Allocate memory for image
    RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
    if (image == NULL)
    {
        printf("Not enough memory to store image.\n");
        fclose(outptr);
        fclose(inptr);
        return 7;
    }

    // Determine padding for scanlines
    int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;

    // Iterate over infile's scanlines
    for (int i = 0; i < height; i++)
    {
        // Read row into pixel array
        fread(image[i], sizeof(RGBTRIPLE), width, inptr);

        // Skip over padding
        fseek(inptr, padding, SEEK_CUR);
    }

    // Filter image
    switch (filter)
    {
        // Blur
        case 'b':
            blur(height, width, image);
            break;

        // Edges
        case 'e':
            edges(height, width, image);
            break;

        // Grayscale
        case 'g':
            grayscale(height, width, image);
            break;

        // Reflect
        case 'r':
            reflect(height, width, image);
            break;
    }

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

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

    // Write new pixels to outfile
    for (int i = 0; i < height; i++)
    {
        // Write row to outfile
        fwrite(image[i], sizeof(RGBTRIPLE), width, outptr);

        // Write padding at end of row
        for (int k = 0; k < padding; k++)
        {
            fputc(0x00, outptr);
        }
    }

    // Free memory for image
    free(image);

    // Close files
    fclose(inptr);
    fclose(outptr);
    return 0;
}

This is Makefile

filter:
    clang -ggdb3 -gdwarf-4 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -lm -o filter filter.c helpers.c
To reproduce use any .bmp image. when you run the program, the command line arguments are -e INFILE.bmp OUTFILE.bmp

My code seems to be having problems with the blue values(I think...). I've checked other posts, where they had a typo, I've checked and there doesn't seem to be any. Others used rgbtriple so the values would sum until 255 and stop, but here I am using doubles. I hope its not something stupid, but I've been checking and can't find the problem. Hope someone can help me. Thank you https://cs50.harvard.edu/x/2022/psets/4/filter/more/. (Here is the link to a description of the problem, you can skip to the edges part.)

  • 1
    This seems like a good time to learn how to [*debug*](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) your programs. Especially how to use a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to step through your code line by line while monitoring variables and their values. – Some programmer dude Dec 25 '22 at 19:53
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Dec 25 '22 at 23:23

1 Answers1

0

I just had this problem too. You might have already fixed it, but I'll describe the problem anyways.

A byte can only store values up to 255. If you perform some math on values like that, then the resulting integer might be above 255, causing some overflow glitch. How might you store integers above 255 if a single byte can't?