📄 pluginpng.cpp
字号:
} // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) freeimage.set_transparency_table_proc(dib, (BYTE *)trans, num_trans); break; } // DIBs *do* support physical resolution if (png_get_valid(png_ptr,info_ptr,PNG_INFO_pHYs)) { png_uint_32 res_x, res_y; // We'll overload this var and use 0 to mean no phys data, // since if it's not in meters we can't use it anyway int res_unit_type = 0; png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type); if (res_unit_type == 1) { BITMAPINFOHEADER *bih = freeimage.get_info_header_proc(dib); bih->biXPelsPerMeter = res_x; bih->biYPelsPerMeter = res_y; } } // set the individual row_pointers to point at the correct offsets row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); if (!row_pointers) { if (palette) png_free(png_ptr, palette); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); freeimage.free_proc(dib); free(row_pointers); return NULL; } // read in the bitmap bits via the pointer table for (png_uint_32 k = 0; k < height; k++) row_pointers[height - 1 - k] = freeimage.get_scanline_proc(dib, k); png_read_image(png_ptr, row_pointers); // check if the bitmap contains transparency, if so enable it in the header if (freeimage.get_bpp_proc(dib) == 32) if (freeimage.get_color_type_proc(dib) == FIC_RGBALPHA) freeimage.set_transparent_proc(dib, TRUE); else freeimage.set_transparent_proc(dib, FALSE); // cleanup if (row_pointers) free(row_pointers); png_read_end(png_ptr, info_ptr); if (png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return dib; } catch (const char *text) { if (png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (row_pointers) free(row_pointers); if (dib) freeimage.free_proc(dib); freeimage.output_message_proc(s_format_id, text); return NULL; } } return NULL;}static BOOL DLL_CALLCONVSave(FreeImage &freeimage, FreeImageIO &io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr; png_infop info_ptr; png_colorp palette = NULL; png_uint_32 width, height, bpp; BOOL has_alpha_channel = FALSE; RGBQUAD *pal; // pointer to dib palette int bit_depth; int palette_entries; int interlace_type; s_io = &io; s_handle = handle; if ((dib) && (handle)) { try { // create the chunk manage structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)error_handler, error_handler, warning_handler); if (!png_ptr) { return FALSE; } // Allocate/initialize the image information data. info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return FALSE; } // Set error handling. REQUIRED if you aren't supplying your own // error handling functions in the png_create_write_struct() call. if (setjmp(png_jmpbuf(png_ptr))) { // If we get here, we had a problem reading the file png_destroy_write_struct(&png_ptr, &info_ptr); return FALSE; } // init the IO png_set_write_fn(png_ptr, info_ptr, _WriteProc, _FlushProc); // DIBs *do* support physical resolution BITMAPINFOHEADER *bih = freeimage.get_info_header_proc(dib); png_uint_32 res_x = bih->biXPelsPerMeter; png_uint_32 res_y = bih->biYPelsPerMeter; if ((res_x > 0) && (res_y > 0)) { png_set_pHYs(png_ptr, info_ptr, res_x, res_y, 1); } // Set the image information here. Width and height are up to 2^31, // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED width = freeimage.get_width_proc(dib); height = freeimage.get_height_proc(dib); bpp = bit_depth = freeimage.get_bpp_proc(dib); if (bit_depth == 16) { png_destroy_write_struct(&png_ptr, &info_ptr); throw "Format not supported"; // Note: this could be enhanced here... } bit_depth = (bit_depth > 8) ? 8 : bit_depth; interlace_type = PNG_INTERLACE_NONE; // Default value switch (freeimage.get_color_type_proc(dib)) { case FIC_MINISWHITE: // Invert monochrome files to have 0 as black and 1 as white // (no break here) png_set_invert_mono(png_ptr); case FIC_MINISBLACK: png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_GRAY, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); break; case FIC_PALETTE: { png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // set the palette palette_entries = 1 << bit_depth; palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color)); pal = freeimage.get_palette_proc(dib); for (int i = 0; i < palette_entries; i++) { palette[i].red = pal[i].rgbRed; palette[i].green = pal[i].rgbGreen; palette[i].blue = pal[i].rgbBlue; } png_set_PLTE(png_ptr, info_ptr, palette, palette_entries); // You must not free palette here, because png_set_PLTE only makes a link to // the palette that you malloced. Wait until you are about to destroy // the png structure. break; } case FIC_RGBALPHA : if (freeimage.is_transparent_proc(dib)) { has_alpha_channel = TRUE; png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGBA, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_bgr(png_ptr); // flip BGR pixels to RGB break; } // intentionally no break here... case FIC_RGB: png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_bgr(png_ptr); // flip BGR pixels to RGB break; } // Optional gamma chunk is strongly suggested if you have any guess // as to the correct gamma of the image. // png_set_gAMA(png_ptr, info_ptr, gamma); if ((freeimage.get_bpp_proc(dib) == 8) && (freeimage.is_transparent_proc(dib)) && (freeimage.get_transparency_count_proc(dib) > 0)) png_set_tRNS(png_ptr, info_ptr, freeimage.get_transparency_table_proc(dib), freeimage.get_transparency_count_proc(dib), NULL); // Write the file header information. png_write_info(png_ptr, info_ptr); // write out the image data if ((bpp == 32) && (!has_alpha_channel)) { BYTE *buffer = (BYTE *)malloc(width * 3); for (png_uint_32 k = 0; k < height; k++) { freeimage.convert_line_32to24_proc(buffer, freeimage.get_scanline_proc(dib, height - k - 1), width); png_write_row(png_ptr, buffer); } free(buffer); } else { for (png_uint_32 k = 0; k < height; k++) { png_write_row(png_ptr, freeimage.get_scanline_proc(dib, height - k - 1)); } } // It is REQUIRED to call this to finish writing the rest of the file // Bug with png_flush png_write_end(png_ptr, info_ptr); // clean up after the write, and free any memory allocated png_destroy_write_struct(&png_ptr, &info_ptr); if (palette) png_free(png_ptr, palette); return TRUE; } catch (const char *text) { freeimage.output_message_proc(s_format_id, text); } } return FALSE;}// ==========================================================// Init// ==========================================================void DLL_CALLCONVInitPNG(Plugin &plugin, int format_id) { s_format_id = format_id; plugin.format_proc = Format; plugin.description_proc = Description; plugin.extension_proc = Extension; plugin.regexpr_proc = RegExpr; plugin.pagecount_proc = NULL; plugin.pagecapability_proc = NULL; plugin.load_proc = Load; plugin.save_proc = Save; plugin.validate_proc = Validate; plugin.mime_proc = MimeType;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -