Basic image processing

Hello again,

I wonder if you can help me and see if I am on the right track.
We have an assignment for basic image processing, I understand about coursework so I'm not looking for the answer just guidance.

So we have been given a basic program that when run loads and image file and saves a copy. The we have been given an image handler library that actually handles the loading and saving.

What we have been tasked to do is to modify the basic program with a function that rotates the image 180 degrees then saves it. No mention of using special graphics handlers etc.

Now the image handler loads the image into an array called PIXELS{WIDTH}{HEIGHT}

I'm working along the lines of creating a function that manipulates the array swapping the width and height values. Using a for loop. Am I on the right track here?

Just so you are aware of the knowledge we have gained so far, it is quite basic. Strings, Loops, Arrays and developing functions. We haven't gone into calling up different libraries or built in functions in C++

we need to know exactly what pixels is, or your image format.

you seem to be on the right track, but if pixel array is unsigned char of an RGB image, it will be broken badly if you flip rows and columns blindly, you have to move 3 bytes at a time in that instance. If its a different type, like 1 byte greyscale, a simple flip will indeed work. Or if pixles is an array of some custom type that encapsulates your pixels, a simple flip will work.
Last edited on
Hi it's a 24bit png image file with a resolution of 344 x 59 pixels.

This is the load part of the code from the imagehandler which is called by the main program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool loadImage(unsigned pixels[WIDTH][HEIGHT], const char* fileName)
{
    bool result;    // Flag used to indicate successful operation

    // Load image file from the directory the application is in
    if( !Image.load(QCoreApplication::applicationDirPath() + "\\" + fileName))
    {
        // If unsuccessful, return false
        result = false;
    }
    else
    {
        // For each row and column ...
        for (int row = 0; row < HEIGHT; row++)
        {
            for (int col = 0; col < WIDTH; col++)
            {
                // Get pixel colour value
                pixels[col][row] = Image.pixel(col, row);
            }
        }
        // Return true to indicate succesful load operation
        result = true;
    }
    return result;
}


and this is code from the main program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    const char LogoFile[] = "Logo.png";

    unsigned PixelGrid[WIDTH][HEIGHT];     // Image loaded from file

    // If the file cannot be loaded ...
    if (!loadImage(PixelGrid, LogoFile))
    {
        // Display an error message
        cout << "Error loading file \"" << LogoFile << "\"" << endl;
    }
    else
    {
        cout << "File \"" << LogoFile << "\" opened successfully" << endl;

        // Demo of use of saveImage - to create a copy as "Logo.png"
        // This should be modified to save the new images as specified
        if (saveImage(PixelGrid, "LogoCopy.png"))
        {
            cout << "File \"LogoCopy.png\" saved successfully" << endl;
        }
        else
        {
            cout << "Could not save \"LogoCopy.png\"" << endl;
        }
    }

     return a.exec();
}


As I said I'm not looking for the answer but just guidance that I am on the right track.

Feedback much appreciated.
Last edited on
try, test, fail, fix, repeat.
ok, so unsigned is storing the rgb values for you, so you can safely swap pixels as a unit. its possible to do it without a second image (by doing it in place in the original), but one easy solution is to copy into a new image from the old one.

that aside I think you are on the right track. Ask if you get into trouble.
Hi jonnin,

Thanks for looking at that, gives me confidence that I'm going in the right direction.
We only started C++ programming a couple of months ago, though I've done bits and bobs prior.
Hello,

Well good news is I have been got my code working to rotate the image.
Now I'm struggling to turn it into a function that works. We have been instructed it has to be a void() function, but I'm cocking something up. Any pointers?

I'm trying to pass the PixelGrid[WIDTH][HEIGHT] to the function but for my function call when I compile I get the following error.

error: invalid conversion from 'unsigned int' to 'unsigned int (*)[59]' [-fpermissive]
rotateImage(PixelGrid[WIDTH][HEIGHT]);

I suspect I have goofed up in some simple way but I just can't see. Pointers appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <QCoreApplication>
#include <iostream>
#include "ImageHandle.h"

using namespace std;

// Declare protoype function for rotating the image
void rotateImage(unsigned PixelGrid[WIDTH][HEIGHT]);

int main(int argc, char *argv[])

{
    QCoreApplication a(argc, argv);
    const char LogoFile[] = "Logo.png";

    unsigned PixelGrid[WIDTH][HEIGHT];     // Image loaded from file


    // If the file cannot be loaded ...
    if (!loadImage(PixelGrid, LogoFile))
    {
        // Display an error message
        cout << "Error loading file \"" << LogoFile << "\"" << endl;
    }
    else
    {
        cout << "File \"" << LogoFile << "\" opened successfully" << endl;

        // Call the function to rotate the image on succesful load
        rotateImage(PixelGrid[WIDTH][HEIGHT]);


        // Save the rotated image in the filename specified
        if (saveImage(PixelGrid, "LogoRotated.png"))
        {
            cout << "File \"LogoRotated.png\" saved successfully" << endl;
        }
        else
        {
            cout << "Could not save \"LogoRotated.png\"" << endl;
        }
    }
    return a.exec();
}

/******************************************************************************
 *
 * Name: rotateImage
 * Parameters: PixelGrid[WIDTH][HEIGHT]
 * Returns: the rmsValue of the waveform
 * Globals: none
 * Description: Rotates the loaded image Logo.png 180 degrees *
 *
 *
 *****************************************************************************/

void rotateImage(unsigned PixelGrid[WIDTH][HEIGHT])
{
    int tempArr[WIDTH][HEIGHT];
    for (int w = 0; w <= WIDTH/2;  w++)
    {
        for (int h = 0; h <=HEIGHT; h++){

            tempArr[WIDTH][HEIGHT]= PixelGrid[w][h];
            PixelGrid[w][h] =  PixelGrid[WIDTH-w][HEIGHT-h];
            PixelGrid[WIDTH-w][HEIGHT-h] = tempArr[WIDTH][HEIGHT];
        }
    }
}
When you declare an array, you use [] to define the size of the array.

However, when using that array, you use [] to specify a particular element of the array.

So, at line 30:

rotateImage(PixelGrid[WIDTH][HEIGHT]);

you are not passing in the whole array, but one single element - that is, an unsigned int.

Well, actually, what you're passing in isn't an element of the array - it's a value read from memory past the end of your array. But it's still a single unsigned int, not an array.
Last edited on
Yes,

This what I'm having the issue with, pulling through the parameter. I'm stuck at how I pull that through.

I know the code in my function works. When it is in main it rotates the image fine.

The function may look like this:

void rotateImage(unsigned (&PixelGrid)[WIDTH][HEIGHT])

That will pass the array as a reference. And you call it like so:

rotateImage(PixelGrid);

Note that only matching arrays can be passed.
Hmmm, it compiles fine, but when it runs I get the console, notification that the image file was opened successfully but then a pop-up informing me Graphics.cpp has crashed.

I've written and called functions before, I'm just struggling to see what I am missing.


If there's a core file, you can analyse it with your debugger.

Otherwise, try running the code in your debugger, and seeing what's happening at the point where it crashes.

If you want us to look at the problem while you do that, please post a minimal, compilable, up-to-date codeset that exhibits the problem.
Actually:
1
2
3
4
5
6
7
8
9
10
11
12
13
void rotateImage(unsigned PixelGrid[WIDTH][HEIGHT])
{
    int tempArr[WIDTH][HEIGHT];
    for (int w = 0; w <= WIDTH/2;  w++)
    {
        for (int h = 0; h <=HEIGHT; h++){

            tempArr[WIDTH][HEIGHT]= PixelGrid[w][h];
            PixelGrid[w][h] =  PixelGrid[WIDTH-w][HEIGHT-h];
            PixelGrid[WIDTH-w][HEIGHT-h] = tempArr[WIDTH][HEIGHT];
        }
    }
}
It seems you have some difficulties to grasp the concept of arrays. See this:

http://www.cplusplus.com/doc/tutorial/arrays/
If I take the width and height out as you have shown, then the program does nothing when it was in main.

Funnily enough as a function it works. Thanks.
Last edited on
Actually when you use WIDTH/HEIGHT as an index they are out of bounds because an array starts with 0 and thus the range is 0...array_size-1. So PixelGrid[WIDTH-w][HEIGHT-h]; is out of bounds as well when w/h are 0.

Out of bounds means undefined behavior which may lead to a crash but it is not predictable what actually happens.
Cheers,

I've worked out the border thing too.
Last edited on
Topic archived. No new replies allowed.