@Override
    public void postFrame(FrameBuffer out) {
        if (capture) {
            capture = false;

            Camera curCamera = rm.getCurrentCamera();
            int viewX = (int) (curCamera.getViewPortLeft() * curCamera.getWidth());
            int viewY = (int) (curCamera.getViewPortBottom() * curCamera.getHeight());
            int viewWidth = (int) ((curCamera.getViewPortRight() - curCamera.getViewPortLeft()) * curCamera.getWidth());
            int viewHeight = (int) ((curCamera.getViewPortTop() - curCamera.getViewPortBottom()) * curCamera.getHeight());

            renderer.setViewPort(0, 0, width, height);
            renderer.readFrameBuffer(out, outBuf);
            renderer.setViewPort(viewX, viewY, viewWidth, viewHeight);

            File file;
            String filename;
            if (numbered) {
                shotIndex++;
                filename = shotName + shotIndex;
            } else {
                filename = shotName;
            }

            if (filePath == null) {
                file = new File(JmeSystem.getStorageFolder() + File.separator + filename + ".png").getAbsoluteFile();
            } else {
                file = new File(filePath + filename + ".png").getAbsoluteFile();
            }

            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, "Saving ScreenShot to: {0}", file.getAbsolutePath());
            }

            try {
                writeImageFile(file);
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "Error while saving screenshot", ex);
            }
        }
    }
Clean up this AppState during the first update after it gets detached.
<p>
Because each ScreenshotAppState is also a SceneProcessor (in addition to
being an AppState) this method is also invoked when the SceneProcessor
get removed from its ViewPort, leading to an indirect recursion:
<ol><li>AppStateManager invokes ScreenshotAppState.cleanup()</li>
<li>cleanup() invokes ViewPort.removeProcessor()</li>
<li>removeProcessor() invokes ScreenshotAppState.cleanup()</li>
<li>... and so on.</li>
</ol>
<p>
In order to break this recursion, this method only removes the
SceneProcessor if it has not previously been removed.
<p>
A better design would have the AppState and SceneProcessor be 2 distinct
objects, but doing so now might break applications that rely on them
being a single object.
jme3-core/src/main/java/com/jme3/app/state/ScreenshotAppState.java