Hi,
I worked it out! here follows my minimal example with a screenshot being saved 
as a pmg; to this end I used pngwriter (http://pngwriter.sourceforge.net/). 
Hopefuly will serve to the next one willing to learn the offscreen use.

the tricky thing here is that even fl_read_image( offscreenImage,...) is 
sensitive for the context i.e. it needs to be called while the offsceen is 
active.
Actually I would expect the offscreen just need to exist, just the drawing 
should be enclosed by fl_begin_offscreen and fl_end_offscreen, but within this 
program it's not possible to test: as soon as the window with the black and red 
boxes is terminated, all the fltk threads exit so the offscreen gets freed, I 
guess.
In any case, a call to fl_read_image( offscreenImage, ... ) in the main() 
results in a segmentation fault ...
Now I can use what I learned in my real system!

#include <iostream>
#include <string>
#include <cassert>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
#include <FL/Fl_Double_Window.H>
#include "../pngwriter-0.5.3/src/pngwriter.h"


uchar *offscreenImage = NULL;
Fl_Offscreen offscr = NULL;
int offscrW = 400, offscrH = 400;

void writeScreenshot( ) {
  std::cout << "writeScreenshot()" << std::endl;
  pngwriter screenshot( offscrW, offscrH, 0.0, "shapedemo-screenshot.png" );

  // Image writeout.
  for ( int row = 0; row < offscrH; ++row ) {
    for ( int col = 0; col < offscrW; ++col ) {
      assert( col + row * offscrW < offscrH * offscrW );
      uchar *pixel = &offscreenImage[ 3 * (col + row * offscrW) ];
      int pixelR = pixel[0] * 256;
      int pixelG = pixel[1] * 256;
      int pixelB = pixel[2] * 256;
      screenshot.plot( col, offscrH - row, pixelR, pixelG, pixelB );
    }
  }


  screenshot.plot_text( "/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf",
                        10, 10, 10, 0.0, "test pngwriter", 1.0, 1.0, 1.0 );

  screenshot.close( );
}

void drawRectangles( int winW, int winH ) {
  std::cout << "drawRectangles( int winW, int winH ) START" << std::endl;
  int x = 0, y = 0;

  std::cout << "aWin x=" << x << " y=" << y << " w=" << winW << " h=" << winH 
<< std::endl;

  fl_color( FL_BLACK );
  fl_rectf( x, y, x + winW, y + winH );
  std::cout << "screen filled in black" << std::endl;

  fl_color( FL_BLUE );
  fl_font( FL_TIMES, 15 );
  fl_draw( "test", 10, 10 );

  int margin = 100;

  int redRectX = x + margin;
  int redRectY = y + margin;
  int redRectW = winW - 2 * margin;
  int redRectH = winH - 2 * margin;

  std::cout << "RECTANGLE x=" << redRectX << " y=" << redRectY
          << " w=" << redRectW << " h=" << redRectH << std::endl;

  fl_color( FL_RED );
  fl_rectf( redRectX, redRectY, redRectW, redRectH );
  std::cout << "screen filled in red" << std::endl;

  std::cout << "drawRectangles( int winW, int winH ) END" << std::endl;
}

void drawOffscreen( Fl_Double_Window *aWin ) {
  std::cout << "drawOffscreen( Fl_Double_Window *aWin ) START" << std::endl;
  std::cout << "*aWin is " << (aWin->shown( ) ? "shown" : "not shown") << 
std::endl;

  fl_begin_offscreen( offscr );
  std::cout << "Fl_Offscreen OPENED" << std::endl;

  drawRectangles( aWin->w( ), aWin->h( ) );

  fl_end_offscreen( );
  std::cout << "Fl_Offscreen CLOSED" << std::endl;

  int srcX = 0, srcY = 0, destX = 0, destY = 0;
  fl_copy_offscreen( destX, destY, offscrW, offscrH, offscr, srcX, srcY );
  std::cout << "Fl_Offscreen COPIED" << std::endl;

  delete[] offscreenImage;
  offscreenImage = fl_read_image( offscreenImage, 0, 0, offscrW, offscrH );
  std::cout << "offscreen pixmap retrieved..." << std::endl;
  std::cout << "offscreenImage:" << unsigned(offscreenImage) << std::endl;

  std::cout << "drawOffscreen( Fl_Double_Window *aWin ) E" << std::endl;
}

class MyWin : public Fl_Double_Window {
protected:

  void draw( ) {
    std::cout << "MyWin::draw()" << std::endl;

    //    if ( !offscr ) {
    //      offscr = fl_create_offscreen( offscrW, offscrH );
    //      std::cout << "Fl_Offscreen CREATED" << std::endl;
    //    }
    Fl_Double_Window::draw( );

    drawOffscreen( this );
    // ALTERNATIVELY COMMENT OUT THE ABOVE LINE OR THE LINE BELOW TO DRAW 
WITHOUT OR WITH OFFSCREEN
    //        drawRectangles( w( ), h( ) );
  }

public:

  MyWin( int a, int b, char const *label = "Fl_Offscreen test" )
  :
  Fl_Double_Window( a, b, label ) { }

  ~MyWin( ) {
    // never called ... ?
    std::cout << "MyWin DESTRUCTOR" << std::endl;
  }

};

int runWin( ) {
  Fl_Double_Window *aWin = new MyWin( 400, 400, "Fl_Offscreen test" );
  aWin->resizable( );
  aWin->show( );
  std::cout << "Fl_Double_Window started" << std::endl;

  // ALTERNATIVELY COMMENT OUT THE OFFSCREEN SETUP BELOW OR IN MyWin::Draw()
  Fl::flush( );
  aWin->make_current( );
  offscr = fl_create_offscreen( offscrW, offscrH );
  std::cout << "Fl_Offscreen created" << std::endl;

  return Fl::run( );
}

int main( ) {
  int retval = runWin( );
  std::cout << "back to main() ..." << std::endl;

  writeScreenshot( );
  delete[] offscreenImage;
  return retval;
}

_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to