用C ++编写PNG

4
我正在尝试使用Visual Studio Express 2013在Windows 7 64位上使用C++向PNG文件写入数据。我知道需要使用外部库来实现这一点,但是这就是我遇到困难的地方。
我尝试使用LodePNG - 它看起来简单、轻量级且易于使用。问题是,它太简单了,并且似乎需要特定像素格式的数据才能匹配我的数据。我可以修改我的数据使其与LodePNG兼容,但我更愿意使用具有更多灵活性的库,例如libpng。
然而,我对构建或链接库一无所知,而且libpng在这方面被证明是绝对的噩梦。我尝试按照this guide,成功生成了“libpng.lib”和“png.h”,但当我尝试在我的项目中包含这些文件(我将两个文件都放在我的项目目录中,将“png.h”添加到我的头文件并将“libpng.lib”添加到链接器的“附加依赖项”字段中)时,我得到了大量的构建错误,尤其是:
error C1083: Cannot open include file: 'pnglibconf.h': No such file or directory

请问有人可以告诉我如何安装libpng吗?或者给我推荐一份好的指南(我惊讶于缺少相关指南...)或者推荐一个不同的(轻量级、易于安装的)PNG库吗?我已经快疯了。


1
你真的,真的不想直接使用libpng。试试FreeImage,它很容易使用。也许你想看看ImageMagick,它可能已经有你想要做的功能了。 - Cubic
http://msdn.microsoft.com/en-us/library/windows/desktop/ms535407%28v=vs.85%29.aspx - Hans Passant
5
你可以从libpng源代码中的scripts目录中获取pnglibconf.h。在那里命名为pnglibconf.h.prebuilt。 - Ivarpoiss
谢谢,我会查看FreeImage、ImageMagick和GDI+。@Ivarpoiss 我相信我尝试过了,但它抱怨另一个文件(可能是pngconf.h)。 - Dan
1
Ivarpoiss:谢谢你指出这个问题!这对我来说是正确的答案! - Peter Parker
3个回答

10

LodePNG 轻而易举,就像你说的那样。我之前也用过它。以防你改变主意并决定将你拥有的数据编码为正确的格式(假设是 BGRA),下面的代码将把 BGRA 格式转换为 LodePNG 所需的 RGBA 格式。

std::vector<std::uint8_t> PngBuffer(ImageData.size());

for(std::int32_t I = 0; I < Height; ++I)
{
    for(std::int32_t J = 0; J < Width; ++J)
    {
        std::size_t OldPos = (Height - I - 1) * (Width * 4) + 4 * J;
        std::size_t NewPos = I * (Width * 4) + 4 * J;
        PngBuffer[NewPos + 0] = ImageData[OldPos + 2]; //B is offset 2
        PngBuffer[NewPos + 1] = ImageData[OldPos + 1]; //G is offset 1
        PngBuffer[NewPos + 2] = ImageData[OldPos + 0]; //R is offset 0
        PngBuffer[NewPos + 3] = ImageData[OldPos + 3]; //A is offset 3
    }
}

std::vector<std::uint8_t> ImageBuffer;
lodepng::encode(ImageBuffer, PngBuffer, Width, Height);
lodepng::save_file(ImageBuffer, "SomeImage.png");

您也可以直接在原地进行操作:
for(std::int32_t I = 0; I < Height; ++I)
{
    for(std::int32_t J = 0; J < Width; ++J)
    {
        std::size_t OldPos = (Height - I - 1) * (Width * 4) + 4 * J;
        std::size_t NewPos = I * (Width * 4) + 4 * J;
        std::swap(ImageData[NewPos + 0], ImageData[ImageData + 2]);
    }
}

奇怪的是,lodepng文档没有提到这一点。它给人的印象是可以加载任何支持的png格式。 - jiggunjer
1
lodepng 在我的简单使用情况下工作得非常好。 - orion elenzil

4
考虑按照这里的NetPBM/PBMplus格式编写您的文件。 这非常容易,因为文件非常简单,无需库。维基百科文章在这里显示了该格式。

以下是一个简单的示例:

#include <stdio.h>
#include <stdlib.h>

int main(){

   FILE *imageFile;
   int x,y,pixel,height=100,width=256;

   imageFile=fopen("image.pgm","wb");
   if(imageFile==NULL){
      perror("ERROR: Cannot open output file");
      exit(EXIT_FAILURE);
   }

   fprintf(imageFile,"P5\n");           // P5 filetype
   fprintf(imageFile,"%d %d\n",width,height);   // dimensions
   fprintf(imageFile,"255\n");          // Max pixel

   /* Now write a greyscale ramp */
   for(x=0;x<height;x++){
      for(y=0;y<width;y++){
         pixel=y;
         fputc(pixel,imageFile);
      }
   }

   fclose(imageFile);
}

一旦您拥有PBM/PGM格式的文件,可以使用ImageMagick (这里) 通过一个简单的命令将其转换为PNG格式,例如:

convert file.pgm file.png

0

找不到头文件可能是因为您需要指定额外的包含目录来指向libpng的头文件。看起来您可能已经正确地进行了链接。

我已经有一段时间没有在Visual Studios中做过这件事了,但是在项目配置中应该有一个字段可以用来指定此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接