📄 image_io_png.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: image_io_png.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:41:37 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5 * PRODUCTION * =========================================================================== *//* $Id: image_io_png.cpp,v 1000.3 2004/06/01 19:41:37 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Mike DiCuccio * * File Description: * CImageIOPng -- interface class for reading/writing PNG files */#include <ncbi_pch.hpp>#include "image_io_png.hpp"#include <util/image/image.hpp>#include <util/image/image_exception.hpp>#ifdef HAVE_LIBPNG////// PNG SUPPORT////// libpng main header#include <png.h>BEGIN_NCBI_SCOPE//// internal message handler for PNG images//static void s_PngReadErrorHandler(png_structp png_ptr, png_const_charp msg){ string str("Error reading PNG file: "); str += msg; NCBI_THROW(CImageException, eReadError, str);}//// internal message handler for PNG images//static void s_PngWriteErrorHandler(png_structp png_ptr, png_const_charp msg){ string str("Error writing PNG file: "); str += msg; NCBI_THROW(CImageException, eWriteError, str);}//// internal handler: translate PNG warnings to NCBI warnings//static void s_PngWarningHandler(png_structp png_ptr, png_const_charp msg){ LOG_POST(Warning << "Warning in PNG file: " << msg);}//// initialize PNG reading//static void s_PngReadInit(png_structp& png_ptr, png_infop& info_ptr, png_infop& end_info_ptr){ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, s_PngReadErrorHandler, s_PngWarningHandler); if ( !png_ptr ) { NCBI_THROW(CImageException, eReadError, "CImageIOPng::ReadImage(): png_create_read_struct() failed"); } info_ptr = png_create_info_struct(png_ptr); if ( !info_ptr ) { NCBI_THROW(CImageException, eReadError, "CImageIOPng::ReadImage(): png_create_info_struct() failed"); } end_info_ptr = png_create_info_struct(png_ptr); if ( !end_info_ptr ) { NCBI_THROW(CImageException, eReadError, "CImageIOPng::ReadImage(): png_create_info_struct() failed"); }}//// initialize PNG writing//static void s_PngWriteInit(png_structp& png_ptr, png_infop& info_ptr, const CImage& image, CImageIO::ECompress compress){ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, s_PngWriteErrorHandler, s_PngWarningHandler); if ( !png_ptr ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): png_create_read_struct() failed"); } info_ptr = png_create_info_struct(png_ptr); if ( !info_ptr ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): png_create_info_struct() failed"); } png_byte color_type = PNG_COLOR_TYPE_RGB; if (image.GetDepth() == 4) { color_type = PNG_COLOR_TYPE_RGBA; } png_set_IHDR(png_ptr, info_ptr, image.GetWidth(), image.GetHeight(), 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // set our compression quality switch (compress) { case CImageIO::eCompress_None: png_set_compression_level(png_ptr, Z_NO_COMPRESSION); break; case CImageIO::eCompress_Low: png_set_compression_level(png_ptr, Z_BEST_SPEED); break; case CImageIO::eCompress_Medium: png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); break; case CImageIO::eCompress_High: png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); break; default: LOG_POST(Error << "unknown compression type: " << (int)compress); break; }}//// validate our input//static void s_PngReadValidate(png_structp png_ptr, png_infop info_ptr, size_t& width, size_t& height, size_t& depth, size_t& x, size_t& y, size_t& w, size_t& h){ // store and validate our image's parameters width = info_ptr->width; height = info_ptr->height; depth = info_ptr->channels; png_byte color_type = info_ptr->color_type; png_byte bit_depth = info_ptr->bit_depth; // we support only RGB and RGBA images if ( color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA ) { string msg("CImageIOPng::ReadImage(): unhandled color type: "); msg += NStr::IntToString((int)color_type); NCBI_THROW(CImageException, eReadError, msg); } // ...and only with a bit depth of 8 if (bit_depth != 8) { string msg("CImageIOPng::ReadImage(): unhandled bit depth: "); msg += NStr::IntToString((int)bit_depth); NCBI_THROW(CImageException, eReadError, msg); } // this goes along with RGB or RGBA if (depth != 3 && depth != 4) { string msg("CImageIOPng::ReadImage(): unhandled image channels: "); msg += NStr::IntToString((int)depth); NCBI_THROW(CImageException, eReadError, msg); } if (x != -1 && y != -1 && w != -1 && h != -1) { // further validation: make sure we're actually on the image if (x >= width || y >= height) { string msg("CImageIOPng::ReadImage(): invalid starting position: "); msg += NStr::IntToString(x); msg += ", "; msg += NStr::IntToString(y); NCBI_THROW(CImageException, eReadError, msg); } // clamp our width and height to the image size if (x + w >= width) { w = width - x; LOG_POST(Warning << "CImageIOPng::ReadImage(): clamped width to " << w); } if (y + h >= height) { h = height - y; LOG_POST(Warning << "CImageIOPng::ReadImage(): clamped height to " << h); } } png_read_update_info(png_ptr, info_ptr);}//// our local i/o handlers//static void s_PngRead(png_structp png_ptr, png_bytep data, png_size_t len){ CNcbiIfstream* istr = reinterpret_cast<CNcbiIfstream*>(png_get_io_ptr(png_ptr)); if (istr) { istr->read(reinterpret_cast<char*>(data), len); }}static void s_PngWrite(png_structp png_ptr, png_bytep data, png_size_t len){ CNcbiOfstream* ostr = reinterpret_cast<CNcbiOfstream*>(png_get_io_ptr(png_ptr)); if (ostr) { ostr->write(reinterpret_cast<char*>(data), len); }}static void s_PngFlush(png_structp png_ptr){ CNcbiOfstream* ostr = reinterpret_cast<CNcbiOfstream*>(png_get_io_ptr(png_ptr)); if (ostr) { ostr->flush(); }}//// finalize our structures//static void s_PngReadFinalize(png_structp& png_ptr, png_infop& info_ptr, png_infop& end_info_ptr){ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);}static void s_PngWriteFinalize(png_structp& png_ptr, png_infop& info_ptr){ png_destroy_write_struct(&png_ptr, &info_ptr);}//// ReadImage()// read a PNG format image into memory, returning the image itself// This version reads the entire image//CImage* CImageIOPng::ReadImage(CNcbiIstream& istr){ png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_infop end_ptr = NULL; CRef<CImage> image; try { // create our PNG structures s_PngReadInit(png_ptr, info_ptr, end_ptr); // begin reading our image png_set_read_fn(png_ptr, &istr, s_PngRead); png_read_info(png_ptr, info_ptr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -