0

I'm currently trying to program a function that allows a user to read in an image and they can either flip the image horizontally or vertically, or convert the image to grayscale. I'm having trouble getting the grayscale function to work.

An error says no match for 'operand[]' (operand types are 'Image' and 'int'). Another error says no match for 'operator=' (operand types are 'Image" and 'unsigned char').

How can I get it so the code can run correctly?

void toGrayScale(Image image, Pixel pixel, int width, int height)
{
    Image newImage[width][height];
    for (int i = 0; i < width; i++){
        for (int j = 0; j < height; j++) {
            unsigned char color[] = image[width][height];
            color[0] = i % 256;
            unsigned char red = color[0];
            color[1] = j % 256;
            unsigned char green = color[1];
            color[2] = (i * j) % 256;
            unsigned char blue = color[2];
            unsigned char gray = round(0.299*red + 0.587*green + 0.114*blue);
            newImage[i][j] = gray;
        }
    }
}

Here's the header file I'm using:

struct Pixel {    
    int numRows;
    int numCols;
    char color[];
    int red;
    int green;
    int blue;
};

struct Image {
    int width;
    int height;
    int size;
    Pixel pixel;
};

 // loads a "P3" PPM  formatted image from a file
void loadImage();

 // saves an image to a text file as a "P3" PPM formatted image
void saveImage();

 // filters an image by converting it to grayscale
void toGrayscale(struct Image);

 // manipulates an image by flipping it either vertically or horizontally
void flipImage(struct Image, bool horizontal);
Ross Rogers
  • 23,523
  • 27
  • 108
  • 164
bigups610
  • 1
  • 2
  • 3
    This entirely depends on the capabilities of the `Image` type, which you did not show. You are trying to assign an `Image` object to an `unsigned char[]` array, and then assign a single `unsigned char` back to an `Image`. Presumably, `Image` provides methods for reading/setting its pixels. We can't see what those methods are. – Remy Lebeau Dec 03 '20 at 18:24
  • 2
    On a side note, `Image newImage[width][height];` is [not standard C++](https://stackoverflow.com/questions/1887097/). Use a `std::vector` instead when working with variable-length arrays. Except that I don't think you actually want an `Image[][]` array to begin with, just a single `Image` with indexed pixel access. Without knowing what `Image` actually is, we can't help you fix your code syntax. Please [edit] your question to provide the definition of `Image`, or at least a link to its documentation. – Remy Lebeau Dec 03 '20 at 18:29
  • 1
    Please don't use wrong tags. This question has nothing to do with jEdit. :-) – Vampire Dec 04 '20 at 10:18
  • I'm using jedit to write the code. – bigups610 Dec 04 '20 at 16:49
  • @bigups610: As a jEdit expert is unlikely to be helpful in answering your question, you should not use that tag. – Mooing Duck Jan 05 '21 at 21:24
  • Is this for C or C++ code? I can't be certain, but I _think_ this is C++, due to the lack of `typedef` on the struct. – Mooing Duck Jan 05 '21 at 21:24

1 Answers1

0

You have a few things in your code that don't make much sense to me

void toGrayScale(Image image, Pixel pixel, int width, int height)

Declares a function returning NOTHING and taking one Image, ONE Pixel, one width and one height

Image newImage[width][height];

Creates an array of arrays of Images

color[0] = i % 256;
unsigned char red = color[0];

writes a value to color[0] (might or might not do something, depending on if you have a correct copy constructor) and then you directly copy the value into red for further processing.

I would recommend to rethink your image struct, because in it's current state it is not able to store an image (at least not in the way you would probably like.)

One approach would be to define a pixel as just a pixel:

struct Pixel {
    uint8_t r, g, b;
};

and the image as a width, a height and a lot of pixels.

struct Image {
    int width, height;
    std::vector<Pixel> pixels;
};

toGrayscale should have the signature:

Image toGrayscale(const Image& image);

Meaning a function returning an image and taking a constant (unmodifieable) reference to an existing image.

Then you can create a new image (named newImage) by using

Image newImage{ WIDTH, HEIGHT, std::vector<Pixels>( WIDTH * HEIGHT )};

To get the colorvalues in your loop you can use:

uint8_t red = image.pixels[j * width + i].r;

and to write the gray value to the new image, you can use

newImage.pixels[j * width + i].r = newImage.pixels[j * width + i].g = newImage.pixels[j * width + i].b = gray;

At last you can return your image with return newImage.

You should probably also rethink the signatures of your other functions, e.g.

void loadImage();

Says that the function takes no arguments and returns nothing, while it should probably take at least the location where the image is saved (probably either const std::filesystem::path& or const std::string& or const char*) and return an image.

Orcthanc
  • 49
  • 1
  • 6