• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
比尔教授的学习之家
博客园    首页    新随笔    联系   管理    订阅  订阅

利用libpng中的函数读写png文件【转】

以下是读取png图片文件的代码: 

  1 #include <stdio.h>
  2 #include <png.h> 
  3 #include <stdlib.h>
  4 /******************************图片数据*********************************/
  5 typedef struct _pic_data pic_data;
  6 struct _pic_data
  7 {
  8  int width, height; /* 尺寸 */
  9  int bit_depth;  /* 位深 */
 10  int flag;   /* 一个标志,表示是否有alpha通道 */
 11 
 12  unsigned char **rgba; /* 图片数组 */
 13 };
 14 /**********************************************************************/
 15 #define PNG_BYTES_TO_CHECK 4
 16 #define HAVE_ALPHA 1
 17 #define NO_ALPHA 0
 18 
 19 
 20 int detect_png(char *filepath, pic_data *out)
 21 /* 用于解码png图片 */
 22 {
 23  FILE *pic_fp;
 24  pic_fp = fopen(filepath, "rb");
 25  if(pic_fp == NULL) /* 文件打开失败 */
 26   return -1;
 27  
 28  /* 初始化各种结构 */
 29  png_structp png_ptr;
 30  png_infop   info_ptr;
 31  char        buf[PNG_BYTES_TO_CHECK];
 32  int         temp;
 33  
 34  png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
 35  info_ptr = png_create_info_struct(png_ptr);
 36  
 37  setjmp(png_jmpbuf(png_ptr)); // 这句很重要
 38  
 39  temp = fread(buf,1,PNG_BYTES_TO_CHECK,pic_fp);
 40  temp = png_sig_cmp((void*)buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
 41  
 42  /*检测是否为png文件*/
 43  if (temp!=0) return 1;
 44  
 45  rewind(pic_fp);
 46  /*开始读文件*/
 47  png_init_io(png_ptr, pic_fp);
 48  // 读文件了
 49  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
 50 
 51  int color_type,channels;
 52  
 53  /*获取宽度,高度,位深,颜色类型*/
 54  channels       = png_get_channels(png_ptr, info_ptr); /*获取通道数*/
 55  out->bit_depth = png_get_bit_depth(png_ptr, info_ptr); /* 获取位深 */
 56  color_type     = png_get_color_type(png_ptr, info_ptr); /*颜色类型*/
 57  
 58  int i,j;
 59  int size, pos = 0;
 60  /* row_pointers里边就是rgba数据 */
 61  png_bytep* row_pointers;
 62  row_pointers = png_get_rows(png_ptr, info_ptr);
 63  out->width = png_get_image_width(png_ptr, info_ptr);
 64  out->height = png_get_image_height(png_ptr, info_ptr);
 65  
 66  size = out->width * out->height; /* 计算图片的总像素点数量 */ 
 67 
 68  if(channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
 69  {/*如果是RGB+alpha通道,或者RGB+其它字节*/ 
 70   size *= (4*sizeof(unsigned char)); /* 每个像素点占4个字节内存 */
 71   out->flag = HAVE_ALPHA;    /* 标记 */
 72   out->rgba = (unsigned char**) malloc(size);
 73   if(out->rgba == NULL)
 74   {/* 如果分配内存失败 */
 75    fclose(pic_fp);
 76    puts("错误(png):无法分配足够的内存供存储数据!");
 77    return 1;
 78   }
 79 
 80   temp = (4 * out->width);/* 每行有4 * out->width个字节 */
 81   for(i = 0; i < out->height; i++)
 82   {
 83    for(j = 0; j < temp; j += 4)
 84    {/* 一个字节一个字节的赋值 */
 85     out->rgba[0][pos] = row_pointers[i][j]; // red
 86     out->rgba[1][pos] = row_pointers[i][j+1]; // green
 87     out->rgba[2][pos] = row_pointers[i][j+2];   // blue
 88     out->rgba[3][pos] = row_pointers[i][j+3]; // alpha
 89     ++pos;
 90    }
 91   }
 92  }
 93  else if(channels == 3 || color_type == PNG_COLOR_TYPE_RGB)
 94  {/* 如果是RGB通道 */
 95   size *= (3*sizeof(unsigned char)); /* 每个像素点占3个字节内存 */
 96   out->flag = NO_ALPHA;    /* 标记 */
 97   out->rgba = (unsigned char**) malloc(size);
 98   if(out->rgba == NULL)
 99   {/* 如果分配内存失败 */
100    fclose(pic_fp);
101    puts("错误(png):无法分配足够的内存供存储数据!");
102    return 1;
103   }
104 
105   temp = (3 * out->width);/* 每行有3 * out->width个字节 */
106   for(i = 0; i < out->height; i++)
107   {
108    for(j = 0; j < temp; j += 3)
109    {/* 一个字节一个字节的赋值 */
110     out->rgba[0][pos] = row_pointers[i][j]; // red
111     out->rgba[1][pos] = row_pointers[i][j+1]; // green
112     out->rgba[2][pos] = row_pointers[i][j+2];   // blue
113     ++pos;
114    }
115   }
116  }
117  else return 1;
118  
119  /* 撤销数据占用的内存 */
120  png_destroy_read_struct(&png_ptr, &info_ptr, 0); 
121  return 0;
122 }

以下是生成png图片文件的代码:

 

 1 int write_png_file(char *file_name , pic_data *graph)
 2 /* 功能:将LCUI_Graph结构中的数据写入至png文件 */
 3 {
 4  int j, i, temp, pos;
 5  png_byte color_type; 
 6 
 7  png_structp png_ptr;
 8  png_infop info_ptr; 
 9  png_bytep * row_pointers;
10  /* create file */
11  FILE *fp = fopen(file_name, "wb");
12  if (!fp)
13  {
14   printf("[write_png_file] File %s could not be opened for writing", file_name);
15   return -1;
16  }
17 
18 
19  /* initialize stuff */
20  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
21 
22  if (!png_ptr)
23  {
24   printf("[write_png_file] png_create_write_struct failed");
25   return -1;
26  }
27  info_ptr = png_create_info_struct(png_ptr);
28  if (!info_ptr)
29  {
30   printf("[write_png_file] png_create_info_struct failed");
31   return -1;
32  }
33  if (setjmp(png_jmpbuf(png_ptr)))
34  {
35   printf("[write_png_file] Error during init_io");
36   return -1;
37  }
38  png_init_io(png_ptr, fp);
39 
40 
41  /* write header */
42  if (setjmp(png_jmpbuf(png_ptr)))
43  {
44   printf("[write_png_file] Error during writing header");
45   return -1;
46  }
47  /* 判断要写入至文件的图片数据是否有透明度,来选择色彩类型 */
48  if(graph->flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
49  else color_type = PNG_COLOR_TYPE_RGB;
50  
51  png_set_IHDR(png_ptr, info_ptr, graph->width, graph->height,
52   graph->bit_depth, color_type, PNG_INTERLACE_NONE,
53   PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
54 
55  png_write_info(png_ptr, info_ptr);
56 
57 
58  /* write bytes */
59  if (setjmp(png_jmpbuf(png_ptr)))
60  {
61   printf("[write_png_file] Error during writing bytes");
62   return -1;
63  }
64  if(graph->flag == HAVE_ALPHA) temp = (4 * graph->width);
65  else temp = (3 * graph->width);
66  
67  pos = 0;
68  row_pointers = (png_bytep*)malloc(graph->height*sizeof(png_bytep));
69  for(i = 0; i < graph->height; i++)
70  {
71   row_pointers[i] = (png_bytep)malloc(sizeof(unsigned char)*temp);
72   for(j = 0; j < temp; j += 4)
73   {
74    row_pointers[i][j]   = graph->rgba[0][pos]; // red
75    row_pointers[i][j+1] = graph->rgba[1][pos]; // green
76    row_pointers[i][j+2] = graph->rgba[2][pos];   // blue
77    if(graph->flag == HAVE_ALPHA) 
78     row_pointers[i][j+3] = graph->rgba[3][pos]; // alpha
79    ++pos;
80   }
81  }
82  png_write_image(png_ptr, row_pointers);
83 
84  /* end write */
85  if (setjmp(png_jmpbuf(png_ptr)))
86  {
87   printf("[write_png_file] Error during end of write");
88   return -1;
89  }
90  png_write_end(png_ptr, NULL);
91 
92     /* cleanup heap allocation */
93  for (j=0; j<graph->height; j++)
94   free(row_pointers[j]);
95  free(row_pointers);
96 
97     fclose(fp);
98     return 0;
99 }

 

 

 

posted @ 2014-07-08 13:31  比尔教授  阅读(1435)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3