Thread: Re: [PyOpenGL-Users] extremely large screen capture]
Brought to you by:
mcfletch
From: stephan) <mai...@sh...> - 2005-03-17 09:11:40
|
Hi Rich, As I understand it there are generally 3 approaches to this: []mesa off screen rendering []glReadPixels []pbuffers glReadPixels seems to be the simplest and has the advantage of being hardware accelarated but is also restricted to whatever max resolution the opengl implemntation supports. This calls for tiled rendering as it is described here: http://www.mesa3d.org/brianp/TR.html I did not have time yet to translate this code to python...should be fairly easy though. It comes down to calling glViewport for each tile and then patching the parts together with PIL. If you go for the challenge (on a rainy sunday afternoon with a delicious cup of darjeeling maybe) please be so kind and post the code on this list. stephan) PS: http://www.mesa3d.org/osmesa.html http://www.mesa3d.org/pbuffers.html Rich Drewes wrote: > Hello, > > I want to save a very large pyopengl scene to a snapshot file. The > resolution I am trying for is 3200x2400. > > The following code fragment, using PIL, works up to 1600x1200: > > import Image > ox, oy, width, height = glGetIntegerv(GL_VIEWPORT) > print width, height, ox, oy > glPixelStorei(GL_PACK_ALIGNMENT, 1) > data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) > image = Image.fromstring("RGB", (width, height), data) > image = image.transpose(Image.FLIP_TOP_BOTTOM) > image.save("snap.png", "PNG") > > However if I try to create my initial window at 3200x2400, like this: > > glutInitWindowSize(3200, 2400) > > two things happen. First, the actual window that is created onscreen is > only about 1600x1200 (minus a bit for window borders). When I move around > my 3D scene, it looks like OpenGL thinks that the scene really is larger > than what the window is showing me (which is great) but I am only seeing > part of it. When I try to do the screen capture with the code above, the > width and height reported by glGetIntegerv(GL_VIEWPORT) are 3200 and 2400. > That looks promising. However, when I examine the resulting snap.png > image, it only contains what appears to be the lower quadrant of my > scene--the portion that was actually visible on screen. > > Is there any simple way to capture an image larger than 1600x1200? What > is the resolution-limiting factor in my current approach? > > Would I have to create 4 viewports of 1600x1200, each one showing part of > the scene (with a different projection matrix but same model transform?) > and same each as a separate image and then paste them together myself? > Does anyone have any suggestions for doing this seamlessly? > > Thanks, > Rich > > > ------------------------------------------------------- > SF email is sponsored by - The IT Product Guide > Read honest & candid reviews on hundreds of IT Products from real users. > Discover which products truly live up to the hype. Start reading now. > http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click > _______________________________________________ > PyOpenGL Homepage > http://pyopengl.sourceforge.net > _______________________________________________ > PyOpenGL-Users mailing list > PyO...@li... > https://lists.sourceforge.net/lists/listinfo/pyopengl-users > |
From: Rich D. <dr...@in...> - 2005-05-02 22:55:50
|
On Thu, 17 Mar 2005, stephan) wrote: > Hi Rich, > As I understand it there are generally 3 approaches to this: > []mesa off screen rendering > []glReadPixels > []pbuffers > > glReadPixels seems to be the simplest and has the advantage of being > hardware accelarated but is also restricted to whatever max resolution > the opengl implemntation supports. This calls for tiled rendering as it > is described here: > http://www.mesa3d.org/brianp/TR.html > > I did not have time yet to translate this code to python...should be > fairly easy though. It comes down to calling glViewport for each tile > and then patching the parts together with PIL. > > If you go for the challenge (on a rainy sunday afternoon with a > delicious cup of darjeeling maybe) please be so kind and post the code > on this list. After considerable experimentation, I did finally get up to 4096x4096 screen dumps with ReadPixels() to work, though I'm not quite sure about some aspects of it--perhaps you could help me understand why this works. Code fragment is at the end of the message. What has me confused is why the viewport is constructed 'left' (negative) of the origin. This is what the example program showed at the URL in the comment in the code above (though that code seemed to have some other bugs which I can't recall at the moment), and building the viewports negative was the only way I could get things to work. Any ideas on why things work that way? For a Linux Journal article that was just published, I generated an image of a neural network model using PyOpenGL and some of the above code, of about 2K pixels by 3K pixels that I hoped would take up the entire cover of the magazine (with text overlaid) . . . however they ended up shrinking my image to about 1 inch by 2 inches for the cover of the June issue and placed it next to a picture of a computer sitting on top of a penguin :/ You can see the image (if you squint) at http://www.linuxjournal.com. Rich http://www.interstice.com/drewes -- code follows -- -- download brainlab.tgz from homepage and look at netplot.py for full code -- vw=self.w*self.nvpx; vh=self.h*self.nvpy # cycle through each viewport and take a snapshot bigimage=Image.new('RGB', (vw, vh)) px=0 cx=0 # I don't understand why the viewport coordinates are specified all negative of 0, per example # at http://astronomy.swin.edu.au/~pbourke/opengl/windowdump/ for vpx in range(0, self.nvpx): cy=-(self.nvpy-1)*self.h py=0 for vpy in range(0, self.nvpy): print "vpx, vpy", vpx, vpy, "cx, cy", cx, cy glMatrixMode(GL_PROJECTION) glLoadIdentity() glViewport(cx, cy, vw, vh) gluPerspective(120.0, float(self.w)/float(self.h), self.near, self.far) glMatrixMode(GL_MODELVIEW) # we actually have to force a redraw *now* so we can't just post a redisplay self.on_display() # now save this viewport data = glReadPixels(0, 0, self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (self.w, self.h), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) oo=(px, py) print "pasting viewport section to", oo bigimage.paste(image, oo) py+=self.h cy+=self.h cx-=self.w px+=self.w # restore default viewport glMatrixMode(GL_PROJECTION) glLoadIdentity() sx,sy=self.ScreenCenter() glViewport(sx, sy, w*self.nvpx, h*self.nvpy) gluPerspective(120.0, float(self.w)/float(self.h), self.near, self.far) glMatrixMode(GL_MODELVIEW) glutPostRedisplay() bigimage.save('snap.png', 'PNG') |