📄 png.c
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <png.h>#include "loader.h"#ifdef USE_X11# include "viewer.h"#endifstatic const char *ct[] = { "gray", "X1", "rgb", "palette", "graya", "X5", "rgba", "X7",};struct png_state { FILE *infile; png_structp png; png_infop info; png_bytep image; png_uint_32 w,h; int color_type;};static void*png_init(FILE *fp, char *filename, unsigned int page, struct ida_image_info *i, int thumbnail){ struct png_state *h; int bit_depth, interlace_type; int pass, number_passes; unsigned int y; png_uint_32 resx, resy; png_color_16 *file_bg, my_bg = { .red = 192, .green = 192, .blue = 192, .gray = 192, }; int unit; h = malloc(sizeof(*h)); memset(h,0,sizeof(*h)); h->infile = fp; h->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (NULL == h->png) goto oops; h->info = png_create_info_struct(h->png); if (NULL == h->info) goto oops; png_init_io(h->png, h->infile); png_read_info(h->png, h->info); png_get_IHDR(h->png, h->info, &h->w, &h->h, &bit_depth,&h->color_type,&interlace_type, NULL,NULL); png_get_pHYs(h->png, h->info, &resx, &resy, &unit); i->width = h->w; i->height = h->h; if (PNG_RESOLUTION_METER == unit) i->dpi = res_m_to_inch(resx); if (debug) fprintf(stderr,"png: color_type=%s #1\n",ct[h->color_type]); i->npages = 1; png_set_packing(h->png); if (bit_depth == 16) png_set_strip_16(h->png); if (h->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(h->png); if (h->color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(h->png); if (png_get_bKGD(h->png, h->info, &file_bg)) { png_set_background(h->png,file_bg,PNG_BACKGROUND_GAMMA_FILE,1,1.0); } else { png_set_background(h->png,&my_bg,PNG_BACKGROUND_GAMMA_SCREEN,0,1.0); } number_passes = png_set_interlace_handling(h->png); png_read_update_info(h->png, h->info); h->color_type = png_get_color_type(h->png, h->info); if (debug) fprintf(stderr,"png: color_type=%s #2\n",ct[h->color_type]); h->image = malloc(i->width * i->height * 4); for (pass = 0; pass < number_passes-1; pass++) { if (debug) fprintf(stderr,"png: pass #%d\n",pass); for (y = 0; y < i->height; y++) { png_bytep row = h->image + y * i->width * 4; png_read_rows(h->png, &row, NULL, 1); } } return h; oops: if (h->image) free(h->image); if (h->png) png_destroy_read_struct(&h->png, NULL, NULL); fclose(h->infile); free(h); return NULL;}static voidpng_read(unsigned char *dst, unsigned int line, void *data){ struct png_state *h = data; png_bytep row = h->image + line * h->w * 4; switch (h->color_type) { case PNG_COLOR_TYPE_GRAY: png_read_rows(h->png, &row, NULL, 1); load_gray(dst,row,h->w); break; case PNG_COLOR_TYPE_RGB: png_read_rows(h->png, &row, NULL, 1); memcpy(dst,row,3*h->w); break; case PNG_COLOR_TYPE_RGB_ALPHA: png_read_rows(h->png, &row, NULL, 1); load_rgba(dst,row,h->w); break; case PNG_COLOR_TYPE_GRAY_ALPHA: png_read_rows(h->png, &row, NULL, 1); load_graya(dst,row,h->w); break; default: /* shouldn't happen */ fprintf(stderr,"Oops: %s:%d\n",__FILE__,__LINE__); exit(1); }}static voidpng_done(void *data){ struct png_state *h = data; free(h->image); png_destroy_read_struct(&h->png, &h->info, NULL); fclose(h->infile); free(h);}static struct ida_loader png_loader = { magic: "\x89PNG", moff: 0, mlen: 4, name: "libpng", init: png_init, read: png_read, done: png_done,};static void __init init_rd(void){ load_register(&png_loader);}#ifdef USE_X11/* ---------------------------------------------------------------------- *//* save */static intpng_write(FILE *fp, struct ida_image *img){ png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row; unsigned int y; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (png_ptr == NULL) goto oops; /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) goto oops; if (setjmp(png_jmpbuf(png_ptr))) goto oops; png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, img->i.width, img->i.height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (img->i.dpi) { png_set_pHYs(png_ptr, info_ptr, res_inch_to_m(img->i.dpi), res_inch_to_m(img->i.dpi), PNG_RESOLUTION_METER); } png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); for (y = 0; y < img->i.height; y++) { row = img->data + y * 3 * img->i.width; png_write_rows(png_ptr, &row, 1); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; oops: fprintf(stderr,"can't save image: libpng error\n"); if (png_ptr) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return -1;}static struct ida_writer png_writer = { label: "PNG", ext: { "png", NULL}, write: png_write,};static void __init init_wr(void){ write_register(&png_writer);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -