C 如何使用选项板设置libpng背景透明度?

C 如何使用选项板设置libpng背景透明度?,c,libpng,C,Libpng,我对libpng的基本概念缺乏理解,所以请容忍我。我有以下源代码: #include <png.h> #include <stdio.h> #include <stdint.h> void cb() { printf("callbacked\n"); } // write row void wr_cb (png_structp png_ptr, png_uint_32 row, int pass) { //printf("wr cb"); } int mai

我对libpng的基本概念缺乏理解,所以请容忍我。我有以下源代码:

#include <png.h>
#include <stdio.h>
#include <stdint.h>
void cb() { printf("callbacked\n"); }
// write row
void wr_cb (png_structp png_ptr, png_uint_32 row, int pass) { 
//printf("wr cb");
}
int main(){

        FILE *fp = fopen("pic.png", "wb");
        png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) cb, cb, cb);
        png_infop info_ptr = png_create_info_struct(png_ptr);
        png_color* palette = (png_color*) png_malloc(png_ptr, 2*sizeof(png_color));
        png_bytep* row_pointers;

        png_color_16 bgcolor;
        bgcolor.red = 255;
        bgcolor.green =255;
        bgcolor.blue = 255;
        //palette[]

        png_color *c1 = &palette[0];
        png_color *c2 = &palette[1];
        c1->red=255; c1->green=255; c1->blue=255;
        c2->red=0;   c2->green= 0;  c2->blue= 0;

        if (setjmp(png_jmpbuf(png_ptr))){
                png_destroy_write_struct(&png_ptr, &info_ptr);
                fclose(fp);
                printf("error: destroyed all\n");
        }
        png_init_io(png_ptr, fp);
        png_set_write_status_fn(png_ptr, wr_cb);
        png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
        png_set_IHDR(png_ptr, info_ptr, 500, 500, 1, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
        png_set_PLTE(png_ptr,info_ptr, palette, 2);
        png_write_info(png_ptr, info_ptr);


        row_pointers = (png_bytep*) malloc(500*sizeof(png_bytep));
        for (size_t l = 0; l < 500; l ++){ 
                row_pointers[l]= (png_byte*) malloc( png_get_rowbytes(png_ptr, info_ptr));
                //png_get_rowbytes(png_ptr, info_ptr) -> gives 63
                if (l==10)
                for (size_t k = 0; k < 70; k++){// NOTE_HERE
                        row_pointers[l][k] =150; // 255 - draws a line
                }
        }

        png_set_background(png_ptr, c2, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1);
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        png_free(png_ptr, palette);

}
#包括
#包括
#包括
void cb(){printf(“callbacked\n”);}
//写行
void wr_cb(png_structp png_ptr,png_uint_32行,int pass){
//printf(“wr cb”);
}
int main(){
文件*fp=fopen(“pic.png”、“wb”);
png_structp png_ptr=png_create_write_struct(png_LIBPNG_VER_STRING,(png_voidp)cb,cb,cb);
png_infop info_ptr=png_create_info_struct(png_ptr);
png_color*调色板=(png_color*)png_malloc(png_ptr,2*sizeof(png_color));
png_字节*行指针;
png_color_16 bgcolor;
bgcolor.red=255;
bgcolor.green=255;
bgcolor.blue=255;
//调色板[]
png_color*c1=&调色板[0];
png_color*c2=&调色板[1];
c1->红色=255;c1->绿色=255;c1->蓝色=255;
c2->红色=0;c2->绿色=0;c2->蓝色=0;
if(setjmp(png_jmpbuf(png_ptr))){
png_destroy_write_struct(&png_ptr和&info_ptr);
fclose(fp);
printf(“错误:已销毁所有\n”);
}
png_init_io(png_ptr,fp);
png设置写入状态(png ptr、wr cb);
png设置压缩级别(png ptr、Z最佳压缩);
png\u设置\u IHDR(png\u ptr、info\u ptr、500、500、1、png\u颜色类型\u调色板、png\u交错\u无、png\u压缩类型\u默认、png\u过滤器类型\u默认);
png_集_PLTE(png_ptr,信息_ptr,调色板,2);
png_write_info(png_ptr,info_ptr);
行指针=(png_bytep*)malloc(500*sizeof(png_bytep));
对于(size_t l=0;l<500;l++){
行指针[l]=(png_字节*)malloc(png_get_行字节(png_ptr,info_ptr));
//png_get_rowbytes(png_ptr,info_ptr)->给出63
如果(l==10)
对于(大小k=0;k<70;k++){//NOTE\u
行指针[l][k]=150;//255-画一条线
}
}
png_设置_背景(png_ptr,c2,png_背景_GAMMA_屏幕,0,1);
png_写入_图像(png_ptr,行指针);
png_write_end(png_ptr,info_ptr);
png_destroy_write_struct(&png_ptr和&info_ptr);
png_免费(png_ptr,调色板);
}
我用gcc thefile.c-lpng-opng\u生成器编译它 运行png_maker会显示以下图像:

我使用PNG_颜色_类型_调色板,因为我希望只使用两种颜色-我的假设是使用调色板将生成比不使用调色板更小的PNG文件-因为在我的用例中,我在图片中只需要两种像素颜色:黑色或白色/透明-这一假设正确吗

3个问题:

  • 从图中可以看到顶部有一条黑色虚线。然而,没有透明度
  • 在第二个for循环中(在代码中查找“NOTE_HERE”)。我正在检查k是否小于70(用于测试的硬编码数字,因为给它更大的数字会得到SIGSEGV)。png_字节是无符号字符的typedef。所以我猜png_get_row_bytes给它63个字节,我猜现在它用1位表示1个像素?如果是,如何设置
  • 如何在某个点将调色板中的颜色指定给像素

  • 嗯,我的设置代码和你的非常相似。我使用
    png\u write\u row
    一次写入图像行,但是它应该与
    png\u write\u image
    非常相似

    #include <stdio.h>
    #include <stdlib.h>
    #include <png.h>
    
    int main(){
      png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
      if (!png_ptr) {
        exit (EXIT_FAILURE);
      }
    
      png_infop info_ptr = png_create_info_struct(png_ptr);
    
      if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, NULL);
        exit (EXIT_FAILURE);
      }
    
      if(setjmp(png_jmpbuf(png_ptr))){
        printf ("PNG error\n");
        exit(EXIT_FAILURE);
      }
    
      FILE * fp = fopen("foo.png", "wb");
      if(fp==NULL){
        perror("opening output file");
        exit (EXIT_FAILURE);
      }
      png_init_io(png_ptr, fp);
    
    
      int width=100, height=100;
    
      png_set_IHDR(png_ptr,
               info_ptr,
               width,
               height,
               8, // bit_depth,
               PNG_COLOR_TYPE_PALETTE,
               PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_BASE,
               PNG_FILTER_TYPE_BASE);
    
      png_color palette[] = {
        {0,0,0}, {100,0,0} 
      };
    
      png_set_PLTE(png_ptr, info_ptr, palette, 2);
    
      png_byte trans[] = {255, 128}; // entry 0 opaque, entry 1 half alpha
      png_set_tRNS(png_ptr, info_ptr, trans, 2, NULL);
    
      png_write_info(png_ptr, info_ptr);
    
      // write the image data, row by row
      for (int y=0; y<height; y++) {
        png_byte row[width];
    
        for (int x = 0; x < width; x++){
          row[x] = ((50-x)*(50-x) + (50-y)*(50-y)) < (50*50); // circle
        }
    
        png_write_row(png_ptr, row);
      }
    
      png_write_end(png_ptr, NULL);
    
      png_destroy_write_struct(&png_ptr, &info_ptr);
    
      png_free(png_ptr, palette);
      return 0;
    }
    
    #包括
    #包括
    #包括
    int main(){
    png_structp png_ptr=png_create_write_struct(png_LIBPNG_VER_STRING,NULL,NULL,NULL);
    如果(!png_ptr){
    退出(退出失败);
    }
    png_infop info_ptr=png_create_info_struct(png_ptr);
    如果(!info_ptr){
    png_destroy_write_struct(&png_ptr,NULL);
    退出(退出失败);
    }
    if(setjmp(png_jmpbuf(png_ptr))){
    printf(“PNG错误\n”);
    退出(退出失败);
    }
    文件*fp=fopen(“foo.png”、“wb”);
    如果(fp==NULL){
    perror(“打开输出文件”);
    退出(退出失败);
    }
    png_init_io(png_ptr,fp);
    内部宽度=100,高度=100;
    png\U set\U IHDR(png\U ptr,
    信息,
    宽度,
    高度,
    8,//位深度,
    PNG_颜色_类型_调色板,
    PNG\u交错\u无,
    PNG_压缩_类型_基础,
    PNG_过滤器_类型_底座);
    png_调色板[]={
    {0,0,0}, {100,0,0} 
    };
    png_集_PLTE(png_ptr,信息_ptr,调色板,2);
    png_byte trans[]={255,128};//条目0不透明,条目1半字母
    png_集_tRNS(png_ptr,info_ptr,trans,2,NULL);
    png_write_info(png_ptr,info_ptr);
    //逐行写入图像数据
    
    对于(int y=0;我接受了你的答案,因为它给了我一些工作的依据。但是从你的代码中,我看到你在做
    行[x]=0或1
    -表示有颜色的像素,而1、0表示透明。如何从调色板中为像素提供有关颜色的数据?您的代码使用的是正确的颜色,但为什么?
    行[x]=0或1
    表示使用调色板条目
    0
    1
    ,其颜色和透明度决定像素的颜色和透明度。我关于设置条目透明度的代码很差-我已经替换了关于trans的两行,这两行应该更清晰。特定调色板条目的颜色在e
    palette
    array:
    png_调色板[]={{0,0,0}、{100,0,0};#黑色、红色
    适用于可能遇到相同问题的人。根据规范,如果你对颜色使用palette,你就必须使用TRN来实现透明度。“PNG规范禁止对基于调色板的图像使用完整的alpha通道,但它确实允许通过透明块tRNS使用‘廉价alpha’。”