📄 cn3d_png.cpp
字号:
// sets callback that's called by PNG after each written row png_set_write_status_fn(png_ptr, write_row_callback); // set various PNG parameters png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); png_set_IHDR(png_ptr, info_ptr, outputWidth, outputHeight, 8, PNG_COLOR_TYPE_RGB, interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); // set up camera so that it's the same view as it is in the window glCanvas->renderer->Init(); glViewport(0, 0, outputWidth, outputHeight); glCanvas->renderer->NewView(); // Redraw the model into the new off-screen context, then use glReadPixels // to retrieve pixel data. It's much easier to use glReadPixels rather than // trying to read directly from the off-screen buffer, since GL can do all // the potentially tricky work of translating from whatever pixel format // the buffer uses into "regular" RGB byte triples. If fonts need scaling, // have to reconstruct lists regardless of whether display lists are shared. if (!shareDisplayLists || outputHeight != glCanvas->GetClientSize().GetHeight()) { glCanvas->SetGLFontFromRegistry(((double) outputHeight) / glCanvas->GetClientSize().GetHeight()); glCanvas->renderer->Construct(); } glPixelStorei(GL_PACK_ALIGNMENT, 1); // Write image row by row to avoid having to allocate another full image's // worth of memory. Do multiple passes for interlacing, if necessary. Note // that PNG's rows are stored top down, while GL's are bottom up. if (interlaced) { // need to draw only once glCanvas->renderer->Display(); int pass, r; nRows = -outputHeight; // signal to monitor that we're interlacing if (png_set_interlace_handling(png_ptr) != 7) throw "confused by unkown PNG interlace scheme"; for (pass = 1; pass <= 7; ++pass) { for (int i = outputHeight - 1; i >= 0; --i) { r = outputHeight - i - 1; // when interlacing, only certain rows are actually read // during certain passes - avoid unncessary reads if ( ((pass == 1 || pass == 2) && (r % 8 == 0)) || ((pass == 3) && ((r - 4) % 8 == 0)) || ((pass == 4) && (r % 4 == 0)) || ((pass == 5) && ((r - 2) % 4 == 0)) || ((pass == 6) && (r % 2 == 0)) || ((pass == 7) && ((r - 1) % 2 == 0)) ) glReadPixels(0, i, outputWidth, 1, GL_RGB, GL_UNSIGNED_BYTE, rowStorage); // ... but still have to call this for each row in each pass */ png_write_row(png_ptr, rowStorage); } } } // not interlaced, but possibly chunked else { int bufferRow, bufferRowStart; nRows = outputHeight; for (int chunk = nChunks - 1; chunk >= 0; --chunk) { // set viewport for this chunk and redraw if (nChunks > 1) { TRACEMSG("drawing chunk #" << (chunk + 1)); glViewport(0, -chunk*bufferHeight, outputWidth, outputHeight); } glCanvas->renderer->Display(); // only draw "visible" part of top chunk if (chunk == nChunks - 1) bufferRowStart = outputHeight - 1 - bufferHeight * (nChunks - 1); else bufferRowStart = bufferHeight - 1; // dump chunk to PNG file for (bufferRow = bufferRowStart; bufferRow >= 0; --bufferRow) { glReadPixels(0, bufferRow, outputWidth, 1, GL_RGB, GL_UNSIGNED_BYTE, rowStorage); png_write_row(png_ptr, rowStorage); } } } // finish up PNG write png_write_end(png_ptr, info_ptr); success = true; // general cleanup if (out) fclose(out); if (rowStorage) delete rowStorage; if (png_ptr) { if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); else png_destroy_write_struct(&png_ptr, NULL); } if (progressMeter) { progressMeter->Close(true); progressMeter->Destroy(); progressMeter = NULL; } // platform-specific cleanup, restore context#if defined(__WXMSW__) if (current_hdc && current_hglrc) wglMakeCurrent(current_hdc, current_hglrc); if (hglrc) wglDeleteContext(hglrc); if (hbm) DeleteObject(hbm); if (hdc) DeleteDC(hdc);#elif defined(__WXGTK__) gotAnXError = false; if (glCtx) { glXMakeCurrent(display, currentXdrw, currentCtx); glXDestroyContext(display, glCtx); } if (glxPixmap) glXDestroyGLXPixmap(display, glxPixmap); if (xPixmap) XFreePixmap(display, xPixmap); if (localVI && visinfo) XFree(visinfo); if (gotAnXError) WARNINGMSG("Got an X error destroying GLXPixmap context"); XSetErrorHandler(currentXErrHandler);#elif defined(__WXMAC__) aglSetCurrentContext(currentCtx); if (ctx) aglDestroyContext(ctx); if (fmt) aglDestroyPixelFormat(fmt); if (base) delete[] base; glCanvas->renderer->RecreateQuadric(); // Macs have context-sensitive quadrics...#endif } catch (const char *err) { ERRORMSG("Error creating PNG: " << err); } catch (exception& e) { ERRORMSG("Uncaught exception while creating PNG: " << e.what()); } // reset font after "regular" context restore glCanvas->SuspendRendering(false); if (outputHeight != glCanvas->GetClientSize().GetHeight()) { glCanvas->SetCurrent(); glCanvas->SetGLFontFromRegistry(1.0); if (shareDisplayLists) GlobalMessenger()->PostRedrawAllStructures(); } glCanvas->Refresh(false); return success;}END_SCOPE(Cn3D)////////////////////////////////////////////////////////////////////////////////////////////////// The following is taken unmodified from wxDesigner's C++ code from png_dialog.wdr////////////////////////////////////////////////////////////////////////////////////////////////wxSizer *SetupPNGOptionsDialog( wxPanel *parent, bool call_fit, bool set_sizer ){ wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL ); wxStaticBox *item2 = new wxStaticBox( parent, -1, "Output Settings" ); wxStaticBoxSizer *item1 = new wxStaticBoxSizer( item2, wxVERTICAL ); wxFlexGridSizer *item3 = new wxFlexGridSizer( 1, 0, 0, 0 ); item3->AddGrowableCol( 1 ); wxStaticText *item4 = new wxStaticText( parent, ID_TEXT, "File name:", wxDefaultPosition, wxDefaultSize, 0 ); item3->Add( item4, 0, wxALIGN_CENTRE|wxALL, 5 ); item3->Add( 20, 20, 0, wxALIGN_CENTRE|wxALL, 5 ); wxButton *item5 = new wxButton( parent, ID_B_BROWSE, "Browse", wxDefaultPosition, wxDefaultSize, 0 ); item3->Add( item5, 0, wxALIGN_CENTRE|wxLEFT|wxRIGHT|wxTOP, 5 ); item1->Add( item3, 0, wxGROW|wxALIGN_CENTER_VERTICAL, 5 ); wxTextCtrl *item6 = new wxTextCtrl( parent, ID_T_NAME, "", wxDefaultPosition, wxDefaultSize, 0 ); item1->Add( item6, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 ); wxFlexGridSizer *item7 = new wxFlexGridSizer( 2, 0, 0, 0 ); item7->AddGrowableCol( 1 ); item7->AddGrowableRow( 1 ); wxStaticText *item8 = new wxStaticText( parent, ID_TEXT, "Width:", wxDefaultPosition, wxDefaultSize, 0 ); item7->Add( item8, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP, 5 ); item7->Add( 20, 20, 0, wxALIGN_CENTRE|wxALL, 5 ); wxStaticText *item9 = new wxStaticText( parent, ID_TEXT, "Height:", wxDefaultPosition, wxDefaultSize, 0 ); item7->Add( item9, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP, 5 ); wxTextCtrl *item10 = new wxTextCtrl( parent, ID_T_WIDTH, "", wxDefaultPosition, wxDefaultSize, 0 ); item7->Add( item10, 0, wxALIGN_CENTRE|wxLEFT|wxRIGHT|wxBOTTOM, 5 ); wxStaticText *item11 = new wxStaticText( parent, ID_TEXT, "x", wxDefaultPosition, wxDefaultSize, 0 ); item7->Add( item11, 0, wxALIGN_CENTRE|wxLEFT|wxRIGHT|wxBOTTOM, 5 ); wxTextCtrl *item12 = new wxTextCtrl( parent, ID_T_HEIGHT, "", wxDefaultPosition, wxDefaultSize, 0 ); item7->Add( item12, 0, wxALIGN_CENTRE|wxLEFT|wxRIGHT|wxBOTTOM, 5 ); item1->Add( item7, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); wxBoxSizer *item13 = new wxBoxSizer( wxHORIZONTAL ); wxCheckBox *item14 = new wxCheckBox( parent, ID_C_ASPECT, "Maintain original aspect ratio", wxDefaultPosition, wxDefaultSize, 0 ); item14->SetValue( TRUE ); item13->Add( item14, 0, wxALIGN_CENTRE|wxALL, 5 ); item13->Add( 20, 20, 0, wxALIGN_CENTRE|wxALL, 5 ); wxCheckBox *item15 = new wxCheckBox( parent, ID_C_INTERLACE, "Interlaced", wxDefaultPosition, wxDefaultSize, 0 ); item15->SetValue( TRUE ); item13->Add( item15, 0, wxALIGN_CENTRE|wxALL, 5 ); item1->Add( item13, 0, wxALIGN_CENTRE|wxLEFT|wxRIGHT|wxTOP, 5 ); item0->Add( item1, 0, wxALIGN_CENTRE|wxALL, 5 ); wxBoxSizer *item16 = new wxBoxSizer( wxHORIZONTAL ); wxButton *item17 = new wxButton( parent, ID_B_OK, "OK", wxDefaultPosition, wxDefaultSize, 0 ); item17->SetDefault(); item16->Add( item17, 0, wxALIGN_CENTRE|wxALL, 5 ); item16->Add( 20, 20, 0, wxALIGN_CENTRE|wxALL, 5 ); wxButton *item18 = new wxButton( parent, ID_B_CANCEL, "Cancel", wxDefaultPosition, wxDefaultSize, 0 ); item16->Add( item18, 0, wxALIGN_CENTRE|wxALL, 5 ); item0->Add( item16, 0, wxALIGN_CENTRE|wxALL, 5 ); if (set_sizer) { parent->SetAutoLayout( TRUE ); parent->SetSizer( item0 ); if (call_fit) { item0->Fit( parent ); item0->SetSizeHints( parent ); } } return item0;}/** ---------------------------------------------------------------------------* $Log: cn3d_png.cpp,v $* Revision 1000.3 2004/06/01 18:28:18 gouriano* PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.21** Revision 1.21 2004/05/21 21:41:39 gorelenk* Added PCH ncbi_pch.hpp** Revision 1.20 2004/03/15 17:30:06 thiessen* prefer prefix vs. postfix ++/-- operators** Revision 1.19 2004/02/19 17:04:50 thiessen* remove cn3d/ from include paths; add pragma to disable annoying msvc warning** Revision 1.18 2003/12/04 15:49:39 thiessen* fix stereo and PNG export problems on Mac** Revision 1.17 2003/11/15 16:08:35 thiessen* add stereo** Revision 1.16 2003/03/13 14:26:18 thiessen* add file_messaging module; split cn3d_main_wxwin into cn3d_app, cn3d_glcanvas, structure_window, cn3d_tools** Revision 1.15 2003/02/03 19:20:03 thiessen* format changes: move CVS Log to bottom of file, remove std:: from .cpp files, and use new diagnostic macros** Revision 1.14 2002/10/21 15:11:29 thiessen* don't share lists in wxGTK build** Revision 1.13 2002/10/18 20:33:54 thiessen* workaround for linux/Mesa bug** Revision 1.12 2002/10/18 15:42:59 thiessen* work around png header issue for linux** Revision 1.11 2002/10/11 17:21:39 thiessen* initial Mac OSX build** Revision 1.10 2002/08/15 22:13:14 thiessen* update for wx2.3.2+ only; add structure pick dialog; fix MultitextDialog bug** Revision 1.9 2002/04/21 12:21:21 thiessen* minor fixes for AIX** Revision 1.8 2001/10/25 17:16:43 thiessen* add PNG output to Mac version** Revision 1.7 2001/10/25 14:19:44 thiessen* move png.h to top** Revision 1.6 2001/10/25 00:06:29 thiessen* fix concurrent rendering problem in wxMSW PNG output** Revision 1.5 2001/10/24 22:02:02 thiessen* fix wxGTK concurrent rendering problem** Revision 1.4 2001/10/24 17:07:30 thiessen* add PNG output for wxGTK** Revision 1.3 2001/10/24 11:25:20 thiessen* fix wxString problem** Revision 1.2 2001/10/23 20:10:23 thiessen* fix scaling of fonts in high-res PNG output** Revision 1.1 2001/10/23 13:53:38 thiessen* add PNG export**/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -