在 C 中操作 PNG 图像导致内存泄漏或图像上出现白色条纹
Manipulating a PNG image in C leading to either memory leaks or white stripes on image
我们应该制作一个处理 PNG 图片的程序。其中一个选项是放大图像,使其大小加倍。我们从老师那里得到了一些函数,用于将图像读取和保存到文件中。
// This function reads an image from the filename source. Will store
// the image in the Pixel 2dim array and allocate the needed space.
void readImage(char *filename, Image *img);
// This function actually writes out the PNG image file. The string 'title' is
// also written into the image file
void writeImage(char* filename, Image *img);
这是一个学校项目,但我对编程真的很陌生,几周来我一直盯着这段代码看,没有任何实际进展,如果有人能指出我正确的方向,我将不胜感激。
这是我们正在使用的两个结构,是老师给的。
typedef struct pixel
{
uint8_t r;
uint8_t g;
uint8_t b;
} Pixel;
typedef struct image
{
Pixel **pixels;
unsigned int height;
unsigned int width;
} Image;
一个版本的代码,其中放大功能有效,但存在内存泄漏。
void imageEnlarge(Image *pic)
{
temp.height = plain.height;
temp.width = plain.width;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < plain.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
for (unsigned int w = 0; w < plain.width; w++)
{
temp.pixels[h][w] = plain.pixels[h][w];
}
}
for (unsigned int h = 0; h < plain.width; h++)
{
free(plain.pixels[h]);
}
free(plain.pixels);
plain.height = temp.height * 2;
plain.width = temp.width * 2;
plain.pixels = (Pixel**)malloc(sizeof(Pixel*) * plain.height);
for (unsigned int h = 0; h < plain.height; h++)
{
plain.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * plain.width);
for (unsigned int w = 0; w < plain.width; w++)
{
plain.pixels[h][w] = tempP.pixels[h * tempP.height / plain.height][w * tempP.width / plain.width];
}
}
for (unsigned int h = 0; h < temp.width; h++)
{
free(temp.pixels[h]);
}
free(temp.pixels);
}
另一个版本,其中放大后的图像更大,但整个图像中每两个像素都是白色的,就好像像素的大小增加了一倍但没有完全填满像素。没有内存泄漏!
void imageEnlarge(Image *pic)
{
temp.height = plain.height * 2;
temp.width = plain.width * 2;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < temp.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
}
for (unsigned int h = 0; h < plain.height; h++)
{
for (unsigned int w = 0; w < plain.width; w++)
{
temp.pixels[h * temp.height / plain.height][w * temp.width / plain.width] = plain.pixels[h][w];
}
}
freePixels(&plain);
plain = temp;
您的第二次尝试(使用白色像素)非常接近。这里的问题是,对于输入中的每个像素 (plain),输出中有 four 个像素 (temp) 但你只设置了其中之一。
为确保设置输出中的每个像素,循环遍历 temp 而不是 plain 的高度和宽度并设置每个像素temp 的像素到 plain 的对应像素。这样的事情应该有效:
void imageEnlarge(Image *pic)
{
temp.height = plain.height * 2;
temp.width = plain.width * 2;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < temp.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
}
for (unsigned int h = 0; h < temp.height; h++)
{
for (unsigned int w = 0; w < temp.width; w++)
{
temp.pixels[h][w] = plain.pixels[h * plain.height / temp.height][w * plain.width / temp.width];
}
}
freePixels(&plain);
plain = temp;
}
如果您使用 2 以外的比例因子,这也应该有效。
我们应该制作一个处理 PNG 图片的程序。其中一个选项是放大图像,使其大小加倍。我们从老师那里得到了一些函数,用于将图像读取和保存到文件中。
// This function reads an image from the filename source. Will store
// the image in the Pixel 2dim array and allocate the needed space.
void readImage(char *filename, Image *img);
// This function actually writes out the PNG image file. The string 'title' is
// also written into the image file
void writeImage(char* filename, Image *img);
这是一个学校项目,但我对编程真的很陌生,几周来我一直盯着这段代码看,没有任何实际进展,如果有人能指出我正确的方向,我将不胜感激。
这是我们正在使用的两个结构,是老师给的。
typedef struct pixel
{
uint8_t r;
uint8_t g;
uint8_t b;
} Pixel;
typedef struct image
{
Pixel **pixels;
unsigned int height;
unsigned int width;
} Image;
一个版本的代码,其中放大功能有效,但存在内存泄漏。
void imageEnlarge(Image *pic)
{
temp.height = plain.height;
temp.width = plain.width;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < plain.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
for (unsigned int w = 0; w < plain.width; w++)
{
temp.pixels[h][w] = plain.pixels[h][w];
}
}
for (unsigned int h = 0; h < plain.width; h++)
{
free(plain.pixels[h]);
}
free(plain.pixels);
plain.height = temp.height * 2;
plain.width = temp.width * 2;
plain.pixels = (Pixel**)malloc(sizeof(Pixel*) * plain.height);
for (unsigned int h = 0; h < plain.height; h++)
{
plain.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * plain.width);
for (unsigned int w = 0; w < plain.width; w++)
{
plain.pixels[h][w] = tempP.pixels[h * tempP.height / plain.height][w * tempP.width / plain.width];
}
}
for (unsigned int h = 0; h < temp.width; h++)
{
free(temp.pixels[h]);
}
free(temp.pixels);
}
另一个版本,其中放大后的图像更大,但整个图像中每两个像素都是白色的,就好像像素的大小增加了一倍但没有完全填满像素。没有内存泄漏!
void imageEnlarge(Image *pic)
{
temp.height = plain.height * 2;
temp.width = plain.width * 2;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < temp.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
}
for (unsigned int h = 0; h < plain.height; h++)
{
for (unsigned int w = 0; w < plain.width; w++)
{
temp.pixels[h * temp.height / plain.height][w * temp.width / plain.width] = plain.pixels[h][w];
}
}
freePixels(&plain);
plain = temp;
您的第二次尝试(使用白色像素)非常接近。这里的问题是,对于输入中的每个像素 (plain),输出中有 four 个像素 (temp) 但你只设置了其中之一。
为确保设置输出中的每个像素,循环遍历 temp 而不是 plain 的高度和宽度并设置每个像素temp 的像素到 plain 的对应像素。这样的事情应该有效:
void imageEnlarge(Image *pic)
{
temp.height = plain.height * 2;
temp.width = plain.width * 2;
temp.pixels = (Pixel**)malloc(sizeof(Pixel*) * temp.height);
for (unsigned int h = 0; h < temp.height; h++)
{
temp.pixels[h] = (Pixel*)malloc(sizeof(Pixel) * temp.width);
}
for (unsigned int h = 0; h < temp.height; h++)
{
for (unsigned int w = 0; w < temp.width; w++)
{
temp.pixels[h][w] = plain.pixels[h * plain.height / temp.height][w * plain.width / temp.width];
}
}
freePixels(&plain);
plain = temp;
}
如果您使用 2 以外的比例因子,这也应该有效。