【发布时间】:2016-08-22 01:26:23
【问题描述】:
我正在使用 libpng 和 libjpeg 来读取和写入图像。我使用的代码几乎直接取自两个库文档提供的示例,并且图像加载在两个库中都可以正常工作。但是,当我去保存图像时,出现了问题,并且似乎以某种方式写入了损坏的数据。令人困惑的部分是它使用两个库以完全相同的错误方式编写它。这是一个例子:
原文:
模糊的图片(保存前在程序中的样子):
如何保存(png):
jpeg 版本保存时具有相同的变色,只是压缩程度更高。
这是png保存代码:
void PNGHandler::save(PixelBuffer* buffer, std::string fileName)
{
FILE* filePointer = fopen(fileName.c_str(), "wb");
int width = buffer->getWidth();
int height = buffer->getHeight();
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info = png_create_info_struct(png);
png_init_io(png, filePointer);
// 8-bit depth, RGBA
png_set_IHDR(png, info, width, height, 8,
PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png, info);
// Set up rows for writing from
png_bytep *rowPointers = new png_bytep[height];
for(int y = 0; y < height; y++) {
rowPointers[y] = new png_byte[png_get_rowbytes(png,info)];
}
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
ColorData cd = buffer->getPixel(x, height - y - 1);
rowPointers[y][x*4] = (int)(cd.getRed() * 255);
rowPointers[y][x*4+1] = (int)(cd.getGreen() * 255);
rowPointers[y][x*4+2] = (int)(cd.getBlue() * 255);
rowPointers[y][x*4+3] = (int)(cd.getAlpha() * 255);
}
}
png_write_image(png, rowPointers);
png_write_end(png, info);
delete [] rowPointers;
png_destroy_write_struct(&png, &info);
fclose(filePointer);
}
(我知道现在的错误处理不是很好,但我稍后会修复)
此外,文件始终以这种方式保存。也就是说,我可以应用模糊并保存,然后重新加载原始文件并再次执行,并对两个文件执行diff 显示它们是相同的。传入的PixelBuffer 指针是指向正在屏幕上显示的缓冲区的指针,因此所有颜色数据都应与显示的完全相同。
我知道这不是很多信息,但如果有人可以指导我寻找我应该寻找的东西,我可以带来更多信息(这是一个大型项目,所以我不能发布所有代码)
编辑:还值得注意的是,图像在保存后看起来是正确的,但是一旦加载保存的图像,它就会显示变色。这表明我的保存方法存在问题
【问题讨论】:
-
如果只加载文件并保存(不对像素缓冲区进行任何过滤或更改),也会出现同样的问题?
-
奇怪的是,它没有。从上面加载正确的毛刺照片(或只是未更改的照片)并保存它可以正常工作。也许它对 PixelBuffers 感到困惑,从撤消/重做功能.. 这很有趣
-
您的滤镜/模糊可能会溢出/下溢颜色值。您应该确保值在 0 和 255 之间饱和(如果值低于 0,则将它们设置为 0,如果值高于 255,则将它们设置为 255)
-
太棒了,就是这样。我在
ColorData对象中内置了clampedColor()函数,但未能使用它。将cd.getRed()(以及其他)更改为cd.clampedColor().getRed()修复了它。谢谢! -
将评论复制到答案中,以便您可以标记为已解决