16位灰度png

Posted

技术标签:

【中文标题】16位灰度png【英文标题】:16 bit grayscale png 【发布时间】:2012-02-07 17:54:18 【问题描述】:

我正在尝试(使用 libpng)编写一个 16 位灰度图像,其中每个点的颜色等于其坐标的总和。下面的代码应该生成一个 16 位的 PNG,而是生成 8 位的,例如 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;

【问题讨论】:

示例是什么语言? 【参考方案1】:

链接到的图像在 Windows 7 的“属性”中显示为“16 位”。我猜您只是看到各种应用程序退回到转换为 8 位进行显示,这(我猜)是意料之中的,因为大多数显示设备不支持 16 位。

【讨论】:

Windows 7 显示两个渐变填充三角形。这应该是 16 位图像的正方形和 8 位图像的三角形。 哦,你是对的。我再次使用 libpng 读取图像并测试点的颜色。他们应该是。【参考方案2】:

很抱歉复活了一个旧线程,但我在谷歌搜索如何编写 16 位灰度图像后来到这里。我遇到了类似的问题,我认为发布我如何解决该问题会有所帮助。

TL;DR:

a) 字节必须首先提供给库 MSB,所以如果你将上面的行翻转到这个位置,它就可以工作:

*row++ = (png_byte)(color >> 8);
*row++ = (png_byte)(color & 0xFF);

b) 要在 8 位屏幕上实际看到 16 位值,任何低于 256 的值都将被简单地裁剪为黑色。实际上,应该使用 256 的几个倍数的值来查看任何内容。上面的 color = x + y 代码可能没有产生足够亮的值。

我是如何得出上述结论的:

我从上面的代码开始,只使用'x'作为颜色,而不是'x + y'。

其目的是让渐变从左侧的黑色渐变到右侧的最大 x。

但是,我没有得到一个长渐变,而是得到了几个窄渐变。这尖叫着“错误的字节序!”

我尝试反转位,但随后我得到了一个黑色图像。我花了一段时间才知道,但由于屏幕只显示 8 位,即使(在我的情况下)968 的最大值也太暗了。这在 8 位屏幕上映射到 2 或 3,即使使用高伽马我也看不出区别。

因为我知道我的最大 X 大约是 1000,并且 16 位值的最大值是 65000 ish,所以我使用 (x * 60) 作为我的颜色。这最终产生了可见的结果。

感谢原帖。这是一个很好的入门示例。

【讨论】:

以上是关于16位灰度png的主要内容,如果未能解决你的问题,请参考以下文章

使用 libpng 编写 1 位深度的灰度 PNG 会导致图像不正确

什么是png格式的图片?

16位图像的65536种颜色是指彩色,还是灰度(灰阶)?

如何使用 libpng 库获取 16 位深度的灰度图像的像素值?

pytorch/torchvision处理32位/16位灰度图的坑

LIBTIFF 16位灰度tif图像转成OpenCV中的Mat格式并显示