📄 image_io_png.cpp
字号:
// store and validate our image's parameters size_t width = 0; size_t height = 0; size_t depth = 0; size_t x = -1; size_t y = -1; size_t w = -1; size_t h = -1; s_PngReadValidate(png_ptr, info_ptr, width, height, depth, x, y, w, h); // allocate our image and read, line by line image.Reset(new CImage(width, height, depth)); unsigned char* row_ptr = image->SetData(); for (size_t i = 0; i < height; ++i) { png_read_row(png_ptr, row_ptr, NULL); row_ptr += width * depth; } // read the end pointer png_read_end(png_ptr, end_ptr); // close and return s_PngReadFinalize(png_ptr, info_ptr, end_ptr); } catch (...) { // destroy everything s_PngReadFinalize(png_ptr, info_ptr, end_ptr); // rethrow throw; } return image.Release();}//// ReadImage()// read a PNG format image into memory, returning the image itself// This version reads a subpart of an image//CImage* CImageIOPng::ReadImage(CNcbiIstream& istr, size_t x, size_t y, size_t w, size_t h){ 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); // store and validate our image's parameters size_t width = 0; size_t height = 0; size_t depth = 0; s_PngReadValidate(png_ptr, info_ptr, width, height, depth, x, y, w, h); // allocate our image image.Reset(new CImage(w, h, depth)); unsigned char* to_data = image->SetData(); size_t to_stride = image->GetWidth() * image->GetDepth(); size_t to_offs = x * image->GetDepth(); // allocate a scanline for this image vector<unsigned char> row(width * depth); unsigned char* row_ptr = &row[0]; size_t i; // read up to our starting scan line for (i = 0; i < y; ++i) { png_read_row(png_ptr, row_ptr, NULL); } // read and convert the scanlines of interest for ( ; i < y + h; ++i) { png_read_row(png_ptr, row_ptr, NULL); memcpy(to_data, row_ptr + to_offs, to_stride); to_data += to_stride; } /** // read the rest of the image (do we need this?) for ( ; i < height; ++i) { png_read_row(png_ptr, row_ptr, NULL); } // read the end pointer png_read_end(png_ptr, end_ptr); **/ // close and return s_PngReadFinalize(png_ptr, info_ptr, end_ptr); } catch (...) { // destroy everything s_PngReadFinalize(png_ptr, info_ptr, end_ptr); // rethrow throw; } return image.Release();}//// WriteImage()// write an image to a file in PNG format// This version writes the entire image//void CImageIOPng::WriteImage(const CImage& image, CNcbiOstream& ostr, CImageIO::ECompress compress){ // make sure we've got an image if ( !image.GetData() ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): " "attempt to write an empty image"); } // validate our image - we need RGB or RGBA images if (image.GetDepth() != 3 && image.GetDepth() != 4) { string msg("CImageIOPng::WriteImage(): invalid image depth: "); msg += NStr::IntToString(image.GetDepth()); NCBI_THROW(CImageException, eWriteError, msg); } png_structp png_ptr = NULL; png_infop info_ptr = NULL; try { // initialize png stuff s_PngWriteInit(png_ptr, info_ptr, image, compress); // begin writing data png_set_write_fn(png_ptr, &ostr, s_PngWrite, s_PngFlush); png_write_info(png_ptr, info_ptr); // write our image, line-by-line unsigned char* row_ptr = const_cast<unsigned char*> (image.GetData()); size_t width = image.GetWidth(); size_t height = image.GetHeight(); size_t depth = image.GetDepth(); for (size_t i = 0; i < height; ++i) { png_write_row(png_ptr, row_ptr); row_ptr += width * depth; } // standard clean-up png_write_end(png_ptr, info_ptr); s_PngWriteFinalize(png_ptr, info_ptr); } catch (...) { s_PngWriteFinalize(png_ptr, info_ptr); throw; }}//// WriteImage()// write an image to a file in PNG format// This version writes only a subpart of the image//void CImageIOPng::WriteImage(const CImage& image, CNcbiOstream& ostr, size_t x, size_t y, size_t w, size_t h, CImageIO::ECompress compress){ // make sure we've got an image if ( !image.GetData() ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): " "attempt to write an empty image"); } // validate our image - we need RGB or RGBA images if (image.GetDepth() != 3 && image.GetDepth() != 4) { string msg("CImageIOPng::WriteImage(): invalid image depth: "); msg += NStr::IntToString(image.GetDepth()); NCBI_THROW(CImageException, eWriteError, msg); } png_structp png_ptr = NULL; png_infop info_ptr = NULL; try { // initialize png stuff s_PngWriteInit(png_ptr, info_ptr, image, compress); // begin writing data png_set_write_fn(png_ptr, &ostr, s_PngWrite, s_PngFlush); png_write_info(png_ptr, info_ptr); // write our image // we plan to march through only part of our image // get a pointer to the start of our scan line // // NB: the const cast is necessary as png_write_row takes a non-const // pointer (go figure...) unsigned char* from_data = const_cast<unsigned char*>(image.GetData()); from_data += (y * image.GetWidth() + x) * image.GetDepth(); size_t from_stride = image.GetWidth() * image.GetDepth(); // march out h scan lines for (size_t i = 0; i < h; ++i) { png_write_row(png_ptr, from_data); from_data += from_stride; } // standard clean-up png_write_end(png_ptr, info_ptr); s_PngWriteFinalize(png_ptr, info_ptr); } catch (...) { s_PngWriteFinalize(png_ptr, info_ptr); throw; }}END_NCBI_SCOPE#else // !HAVE_LIBPNG//// LIBPNG functionality not included - we stub out the various needed// functions//BEGIN_NCBI_SCOPECImage* CImageIOPng::ReadImage(CNcbiIstream& file){ NCBI_THROW(CImageException, eUnsupported, "CImageIOPng::ReadImage(): PNG format not supported");}CImage* CImageIOPng::ReadImage(CNcbiIstream& file, size_t, size_t, size_t, size_t){ NCBI_THROW(CImageException, eUnsupported, "CImageIOPng::ReadImage(): PNG format not supported");}void CImageIOPng::WriteImage(const CImage& image, CNcbiOstream& file, CImageIO::ECompress){ NCBI_THROW(CImageException, eUnsupported, "CImageIOPng::WriteImage(): PNG format not supported");}void CImageIOPng::WriteImage(const CImage& image, CNcbiOstream& file, size_t, size_t, size_t, size_t, CImageIO::ECompress){ NCBI_THROW(CImageException, eUnsupported, "CImageIOPng::WriteImage(): PNG format not supported");}END_NCBI_SCOPE#endif // HAVE_LIBPNG/* * =========================================================================== * $Log: image_io_png.cpp,v $ * Revision 1000.3 2004/06/01 19:41:37 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5 * * Revision 1.5 2004/05/17 21:07:58 gorelenk * Added include of PCH ncbi_pch.hpp * * Revision 1.4 2003/12/20 17:50:53 dicuccio * Fixed bugs in reading of subimage - don't declare image in try block; use * correct height. Dropped unnecessary finalization - don't need to scan whole * image. * * Revision 1.3 2003/12/16 15:49:37 dicuccio * Large re-write of image handling. Added improved error-handling and support * for streams-based i/o (via hooks into each client library). * * Revision 1.2 2003/11/03 15:19:57 dicuccio * Added optional compression parameter * * Revision 1.1 2003/06/03 15:17:13 dicuccio * Initial revision of image library * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -