Problem refreshing GimpPreviewArea

View: New views
8 Messages — Rating Filter:   Alert me  

Problem refreshing GimpPreviewArea

by Nicolás Serrano Martínez Santos :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi! I am using GimpPreviewArea to show previews in my plugin dialog. My problem is that when the size of area changes and i draw it. It doesn't refresh the contents but if I minimize the dialog and then show it again the area is refreshed. 

I've tried to use gtk_widget_queue_draw_area but it doesn't work. Any idea?



_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Tue, 2008-05-06 at 18:58 +0200, Nicolás Serrano Martínez Santos
wrote:
> Hi! I am using GimpPreviewArea to show previews in my plugin dialog.
> My problem is that when the size of area changes and i draw it. It
> doesn't refresh the contents but if I minimize the dialog and then
> show it again the area is refreshed.

Can you show us some example code?


Sven


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Nicolás Serrano Martínez Santos :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>
> Can you show us some example code?
>

Of course!

-----------------------------------------------------------


(When the plugin dialog appears it creates a layer that changes when  
you are changing the options. This layer has variable size and I use  
GimpDrawablePreview in order to see it at it's real size.

....

/*  clear the current preview and get the new line adjusted drawable */
   gimp_image_remove_layer(m->image_id,*(m->layer));
   gimp_drawable_detach(*(m->d));
   *(m->layer) = gimp_layer_copy(m->back_layer);
   gimp_image_add_layer(m->image_id,*(m->layer),-1);
   width = x2-x1;  height = (y2-y1;
   gimp_layer_resize(*(m->layer),width,height,-x1,-y1);
   d_id = gimp_image_get_active_drawable(m->image_id);
   *(m->d) = gimp_drawable_get(d_id);

   refresh_preview((GimpPreviewArea *) m->preview,*(m->d));
}

void refresh_preview(GimpPreviewArea *p, GimpDrawable *d){
   gint width, height; GimpPixelRgn rgn_input; guchar *buf;

   width = gimp_drawable_width(d->drawable_id);
   height = gimp_drawable_height(d->drawable_id);
   buf = g_new(guchar,width*height*3);
   gimp_pixel_rgn_init (&rgn_input,
                        d,
                        0,0,
                        width, height,
                        FALSE, FALSE);
   gimp_pixel_rgn_get_rect(&rgn_input,buf,0,0,width,height);
   gtk_widget_set_size_request((GtkWidget *) p,width,height);
   gimp_preview_area_draw(p,0,0,width,
         height,GIMP_RGB_IMAGE,buf,3*width); /* always RGB */
   g_free(buf);
}
--------------------------------------

As I commented if the size of drawable shown changes it isn't  
refreshed. On the other hand if immediately after a layer of the same  
size is shown it's refreshed (or if you minimize the dialog window).


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Wed, 2008-05-07 at 09:27 +0200, Nicolás Serrano Martínez Santos
wrote:

> void refresh_preview(GimpPreviewArea *p, GimpDrawable *d){
>    gint width, height; GimpPixelRgn rgn_input; guchar *buf;
>
>    width = gimp_drawable_width(d->drawable_id);
>    height = gimp_drawable_height(d->drawable_id);
>    buf = g_new(guchar,width*height*3);
>    gimp_pixel_rgn_init (&rgn_input,
>                         d,
>                         0,0,
>                         width, height,
>                         FALSE, FALSE);
>    gimp_pixel_rgn_get_rect(&rgn_input,buf,0,0,width,height);
>    gtk_widget_set_size_request((GtkWidget *) p,width,height);
>    gimp_preview_area_draw(p,0,0,width,
>          height,GIMP_RGB_IMAGE,buf,3*width); /* always RGB */
>    g_free(buf);
> }

That's a terribly inefficient way to doing things as you are allocating
a large amount of memory here to draw everything in a single call
instead of iterating over the drawable on a tile-by-tile basis (which is
what GimpDrawablePreview is doing). But it should work. I don't see
anything obviously wrong with this code. Perhaps you can make a simple
test application that we can compile and use to reproduce your problem?


Sven


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Nicolás Serrano Martínez Santos :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Please find attached a simple plugin which consist in a dialog showing a drawable. Where you can specify the width and height that will be shown.

This dialog does not refresh the GimpPreviewArea every time you click the spin. am I missing something??




El 08/05/2008, a las 13:45, Sven Neumann escribió:

That's a terribly inefficient way to doing things as you are allocating

a large amount of memory here to draw everything in a single call

instead of iterating over the drawable on a tile-by-tile basis (which is

what GimpDrawablePreview is doing). But it should work. I don't see

anything obviously wrong with this code. Perhaps you can make a simple

test application that we can compile and use to reproduce your problem?



_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

test.c.gz (2K) Download Attachment

Re: Problem refreshing GimpPreviewArea

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Fri, 2008-05-09 at 11:45 +0200, Nicolás Serrano Martínez Santos
wrote:
> Please find attached a simple plugin which consist in a dialog showing
> a drawable. Where you can specify the width and height that will be
> shown.
>
>
> This dialog does not refresh the GimpPreviewArea every time you click
> the spin. am I missing something??

You need to redraw the preview-area everytime it's size changes. It
doesn't keep the buffer across size changes. I have attached a modified
version of your test code that does the right thing.


Sven


[test.c]

#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>

typedef struct{
  gint x1,y1,width,height;
  GimpDrawable *drawable; GtkWidget *preview, *frame;
} redraw_info;


gboolean dialog (GimpDrawable *drawable);
void change_width(GtkSpinButton *p, gpointer data);
void change_height(GtkSpinButton *p, gpointer data);
static void size_changed (GimpPreviewArea *preview,
                          GtkAllocation   *allocation,
                          redraw_info     *info);

/*****************************************/

static void query (void);
static void run   (const gchar      *name,
                   gint              nparams,
                   const GimpParam  *param,
                   gint             *nreturn_vals,
                   GimpParam       **return_vals);

GimpPlugInInfo PLUG_IN_INFO =
{
  NULL,
  NULL,
  query,
  run
};

MAIN()

static void query (void){
  static GimpParamDef args[] =  {
    { GIMP_PDB_INT32,"run-mode","Run mode"},
    { GIMP_PDB_IMAGE,"image","Input image"},
    { GIMP_PDB_DRAWABLE,"drawable","Input drawable" },
  };

  gimp_install_procedure (
    "test",
    "test",
    "Help:",
    "test-author",
    "Copyright test-author",
    "2008",
    "test",
    "GRAY",
    GIMP_PLUGIN,
    G_N_ELEMENTS (args), 0,
    args, NULL);

  gimp_plugin_menu_register ("test","<Image>/test");
}

static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam  values[1];
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  GimpRunMode       run_mode;
  gint32 image; GimpDrawable     *drawable;

  /* Setting mandatory output values */
  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type = GIMP_PDB_STATUS;
  values[0].data.d_status = status;

  /* Getting run_mode - we won't display a dialog if
   * we are in NONINTERACTIVE mode
  */
  run_mode = param[0].data.d_int32;
  image = param[1].data.d_image;
  drawable = gimp_drawable_get(param[2].data.d_drawable);

  gimp_tile_cache_ntiles (2 * (drawable->width /
                                     gimp_tile_width () + 1));
  switch (run_mode){
    case GIMP_RUN_NONINTERACTIVE:
      status = GIMP_PDB_CALLING_ERROR;
      break;
    case GIMP_RUN_INTERACTIVE:
      dialog(drawable);
      break;
          case GIMP_RUN_WITH_LAST_VALS:
      /*  Possibly retrieve data  */
      //gimp_get_data (GIDOC_TRANSCRIPTIONS_KEY_VALS, &vals);
      break;
    default:
      break;
  }
  /********************   RUN SECTION   ************************/    
  if (status == GIMP_PDB_SUCCESS)
 
  values[0].type = GIMP_PDB_STATUS;
  values[0].data.d_status = status;
}

gboolean dialog (GimpDrawable *drawable) {
  /*  widget variables  */
  GtkWidget *dlg;
  GtkWidget *main_vbox;
  GtkWidget *frame;
  GtkWidget *hbox;
  GtkWidget *label;
  GtkWidget *spin_width, *spin_height;
  GtkWidget *preview;
  gboolean   run = FALSE;
  redraw_info info;

  gimp_ui_init ("test", TRUE);

  dlg = gimp_dialog_new ("test", "test",
                         NULL, 0,
                         gimp_standard_help_func, "test",

                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                         GTK_STOCK_OK,     GTK_RESPONSE_OK,

                         NULL);

  /*  FIXME The window doesn't fit the scrowable zone...  */
  main_vbox = gtk_vbox_new (FALSE, 12);
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dlg)->vbox), main_vbox);


  frame = gimp_frame_new("Preview");
  gtk_box_pack_start (GTK_BOX (main_vbox), frame,FALSE,FALSE, 0);

  hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), hbox);

  preview = gimp_preview_area_new();
  gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0);

  g_signal_connect (preview, "size-allocate", G_CALLBACK (size_changed), &info);

  info.x1 = 0; info.y1 = 0;
  info.height = 100; info.width = 100;
  info.drawable = drawable; info.preview = preview; info.frame = frame;

  gtk_widget_set_size_request (GTK_WIDGET (preview),
                               info.width, info.height);

  gtk_widget_show_all (frame);

  hbox = gtk_hbox_new (FALSE, 12);
  gtk_box_pack_start (GTK_BOX (main_vbox), hbox,FALSE,FALSE, 0);
  label = gtk_label_new("width");
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE,FALSE, 0);
  spin_width = gtk_spin_button_new_with_range(100,
     gimp_drawable_width(drawable->drawable_id),1);  
  g_signal_connect(G_OBJECT(spin_width),"value-changed",
      G_CALLBACK(change_width),&info);
  gtk_box_pack_start (GTK_BOX (hbox), spin_width, FALSE,FALSE, 0);
  label = gtk_label_new("height");
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE,FALSE, 0);
  spin_height = gtk_spin_button_new_with_range(100,
     gimp_drawable_height(drawable->drawable_id),1);  
  g_signal_connect(G_OBJECT(spin_height),"value-changed",
      G_CALLBACK(change_height),&info);
  gtk_box_pack_start (GTK_BOX (hbox), spin_height, FALSE,FALSE, 0);
 
  gtk_widget_show_all(hbox);

  gtk_widget_show (main_vbox);
  gtk_widget_show (dlg);

  /*  put an initial preview  */
  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);

  gimp_displays_flush ();

  gtk_widget_destroy (dlg);

  return run;
}

void change_width(GtkSpinButton *p, gpointer data){
  redraw_info *info = data;

  info->width = gtk_spin_button_get_value(p);

  gtk_widget_set_size_request((GtkWidget *) info->preview,
      info->width,info->height);
}

void change_height(GtkSpinButton *p, gpointer data){
  redraw_info *info = data;

  info->height = gtk_spin_button_get_value(p);

  gtk_widget_set_size_request (GTK_WIDGET (info->preview),
                               info->width, info->height);
}

static void
size_changed (GimpPreviewArea *preview,
              GtkAllocation   *allocation,
              redraw_info     *info)
{
  GimpPixelRgn rgn_input; guchar *buf;  gint i;

  buf = g_newa (guchar, info->width);

  gimp_pixel_rgn_init (&rgn_input,
                       info->drawable,
                       0,0,
                       info->width, info->height,
                       FALSE, FALSE);

  for (i=0; i<info->height; i++)
    {
      gimp_pixel_rgn_get_row (&rgn_input,buf,0,i,info->width);
      gimp_preview_area_draw (GIMP_PREVIEW_AREA(info->preview),
                              0, i,
                              info->width, 1,
                              GIMP_GRAY_IMAGE, buf, info->width);
    }
}


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Nicolás Serrano Martínez Santos :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks! Now it works as it will be expected. I didn't notice that signal in the API before...

El 09/05/2008, a las 12:36, Sven Neumann escribió:

You need to redraw the preview-area everytime it's size changes. It

doesn't keep the buffer across size changes. I have attached a modified

version of your test code that does the right thing.



_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Problem refreshing GimpPreviewArea

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Fri, 2008-05-09 at 12:53 +0200, Nicolás Serrano Martínez Santos
wrote:
> Thanks! Now it works as it will be expected. I didn't notice that
> signal in the API before...

GimpPreviewArea is derived from GtkDrawingArea. It inherits all
functions and signals from its parent classes, including
GtkWidget::size-allocate.


Sven


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer