这个用了好多次了,在blog上记录一下吧 int SavePng(const string &png_file_name, byte **data, int width, int height, int bit_depth, png_colorp palette, int palette_len) { png_structp png_ptr; png_infop info_ptr; FILE *png_file = fopen(png_file_name.c_str(), "wb"); assert(png_file); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == NULL) { cerr<<"ERROR:png_create_write_struct/n"; return 0; } info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { cerr<<"ERROR:png_create_info_struct/n"; png_destroy_write_struct(&png_ptr, NULL); return 0; } png_init_io(png_ptr, png_file); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_PLTE(png_ptr, info_ptr, palette, palette_len); png_write_info(png_ptr, info_ptr); //这里就是图像数据了 png_bytepp row_pointers = new png_bytep[height]; for (int i=0; i<height; ++i) { row_pointers[i] = (png_bytep)data[i]; } png_write_image(png_ptr, row_pointers); delete row_pointers; png_write_end(png_ptr, info_ptr); png_free(png_ptr, palette); palette=NULL; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(png_file); return 0; } void ReadPng(const string &png_file, byte *buf, byte real_bit_dep) { FILE *file = fopen(png_file.c_str(), "rb"); assert(file); // create read struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(png_ptr); // create info struct png_infop info_ptr = png_create_info_struct(png_ptr); assert(info_ptr); // I/O initialization using standard C streams png_init_io(png_ptr, file); // read entire image , ignore alpha channel png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY|PNG_TRANSFORM_STRIP_ALPHA, NULL); int width = info_ptr->width; int height = info_ptr->height; int color_type = info_ptr->color_type; int bit_dep = info_ptr->pixel_depth; //这里要注意任何小于8bpp的图像被ps打开后都会被默认保存成8bpp的格式 if (bit_dep < 8) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); fclose(file); return; } uint line_bytes = (uint)(width*bit_dep/8.0); printf("%d %d %d line_bytes=%d/n", width, height, bit_dep, line_bytes); //read pic data png_bytep* row_pointers = png_get_rows(png_ptr,info_ptr); uint real_line_bytes = (uint)(width*real_bit_dep/8.0); byte* real_ptr = new byte[real_line_bytes]; //write data to buf uint buf_offset = 0; printf("real_bit_dep = %d/n", real_bit_dep); for (int i=0; i<height; ++i) { //2bpp的情况 if (real_bit_dep == 2) { for (uint j=0, t=0; j<real_line_bytes; ++j, t+=4) { real_ptr[j] = ((row_pointers[i][t+3]&0x3)<<6) | ((row_pointers[i][t+2]&0x3)<<4) | ((row_pointers[i][t+1]&0x3)<<2) | (row_pointers[i][t]&0x3); } } //4bpp的情况 else if (real_bit_dep == 4) { for (uint j=0, t=0; j<real_line_bytes; ++j, t+=2) real_ptr[j] = ((row_pointers[i][t+1]&0xF) << 4) | (row_pointers[i][t]&0xF); } memcpy(&buf[buf_offset], real_ptr, real_line_bytes); buf_offset += real_line_bytes; } // free memory png_destroy_read_struct(&png_ptr, &info_ptr, 0); // close file fclose(file); }