Page 1 of 1

ImageMagick + Drawing + Gtk3 + Linux

Posted: 2012-10-20T23:59:24-07:00
by harestomper
Hello!
I have the problem with a combination of ImageMagick + Draw + GTK3 + Linux. We have an original image (image 1). Code that spread below, works as expected when it excludes functions gtk_init and show_image. This creates rounded corners (image 2) with radiuces from the array corners, regardless of whether I use relative or absolute coordinates. Image 3 you can see how to break the result after enabling gtk_init. In the image 4, the is reslut of the function show_image.Image 3 and 4 that only a portion of the original image, because it turns out wrong coordinates of endpoints.
Why it makes ImageMagick and how can I solve this problem?
1)Image 2)Image 3)Image 4)Image

Code: Select all

#include <stdio.h>
#include <wand/magick_wand.h>
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>

enum {
    NIM_CORNER_TL,
    NIM_CORNER_TR,
    NIM_CORNER_BR,
    NIM_CORNER_BL,
    NIM_CORNER_LAST
};

void window_destroy_cb (GtkWidget *widget)
{
  gtk_main_quit ();
}

/*
  Function to convert MagickWand to GdkPixbuf and show this in the GtkWindow
*/
void show_image (MagickWand *wand)
{
  GdkPixbuf *pixbuf;
  gint width;
  gint height;
  gint rowstride;
  gint row;
  guchar *pixels;

  width = MagickGetImageWidth (wand);
  height = MagickGetImageHeight (wand);
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
  pixels = gdk_pixbuf_get_pixels (pixbuf);
  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
  MagickSetImageDepth (wand, 8);

  for (row = 0; row < height; row++) {
      guchar *data = pixels + row * rowstride;
      MagickExportImagePixels (wand, 0, row, width, 1, "RGBA", CharPixel, data);
  }

  if (pixbuf) {
    GtkWidget *image;
    GtkWidget *window;

    image = gtk_image_new_from_pixbuf (pixbuf);
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_container_add (GTK_CONTAINER (window), image);
    gtk_widget_show_all (window);
    g_signal_connect (window, "destroy", G_CALLBACK (window_destroy_cb), NULL);
    gtk_main ();
  }  
}


