Eva
Eva

Reputation: 33

C - Resize/enlarge image

I just want to say that I'm a novice at C. Alright, with that out of the way, my assignment over Christmas break has been to make a program that manipulates a PNG image in various ways. I've done most of the things, but I've run into a problem when trying to write the program that is supposed to enlarge the image. I have tried and I've gotten something down. Though I'm pretty sure it's all wrong...

    void enlargeImage(Image plain, char *imageInput[])
{

Image tempImage;
Pixel** pixels;

int scale = 2;

pixels = malloc(plain.height * sizeof(Pixel*) *scale);

for (int i = 0; i < plain.height; i++)
{
    pixels[i] = malloc(plain.width * sizeof(Pixel*) * scale);
}

tempImage.pixels = pixels;
tempImage.height = plain.height * scale; //Can I even do this?? Or is it completely wrong? 
tempImage.width = plain.width * scale;

// I've tried a few variations of this code 
for (int height = 0; height < plain.height; height++)
{

    for (int width = 0; width < plain.width; width++)
    {

            tempImage.pixels[height][width] = plain.pixels[height][width];

    }
} 



writeImage(imageInput, &tempImage); //This is a function written by my teachers. This is also where I get an error. I'm suspecting it's because I've doubled the size of tempImage ?? 

free(tempImage.pixels);
}

I'd be super grateful if someone could help me ^^
Thank you!

Upvotes: 2

Views: 6882

Answers (1)

MikeCAT
MikeCAT

Reputation: 75062

1. The allocation should be like this:

tempImage.height = plain.height * scale;
tempImage.width = plain.width * scale;

pixels = malloc(tempImage.height * sizeof(Pixel*));
if (pixels == NULL) return;

for (int i = 0; i < tempImage.height; i++)
{
    pixels[i] = malloc(tempImage.width * sizeof(Pixel));
    if (pixels[i] == NULL)
    {
        for (int j = 0; j < i; j++) free(pixels[j]);
        free(pixels);
        return;
    }
}

tempImage.pixels = pixels;

Points are:

  • Avoid doing pair of multiplications twice by calculating tempImage.height and tempImage.width before doing allocation.
  • Though sizeof(char) is defined to 1 and therefore multiplying it isn't harmful, it seems producing confusion and making reading the program harder.
  • The type of elements of pixels[i] is Pixel. so sizeof(Pixel) should be multiplied instead of sizeof(Pixel*) in the second malloc().
  • Allocate memory for all of the rows. Your program was allocating for only the first half of rows.
  • Return values of malloc() should be checked in order to avoid dereferencing NULL, which is returned from malloc() when it fails, and invoking undefined behavior.

2. The conversion should be like this:

for (int height = 0; height < tempImage.height; height++)
{
    for (int width = 0; width < tempImage.width; width++)
    {
        tempImage.pixels[height][width] = plain.pixels[height / scale][width / scale];
    }
}

Points are:

  • Set values for all pixels of the destination image (tempImage). Initial values of buffer allocated via malloc() is indeterminate and using them will invoke undefined behavior.
  • Be careful not to access (no read nor write) out-of-range of arrays, or you will invoke undefined behavior.

3. You are freeing the list of rows by free(tempImage.pixels);, but you should free the data of each rows by adding

for (int i = 0; i < tempImage.height; i++)
{
    free(tempImage.pixels[i]);
}

just before the line free(tempImage.pixels);. Note that tempImage.pixels and pixels are pointing at the same array, so you don't have to (and must not) use free() for both of them: use free() for only one of them.

4. Not knowing the actual signature of writeImage, convination of

void enlargeImage(Image plain, char *imageInput[])

and

writeImage(imageInput, &tempImage);

looks strange. Are you sure the first argument of writeImage should be a pointer to pointer to characters, not a pointer to characters like char *imageInput?

Upvotes: 2

Related Questions