如何用 libpng 写一个 16 位 PNG_COLOR_TYPE_GRAY?
How to write a 16 bit PNG_COLOR_TYPE_GRAY with libpng?
我编写了以下代码来生成黑白 PNG 图像,其中每个像素的值为 16 位(0 = 黑色,0xFFFF = 白色)。这是一个简单的 640x480 测试图像,其中所有线条都相同,并且左侧的每条线条都有最大的黑色,然后逐渐淡化为右侧的白色。因为每条线都是 640 像素宽,所以我希望看到几乎全黑的图像,右侧的白色最大达到 640/65535。相反,我得到的图像达到纯白色 2 次,与值 0x00ff 和 0x01ff 相对应。这表明 libpng 没有使用每个像素的最高有效字节。
有人可以告诉我哪里错了吗?
总之谢谢大家。
再见
系统和编译详细信息:
系统 MacBook Pro(视网膜,15 英寸,2013 年底)OS X 10.11.6
PNG > gcc --version
配置为:--prefix =/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms /MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
苹果 LLVM 版本 8.0.0 (clang-800.0.42.1)
目标:x86_64-apple-darwin15.6.0
线程模型:posix
安装目录:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
PNG> gcc -I /opt/X11/include/ -L /opt/X11/lib/ -l png -l z writeTest16bit.c
生成的图片(file.png)为:
/* This is the test code upper described */
#include <png.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define ERROR -1
#define GOTO_ERROR {line = __LINE__; goto error;}
#define width 640
#define height 460
#define bit_depth 16
unsigned short int image[height][width];
void setBitMapImageGray (void);
int main (int argc, char **argv)
{
char *pngFileName = "file.png";
FILE *pngFile = NULL;
png_structp pngStruct = NULL;
png_infop pngInfo = NULL;
int line = __LINE__;
int i;
setBitMapImageGray ();
if (NULL == (pngFile = fopen (pngFileName, "wb"))) GOTO_ERROR;
if (NULL == (pngStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) GOTO_ERROR;
if (NULL == (pngInfo = png_create_info_struct (pngStruct))) GOTO_ERROR;
// setting long jump: posponed
png_init_io(pngStruct, pngFile);
png_set_IHDR (pngStruct, pngInfo, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info (pngStruct, pngInfo);
for (i=0; i<height; i++)
png_write_row (pngStruct, (png_const_bytep)&image[i][0]);
png_write_end (pngStruct, NULL);
png_destroy_write_struct (&pngStruct, (png_infopp)NULL);
fclose (pngFile);
return 0;
error:
printf ("Error in line %d\n", line);
if (pngStruct) png_destroy_write_struct (&pngStruct, (png_infopp)NULL);
if (pngFile) fclose (pngFile);
return (ERROR);
}
void setBitMapImageGray (void)
{
int x,y;
unsigned short int const black=0, step=0x10000/width;
for (y=0; y<height; y++)
for (x=0; x<width; x++)
// image[y][x] = 0xFF00;
image[y][x] = x;
}
你几乎是对的 - 它没有忽略高字节,但你有一个字节序问题。
如果您像这样在 png_write_info()
之后添加 png_set_swap()
,您的代码就可以正常工作:
...
png_set_IHDR (pngStruct, pngInfo, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(pngStruct, pngInfo);
png_set_swap(pngStruct); // <--- THIS LINE ADDED
...
关键字: PNG, libpng, 16-bit, 16 bit, greyscale, endian, endianness, byte order, little endian, big-endian, write, image, image processing , C.
我编写了以下代码来生成黑白 PNG 图像,其中每个像素的值为 16 位(0 = 黑色,0xFFFF = 白色)。这是一个简单的 640x480 测试图像,其中所有线条都相同,并且左侧的每条线条都有最大的黑色,然后逐渐淡化为右侧的白色。因为每条线都是 640 像素宽,所以我希望看到几乎全黑的图像,右侧的白色最大达到 640/65535。相反,我得到的图像达到纯白色 2 次,与值 0x00ff 和 0x01ff 相对应。这表明 libpng 没有使用每个像素的最高有效字节。 有人可以告诉我哪里错了吗? 总之谢谢大家。 再见
系统和编译详细信息:
系统 MacBook Pro(视网膜,15 英寸,2013 年底)OS X 10.11.6
PNG > gcc --version
配置为:--prefix =/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms /MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1 苹果 LLVM 版本 8.0.0 (clang-800.0.42.1) 目标:x86_64-apple-darwin15.6.0 线程模型:posix 安装目录:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
PNG> gcc -I /opt/X11/include/ -L /opt/X11/lib/ -l png -l z writeTest16bit.c
生成的图片(file.png)为:
/* This is the test code upper described */
#include <png.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define ERROR -1
#define GOTO_ERROR {line = __LINE__; goto error;}
#define width 640
#define height 460
#define bit_depth 16
unsigned short int image[height][width];
void setBitMapImageGray (void);
int main (int argc, char **argv)
{
char *pngFileName = "file.png";
FILE *pngFile = NULL;
png_structp pngStruct = NULL;
png_infop pngInfo = NULL;
int line = __LINE__;
int i;
setBitMapImageGray ();
if (NULL == (pngFile = fopen (pngFileName, "wb"))) GOTO_ERROR;
if (NULL == (pngStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) GOTO_ERROR;
if (NULL == (pngInfo = png_create_info_struct (pngStruct))) GOTO_ERROR;
// setting long jump: posponed
png_init_io(pngStruct, pngFile);
png_set_IHDR (pngStruct, pngInfo, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info (pngStruct, pngInfo);
for (i=0; i<height; i++)
png_write_row (pngStruct, (png_const_bytep)&image[i][0]);
png_write_end (pngStruct, NULL);
png_destroy_write_struct (&pngStruct, (png_infopp)NULL);
fclose (pngFile);
return 0;
error:
printf ("Error in line %d\n", line);
if (pngStruct) png_destroy_write_struct (&pngStruct, (png_infopp)NULL);
if (pngFile) fclose (pngFile);
return (ERROR);
}
void setBitMapImageGray (void)
{
int x,y;
unsigned short int const black=0, step=0x10000/width;
for (y=0; y<height; y++)
for (x=0; x<width; x++)
// image[y][x] = 0xFF00;
image[y][x] = x;
}
你几乎是对的 - 它没有忽略高字节,但你有一个字节序问题。
如果您像这样在 png_write_info()
之后添加 png_set_swap()
,您的代码就可以正常工作:
...
png_set_IHDR (pngStruct, pngInfo, width, height, bit_depth,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(pngStruct, pngInfo);
png_set_swap(pngStruct); // <--- THIS LINE ADDED
...
关键字: PNG, libpng, 16-bit, 16 bit, greyscale, endian, endianness, byte order, little endian, big-endian, write, image, image processing , C.