/*
  Function to create the rounding corners and save result to test file.
*/
gboolean nim_imaging_round_corners (gchar *filename, const gdouble corners [NIM_CORNER_LAST])
{
  gboolean response = FALSE;
  MagickWand *m_wand = NULL;
  MagickWand *l_wand = NULL;
  PixelWand *p_wand = NULL;
  DrawingWand *d_wand = NULL;
  gdouble width, height;

  gdouble ctl = ABS (corners [NIM_CORNER_TL]);
  gdouble cbl = ABS (corners [NIM_CORNER_BL]);
  gdouble ctr = ABS (corners [NIM_CORNER_TR]);
  gdouble cbr = ABS (corners [NIM_CORNER_BR]);
  gdouble x, y;

// Padding 
#define LIMIT 1.5

  MagickWandGenesis ();

  m_wand = NewMagickWand ();
  l_wand = NewMagickWand ();
  p_wand = NewPixelWand ();
  d_wand = NewDrawingWand ();

  MagickReadImage (l_wand, filename);
  width = (gdouble) MagickGetImageWidth (l_wand);
  height = (gdouble) MagickGetImageHeight (l_wand);

  PixelSetColor (p_wand, "none");
  MagickNewImage (m_wand, width, height, p_wand);

  width -= LIMIT;
  height -= LIMIT;

  PixelSetColor (p_wand, "white");
  DrawSetFillColor (d_wand, p_wand);

  DrawPathStart (d_wand);

  /*
    I tring the absolute and relative coordinates
    but its work without GTK and failed with GTK.
    WHY???
  */
  DrawPathMoveToAbsolute (d_wand, ctl, LIMIT);
  DrawPathLineToHorizontalAbsolute (d_wand, width - ctr);

  if (corners [NIM_CORNER_TR] >= 0) {
    x = width;
    y = LIMIT;
  } else {
    x = width - ctr;
    y = ctr;
  }

  DrawPathCurveToQuadraticBezierAbsolute (d_wand, x, y, width, ctr);
  DrawPathLineToVerticalAbsolute (d_wand, height - cbr);

  if (corners [NIM_CORNER_BR] >= 0) {
    x = width;
    y = height;
  } else {
    x = width - cbr;
    y = height - cbr;
  }

  DrawPathCurveToQuadraticBezierAbsolute (d_wand, x, y, width - cbr, height);
  DrawPathLineToHorizontalAbsolute (d_wand, cbl);

  if (corners [NIM_CORNER_BL] >= 0) {
    x = LIMIT;
    y = height;
  } else {
    x = cbl;
    y = height - cbl;
  }

  DrawPathCurveToQuadraticBezierAbsolute (d_wand, x, y, LIMIT, height - cbl);
  DrawPathLineToVerticalAbsolute (d_wand, ctl);

  if (corners [NIM_CORNER_TL] >= 0) {
    x = LIMIT;
    y = LIMIT;
  } else {
    x = ctl;
    y = ctl;
  }

  DrawPathCurveToQuadraticBezierAbsolute (d_wand, x, y, ctl, LIMIT);
  DrawPathClose (d_wand);

  DrawPathFinish (d_wand);
  MagickDrawImage (m_wand, d_wand);

  MagickCompositeImage (m_wand, l_wand, SrcInCompositeOp, 0, 0);
  MagickWriteImage (m_wand, "mask_result.png");

  // Comment this line to exclude creates GdkPixbuf and GtkWindow
  show_image (m_wand);

  if (m_wand)
    m_wand = DestroyMagickWand (m_wand);

  if (l_wand)
    l_wand = DestroyMagickWand (l_wand);

  if (d_wand)
    d_wand = DestroyDrawingWand (d_wand);

  if (p_wand)
    p_wand = DestroyPixelWand (p_wand);

  MagickWandTerminus ();

  return response;
}


int main(int argc, char **argv)
{
  // Array of the radiuces of the corners
  gdouble corners [NIM_CORNER_LAST] = {-15.0, 15.0, -15.0, 15.0};

  // Comment this line to exclude GTK
  gtk_init (&argc, &argv);
  nim_imaging_round_corners (argv [1], corners);

  return 0;
}
Technical data:
ImageMagick 6.7.9.8
Built the ImageMagick with flags:

Code: Select all

    --with-modules 
    --disable-static
    --disable-openmp 
    --with-wmf 
    --with-openexr 
    --with-xml 
    --with-lcms2 
    --with-jp2 
    --with-gslib 
    --with-gs-font-dir=/usr/share/fonts/Type1
    --with-perl 
    --with-perl-options="INSTALLDIRS=vendor" 
    --with-lqr 
    --with-rsvg 
    --without-gvc 
    --without-djvu 
    --without-autotrace 
    --without-webp 
    --without-jbig 
    --without-fpx 
    --without-dps 
    --without-fftw
Hosts: ArchLinux x86_64 and Ubuntu 12.04.1 LTS i386
GTK3: gtk+-3.0 3.4.4


Link to download archive
https://docs.google.com/open?id=0B7bPA0 ... zl5cDFtUEk

Re: ImageMagick + Drawing + Gtk3 + Linux

Posted: 2012-10-21T12:04:37-07:00
by harestomper
Solved!
The problem is that when I was called gtk_init, then ImageMagick misbehaves with non integer coordinates​, that is, the fractional part is not rounded to zero. In my case, it's a macro LIMIT, which is equal to 1.5. If I set its to, for example, to 2.0 or 1.0 or make "floor" or "ceil" for coordinates or start without called gtk_init then no problem.
Thank you for your quick response. :)