⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cn3d_png.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        cInterlace->SetValue(false);    } else        cInterlace->SetValue(initialInterlaced);    // bring up file selector first    wxCommandEvent browse(wxEVT_COMMAND_BUTTON_CLICKED, ID_B_BROWSE);    OnButton(browse);    if (tName->GetValue().size() == 0) return false;    // cancelled    // return dialog result    return (ShowModal() == wxOK);}bool PNGOptionsDialog::GetValues(wxString *outputFilename, int *width, int *height, bool *interlaced){    DECLARE_AND_FIND_WINDOW_RETURN_RESULT_ON_ERR(tName, ID_T_NAME, wxTextCtrl, false)    DECLARE_AND_FIND_WINDOW_RETURN_RESULT_ON_ERR(tWidth, ID_T_WIDTH, wxTextCtrl, false)    DECLARE_AND_FIND_WINDOW_RETURN_RESULT_ON_ERR(tHeight, ID_T_HEIGHT, wxTextCtrl, false)    DECLARE_AND_FIND_WINDOW_RETURN_RESULT_ON_ERR(cInterlace, ID_C_INTERLACE, wxCheckBox, false)    *outputFilename = tName->GetValue();    double val;    if (!GET_AND_IS_VALID_SIZE(tWidth, val)) return false;    *width = (int) val;    if (!GET_AND_IS_VALID_SIZE(tHeight, val)) return false;    *height = (int) val;    *interlaced = (cInterlace->IsEnabled() && cInterlace->GetValue());    return true;}static bool GetOutputParameters(wxString *outputFilename, int *width, int *height, bool *interlaced){    PNGOptionsDialog dialog(NULL);    bool ok = dialog.Activate(*width, *height, *interlaced);    if (ok) dialog.GetValues(outputFilename, width, height, interlaced);    return ok;}// callback used by PNG library to report errorsstatic void writepng_error_handler(png_structp png_ptr, png_const_charp msg){    ERRORMSG("PNG library error: " << msg);}#ifdef __WXGTK__static bool gotAnXError;int X_error_handler(Display *dpy, XErrorEvent *error){    gotAnXError = true;    return 0;}#endif// called after each row is written to the filestatic void write_row_callback(png_structp png_ptr, png_uint_32 row, int pass){    if (!progressMeter) return;    int progress = 0;    if (nRows < 0) { /* if negative, then we're doing interlacing */        double start, end;        switch (pass + 1) {            case 1: start = 0;  end = 1;  break;            case 2: start = 1;  end = 2;  break;            case 3: start = 2;  end = 3;  break;            case 4: start = 3;  end = 5;  break;            case 5: start = 5;  end = 7;  break;            case 6: start = 7;  end = 11; break;            case 7: start = 11; end = 15; break;            default: return;    // png lib gives final pass=7,row=0 to signal completion        }        progress = (int) (1.0 * PROGRESS_RESOLUTION *            ((start / 15) + (((double) row) / (-nRows)) * ((end - start) / 15)));    } else { /* not interlaced */        progress = (int) (1.0 * PROGRESS_RESOLUTION * row / nRows);    }    progressMeter->SetValue(progress);}bool ExportPNG(Cn3DGLCanvas *glCanvas){#if !defined(__WXMSW__) && !defined(__WXGTK__) && !defined(__WXMAC__)    ERRORMSG("PNG export not (yet) implemented on this platform");    return false;#endif    if (!glCanvas || !glCanvas->renderer) {        ERRORMSG("ExportPNG() - bad glCanvas parameter");        return false;    }    bool success = false, shareDisplayLists = true, interlaced = true;    int outputWidth, outputHeight, bufferHeight, bytesPerPixel = 3, nChunks = 1;    wxString filename;    FILE *out = NULL;    unsigned char *rowStorage = NULL;    png_structp png_ptr = NULL;    png_infop info_ptr = NULL;    outputWidth = glCanvas->GetClientSize().GetWidth();		// initial size    outputHeight = glCanvas->GetClientSize().GetHeight();    if (!GetOutputParameters(&filename, &outputWidth, &outputHeight, &interlaced))        return true; // cancelled    try {        INFOMSG("saving PNG file '" << filename.c_str() << "'");        // need to avoid any GL calls in glCanvas while off-screen rendering is happening; so        // temporarily prevent glCanvas from responding to window resize/exposure, etc.        glCanvas->SuspendRendering(true);        int windowViewport[4];        glCanvas->renderer->GetViewport(windowViewport);        TRACEMSG("window viewport: x,y: " << windowViewport[0] << ',' << windowViewport[1]            << " size: " << windowViewport[2] << ',' << windowViewport[3]);        INFOMSG("output size: " << outputWidth << ',' << outputHeight);        // decide whether the in-memory image buffer can fit the whole drawing,        // or whether we need to split it up into separate horizontal chunks        bufferHeight = outputHeight;        if (outputWidth * outputHeight > MAX_BUFFER_PIXELS) {            bufferHeight = MAX_BUFFER_PIXELS / outputWidth;            nChunks = outputHeight / bufferHeight;              // whole chunks +            if (outputHeight % bufferHeight != 0) ++nChunks;    // partially occupied chunk            interlaced = false;        }        // create and show progress meter        wxString message;        message.Printf("Writing PNG file %s (%ix%i)",            (wxString(wxFileNameFromPath(filename.c_str()))).c_str(),            outputWidth, outputHeight);        progressMeter = new ProgressMeter(NULL, message, "Saving...", PROGRESS_RESOLUTION);        // open the output file for writing        out = fopen(filename.c_str(), "wb");        if (!out) throw "can't open file for writing";#if defined(__WXMSW__)        HDC hdc = NULL, current_hdc = NULL;        HGLRC hglrc = NULL, current_hglrc = NULL;        HGDIOBJ current_hgdiobj = NULL;        HBITMAP hbm = NULL;        PIXELFORMATDESCRIPTOR pfd;        int nPixelFormat;        current_hglrc = wglGetCurrentContext(); // save to restore later        current_hdc = wglGetCurrentDC();        // create bitmap of same color type as current rendering context        hbm = CreateCompatibleBitmap(current_hdc, outputWidth, bufferHeight);        if (!hbm) throw "failed to create rendering BITMAP";        hdc = CreateCompatibleDC(current_hdc);        if (!hdc) throw "CreateCompatibleDC failed";        current_hgdiobj = SelectObject(hdc, hbm);        if (!current_hgdiobj) throw "SelectObject failed";        memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);        pfd.nVersion = 1;        pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;  // NOT doublebuffered, to save memory        pfd.iPixelType = PFD_TYPE_RGBA;        pfd.cColorBits = GetDeviceCaps(current_hdc, BITSPIXEL);        pfd.iLayerType = PFD_MAIN_PLANE;        nPixelFormat = ChoosePixelFormat(hdc, &pfd);        if (!nPixelFormat) {            ERRORMSG("ChoosePixelFormat failed");            throw GetLastError();        }        if (!SetPixelFormat(hdc, nPixelFormat, &pfd)) {            ERRORMSG("SetPixelFormat failed");            throw GetLastError();        }        hglrc = wglCreateContext(hdc);        if (!hglrc) {            ERRORMSG("wglCreateContext failed");            throw GetLastError();        }        // try to share display lists with regular window, to save memory and draw time        if (!wglShareLists(current_hglrc, hglrc)) {            WARNINGMSG("wglShareLists failed: " << GetLastError());            shareDisplayLists = false;        }        if (!wglMakeCurrent(hdc, hglrc)) {            ERRORMSG("wglMakeCurrent failed");            throw GetLastError();        }#elif defined(__WXGTK__)        GLint glSize;        int nAttribs, attribs[20];        XVisualInfo *visinfo = NULL;        bool localVI = false;        Pixmap xPixmap = 0;        GLXContext currentCtx = NULL, glCtx = NULL;        GLXPixmap glxPixmap = 0;        GLXDrawable currentXdrw = 0;        Display *display;        int (*currentXErrHandler)(Display *, XErrorEvent *) = NULL;        currentCtx = glXGetCurrentContext(); // save current context info        currentXdrw = glXGetCurrentDrawable();        display = GDK_DISPLAY();        currentXErrHandler = XSetErrorHandler(X_error_handler);        gotAnXError = false;        // first, try to get a non-doublebuffered visual, to economize on memory        nAttribs = 0;        attribs[nAttribs++] = GLX_USE_GL;        attribs[nAttribs++] = GLX_RGBA;        attribs[nAttribs++] = GLX_RED_SIZE;        glGetIntegerv(GL_RED_BITS, &glSize);        attribs[nAttribs++] = glSize;        attribs[nAttribs++] = GLX_GREEN_SIZE;        attribs[nAttribs++] = glSize;        attribs[nAttribs++] = GLX_BLUE_SIZE;        attribs[nAttribs++] = glSize;        attribs[nAttribs++] = GLX_DEPTH_SIZE;        glGetIntegerv(GL_DEPTH_BITS, &glSize);        attribs[nAttribs++] = glSize;        attribs[nAttribs++] = None;        visinfo = glXChooseVisual(display, DefaultScreen(display), attribs);        // if that fails, just revert to the one used for the regular window        if (visinfo)            localVI = true;        else            visinfo = (XVisualInfo *) (glCanvas->m_vi);        // create pixmap        xPixmap = XCreatePixmap(display,            RootWindow(display, DefaultScreen(display)),            outputWidth, bufferHeight, visinfo->depth);        if (!xPixmap) throw "failed to create Pixmap";        glxPixmap = glXCreateGLXPixmap(display, visinfo, xPixmap);        if (!glxPixmap) throw "failed to create GLXPixmap";        if (gotAnXError) throw "Got an X error creating GLXPixmap";        // try to share display lists with "regular" context	// ... seems to be too flaky - fails on Linux/Mesa, Solaris//        glCtx = glXCreateContext(display, visinfo, currentCtx, False);//        if (!glCtx || !glXMakeCurrent(display, glxPixmap, glCtx)) {//            WARNINGMSG("failed to make GLXPixmap rendering context with shared display lists");//            if (glCtx) glXDestroyContext(display, glCtx);            shareDisplayLists = false;            // try to create context without shared lists            glCtx = glXCreateContext(display, visinfo, NULL, False);            if (!glCtx || !glXMakeCurrent(display, glxPixmap, glCtx))                throw "failed to make GLXPixmap rendering context without shared display lists";//        }        if (gotAnXError) throw "Got an X error setting GLX context";#elif defined(__WXMAC__)        unsigned char *base = NULL;        GLint attrib[20], glSize;        int na = 0;        AGLPixelFormat fmt = NULL;        AGLContext ctx = NULL, currentCtx;    	currentCtx = aglGetCurrentContext();    	// Mac pixels seem to always be 32-bit    	bytesPerPixel = 4;    	base = new unsigned char[outputWidth * bufferHeight * bytesPerPixel];    	if (!base) throw "failed to allocate image buffer";    	// create an off-screen rendering context (NOT doublebuffered)    	attrib[na++] = AGL_OFFSCREEN;    	attrib[na++] = AGL_RGBA;    	glGetIntegerv(GL_RED_BITS, &glSize);        attrib[na++] = AGL_RED_SIZE;        attrib[na++] = glSize;        attrib[na++] = AGL_GREEN_SIZE;        attrib[na++] = glSize;        attrib[na++] = AGL_BLUE_SIZE;        attrib[na++] = glSize;    	glGetIntegerv(GL_DEPTH_BITS, &glSize);        attrib[na++] = AGL_DEPTH_SIZE;        attrib[na++] = glSize;        attrib[na++] = AGL_NONE;        if ((fmt=aglChoosePixelFormat(NULL, 0, attrib)) == NULL)        	throw "aglChoosePixelFormat failed";        // try to share display lists with current "regular" context        if ((ctx=aglCreateContext(fmt, currentCtx)) == NULL) {            WARNINGMSG("aglCreateContext with shared lists failed");        	shareDisplayLists = false;        	if ((ctx=aglCreateContext(fmt, NULL)) == NULL)        	    throw "aglCreateContext without shared lists failed";        }        // attach off-screen buffer to this context        if (!aglSetOffScreen(ctx, outputWidth, bufferHeight, bytesPerPixel * outputWidth, base))        	throw "aglSetOffScreen failed";        if (!aglSetCurrentContext(ctx))        	throw "aglSetCurrentContext failed";        glCanvas->renderer->RecreateQuadric();	// Macs have context-sensitive quadrics...#endif        TRACEMSG("interlaced: " << interlaced << ", nChunks: " << nChunks            << ", buffer height: " << bufferHeight << ", shared: " << shareDisplayLists);        // allocate a row of pixel storage        rowStorage = new unsigned char[outputWidth * bytesPerPixel];        if (!rowStorage) throw "failed to allocate pixel row buffer";        /* set up the PNG writing (see libpng.txt) */        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, writepng_error_handler, NULL);        if (!png_ptr) throw "can't create PNG write structure";        info_ptr = png_create_info_struct(png_ptr);        if (!info_ptr) throw "can't create PNG info structure";        if (setjmp(png_ptr->jmpbuf)) throw "setjmp failed";        png_init_io(png_ptr, out);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -