16位灰度PNG
我正在尝试编写(使用 libpng)一个 16 位灰度图像,其中每个点颜色等于其坐标之和。以下代码应生成 16 位 PNG,但会生成类似 this。为什么?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <png.h>
void save_png(FILE* fp, long int size)
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_bytepp row_pointers;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
return ;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
return ;
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return ;
}
png_set_IHDR(png_ptr, info_ptr,
size, size, // width and height
16, // bit depth
PNG_COLOR_TYPE_GRAY, // color type
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
row_pointers = (png_bytepp)png_malloc(png_ptr,
size*png_sizeof(png_bytep));
for (int i=0; i<size; i++)
row_pointers[i]=NULL;
for (int i=0; i<size; i++)
row_pointers[i]=png_malloc(png_ptr, size*2);
//set row data
for (y = 0; y < size; ++y) {
png_bytep row = row_pointers[y];
for (x = 0; x < size; ++x) {
short color = x+y;
*row++ = (png_byte)(color & 0xFF);
*row++ = (png_byte)(color >> 8);
}
}
/* Actually write the image data. */
png_init_io(png_ptr, fp);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
//png_write_image(png_ptr, row_pointers);
/* Cleanup. */
for (y = 0; y < size; y++) {
png_free(png_ptr, row_pointers[y]);
}
png_free(png_ptr, row_pointers);
png_destroy_write_struct(&png_ptr, &info_ptr);
}
int main()
{
FILE* f;
if((f=fopen("test.png", "wb"))!=NULL)
{
save_png(f, 257);
fclose(f);
}
return 0;
}
I'm trying to write (using libpng) an 16-bit grayscale image where each point color equals to sum of its coordinates. The following code should produce a 16-bit PNG, but instead produces 8-bit like this. Why?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <png.h>
void save_png(FILE* fp, long int size)
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
png_bytepp row_pointers;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
return ;
}
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
png_destroy_write_struct(&png_ptr, NULL);
return ;
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
return ;
}
png_set_IHDR(png_ptr, info_ptr,
size, size, // width and height
16, // bit depth
PNG_COLOR_TYPE_GRAY, // color type
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
row_pointers = (png_bytepp)png_malloc(png_ptr,
size*png_sizeof(png_bytep));
for (int i=0; i<size; i++)
row_pointers[i]=NULL;
for (int i=0; i<size; i++)
row_pointers[i]=png_malloc(png_ptr, size*2);
//set row data
for (y = 0; y < size; ++y) {
png_bytep row = row_pointers[y];
for (x = 0; x < size; ++x) {
short color = x+y;
*row++ = (png_byte)(color & 0xFF);
*row++ = (png_byte)(color >> 8);
}
}
/* Actually write the image data. */
png_init_io(png_ptr, fp);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
//png_write_image(png_ptr, row_pointers);
/* Cleanup. */
for (y = 0; y < size; y++) {
png_free(png_ptr, row_pointers[y]);
}
png_free(png_ptr, row_pointers);
png_destroy_write_struct(&png_ptr, &info_ptr);
}
int main()
{
FILE* f;
if((f=fopen("test.png", "wb"))!=NULL)
{
save_png(f, 257);
fclose(f);
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
链接到的图像在 Windows 7 的“属性”中显示为“16 位”。我想您只是看到各种应用程序回退到转换为 8 位进行显示,这(我猜)是预料之中的,因为大多数显示设备不支持 16 位。
The linked-to image shows as being "16-bit" in Windows 7's "Properties". I guess you're just seeing various applications falling back to converting down to 8-bit for display, which (I guess) is pretty expected since most display devices don't support 16 bits.
很抱歉复活了一个旧线程,但我是在谷歌搜索如何编写 16 位灰度图像后来到这里的。我遇到了类似的问题,我认为发布我如何解决该问题会有所帮助。
TL;DR:
a) 字节必须首先提供给库 MSB,因此如果将上面的行翻转为以下内容,它就可以工作:
b) 要在 8 位屏幕上实际看到 16 位值,任何低于 256 的值只会被剪裁为黑色。实际上,应该使用 256 的几倍数的值来查看任何内容。上面的 color = x + y 代码可能没有产生足够明亮的值。
我是如何得出上述结论的:
我从上面的代码开始,仅使用“x”作为颜色,而不是“x + y”。
目的是让渐变从左侧的黑色淡入右侧的最大 x 值。
然而,我没有得到一个长渐变,而是得到了几个窄渐变。这尖叫着“错误的端序!”
我尝试反转这些位,但后来得到了黑色图像。我花了一段时间才弄清楚,但由于屏幕仅以 8 位显示,即使是最大值(在我的例子中)968 也太暗了。这在 8 位屏幕上映射为 2 或 3,即使使用高伽玛,我也看不出差异。
因为我知道我的最大 X 大约是 1000,并且 16 位值的最大值是 65000 左右,所以我使用 (x * 60) 作为我的颜色。最终产生了明显的结果。
感谢您的原始帖子。这是一个很好的入门示例。
Sorry for resurrecting an old thread, but I got here after googling for how to write 16 bit grayscale images. I ran into similar problems, and I thought it would be helpful to post how I resolved the issue.
TL;DR:
a) The bytes have to be provided to the library MSB first, so it works if you flip the lines above to this:
b) To actually see a 16 bit value on an 8-bit screen, any values under 256 will simply be clipped to black. Practically speaking, values that are several multiples of 256 should be used to see anything at all. The color = x + y code above probably didn't produce values that were bright enough.
How I got to the conclusions above:
I started with the code above, using only 'x' as the color, not 'x + y'.
The intent was to have a gradient that faded in from black on the left to whatever the max x was on the right.
However, instead of having one long gradient, I was getting several narrow gradients instead. This screamed "WRONG ENDIANNESS!"
I tried inverting the bits, but then I got a black image. Took me a while to clue in, but since the screen only displays in 8 bits, even the maximum value of (in my case) 968 was too dark. This maps to 2 or 3 on an 8 bit screen, and even with high gamma I couldn't see the difference.
Since I knew my max X was roughly 1000, and that the max value for a 16 bit value is 65000 ish, so I used (x * 60) as my color. That ended up producing a visible result.
Thanks for the original post. It was an excellent example to get started.
这是期望与现实的问题。创建 PNG16 并在 8 位颜色计算机上使用它,这允许颜色值在 0-255 范围内(1 字节 = 8 位颜色深度)。
PNG16 使用无符号 16 位整数作为颜色代码。
这里任何大于 2^8 = 256 的值都将被简单地剪裁为 255,可能使用 modulo 255 命令。我制作了类似的图像,但具有水平渐变。图像有 1000 个像素,我看到 4 次重复的渐变 (1000 / 255 = 4)。
从图形文件到应用程序到显示器的链中的所有元素都必须具有相同的颜色位。
我已使用 Image Magic HDR16 查看器检查了该文件。它将文件描述
查看器: sstatic.net/11Mwh.png" rel="nofollow noreferrer">
This is expectations versusu reality problem. One creates PNG16 and uses it on the 8-bit color computer, which allows color values to be in the range 0-255 ( 1 byte = 8 bit color depth).
PNG16 uses unsigned 16 bit integers for color codes.
Here any values greater then 2^8 = 256 will simply be clipped to 255, probably using modulo 255 command. I have made similar image, but with horizontal gradient. Image has 1000 pixels and I see 4 repetition of the gradient ( 1000 / 255 = 4).
All elements in the chain from the graphic file thru the application to the monitor must have the same color bits.
I have checked the file with Image Magic HDR16 viewer. It describes