コード例 #1
0
ファイル: gimp-gegl-loops.c プロジェクト: SHIVAPRASAD96/gimp
void
gimp_gegl_convolve (GeglBuffer          *src_buffer,
                    const GeglRectangle *src_rect,
                    GeglBuffer          *dest_buffer,
                    const GeglRectangle *dest_rect,
                    const gfloat        *kernel,
                    gint                 kernel_size,
                    gdouble              divisor,
                    GimpConvolutionType  mode,
                    gboolean             alpha_weighting)
{
  GeglBufferIterator *dest_iter;
  gfloat             *src;
  gint                src_rowstride;

  const Babl         *src_format;
  const Babl         *dest_format;
  gint                src_components;
  gint                dest_components;

  src_format = gegl_buffer_get_format (src_buffer);

  if (babl_format_is_palette (src_format))
    src_format = gimp_babl_format (GIMP_RGB,
                                   GIMP_PRECISION_FLOAT_LINEAR,
                                   babl_format_has_alpha (src_format));
  else
    src_format = gimp_babl_format (gimp_babl_format_get_base_type (src_format),
                                   GIMP_PRECISION_FLOAT_LINEAR,
                                   babl_format_has_alpha (src_format));

  dest_format = gegl_buffer_get_format (dest_buffer);

  if (babl_format_is_palette (dest_format))
    dest_format = gimp_babl_format (GIMP_RGB,
                                    GIMP_PRECISION_FLOAT_LINEAR,
                                    babl_format_has_alpha (dest_format));
  else
    dest_format = gimp_babl_format (gimp_babl_format_get_base_type (dest_format),
                                    GIMP_PRECISION_FLOAT_LINEAR,
                                    babl_format_has_alpha (dest_format));

  src_components  = babl_format_get_n_components (src_format);
  dest_components = babl_format_get_n_components (dest_format);

  /* Set up dest iterator */
  dest_iter = gegl_buffer_iterator_new (dest_buffer, dest_rect, 0, dest_format,
                                        GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);

  /* Get source pixel data */
  src_rowstride = src_components * src_rect->width;
  src = g_malloc (sizeof(gfloat) * src_rowstride * src_rect->height);
  gegl_buffer_get (src_buffer, src_rect, 1.0, src_format, src,
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  while (gegl_buffer_iterator_next (dest_iter))
    {
      /*  Convolve the src image using the convolution kernel, writing
       *  to dest Convolve is not tile-enabled--use accordingly
       */
      gfloat       *dest        = dest_iter->data[0];
      const gint    components  = src_components;
      const gint    a_component = components - 1;
      const gint    margin      = kernel_size / 2;
      const gint    x1          = 0;
      const gint    y1          = 0;
      const gint    x2          = src_rect->width  - 1;
      const gint    y2          = src_rect->height - 1;
      const gint    dest_x1     = dest_iter->roi[0].x;
      const gint    dest_y1     = dest_iter->roi[0].y;
      const gint    dest_x2     = dest_iter->roi[0].x + dest_iter->roi[0].width;
      const gint    dest_y2     = dest_iter->roi[0].y + dest_iter->roi[0].height;
      gint          x, y;
      gfloat        offset;

      /*  If the mode is NEGATIVE_CONVOL, the offset should be 128  */
      if (mode == GIMP_NEGATIVE_CONVOL)
        {
          offset = 0.5;
          mode = GIMP_NORMAL_CONVOL;
        }
      else
        {
          offset = 0.0;
        }

      for (y = dest_y1; y < dest_y2; y++)
        {
          gfloat *d = dest;

          if (alpha_weighting)
            {
              for (x = dest_x1; x < dest_x2; x++)
                {
                  const gfloat *m                = kernel;
                  gdouble       total[4]         = { 0.0, 0.0, 0.0, 0.0 };
                  gdouble       weighted_divisor = 0.0;
                  gint          i, j, b;

                  for (j = y - margin; j <= y + margin; j++)
                    {
                      for (i = x - margin; i <= x + margin; i++, m++)
                        {
                          gint          xx = CLAMP (i, x1, x2);
                          gint          yy = CLAMP (j, y1, y2);
                          const gfloat *s  = src + yy * src_rowstride + xx * components;
                          const gfloat  a  = s[a_component];

                          if (a)
                            {
                              gdouble mult_alpha = *m * a;

                              weighted_divisor += mult_alpha;

                              for (b = 0; b < a_component; b++)
                                total[b] += mult_alpha * s[b];

                              total[a_component] += mult_alpha;
                            }
                        }
                    }

                  if (weighted_divisor == 0.0)
                    weighted_divisor = divisor;

                  for (b = 0; b < a_component; b++)
                    total[b] /= weighted_divisor;

                  total[a_component] /= divisor;

                  for (b = 0; b < components; b++)
                    {
                      total[b] += offset;

                      if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0)
                        total[b] = - total[b];

                      *d++ = CLAMP (total[b], 0.0, 1.0);
                    }
                }
            }
          else
            {
              for (x = dest_x1; x < dest_x2; x++)
                {
                  const gfloat *m        = kernel;
                  gdouble       total[4] = { 0.0, 0.0, 0.0, 0.0 };
                  gint          i, j, b;

                  for (j = y - margin; j <= y + margin; j++)
                    {
                      for (i = x - margin; i <= x + margin; i++, m++)
                        {
                          gint          xx = CLAMP (i, x1, x2);
                          gint          yy = CLAMP (j, y1, y2);
                          const gfloat *s  = src + yy * src_rowstride + xx * components;

                          for (b = 0; b < components; b++)
                            total[b] += *m * s[b];
                        }
                    }

                  for (b = 0; b < components; b++)
                    {
                      total[b] = total[b] / divisor + offset;

                      if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0)
                        total[b] = - total[b];

                      *d++ = CLAMP (total[b], 0.0, 1.0);
                    }
                }
            }

          dest += dest_iter->roi[0].width * dest_components;
        }
    }

  g_free (src);
}
コード例 #2
0
GtkWidget *
convert_precision_dialog_new (GimpImage         *image,
                              GimpContext       *context,
                              GtkWidget         *parent,
                              GimpComponentType  component_type,
                              GimpProgress      *progress)
{
  ConvertDialog *dialog;
  GtkWidget     *button;
  GtkWidget     *main_vbox;
  GtkWidget     *vbox;
  GtkWidget     *hbox;
  GtkWidget     *label;
  GtkWidget     *frame;
  GtkWidget     *combo;
  GtkSizeGroup  *size_group;
  const gchar   *enum_desc;
  gchar         *blurb;
  GType          dither_type;
  const Babl    *format;
  gint           bits;
  gboolean       linear;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);

  dialog = g_slice_new0 (ConvertDialog);

  /* a random format with precision */
  format = gimp_babl_format (GIMP_RGB, gimp_babl_precision (component_type,
                                                            FALSE), FALSE);
  bits   = (babl_format_get_bytes_per_pixel (format) * 8 /
            babl_format_get_n_components (format));

  linear = gimp_babl_format_get_linear (gimp_image_get_layer_format (image,
                                                                     FALSE));

  dialog->image          = image;
  dialog->progress       = progress;
  dialog->component_type = component_type;
  dialog->linear         = linear;
  dialog->bits           = bits;

  /* gegl:color-reduction only does 16 bits */
  if (bits <= 16)
    {
      dialog->layer_dither_type      = saved_layer_dither_type;
      dialog->text_layer_dither_type = saved_text_layer_dither_type;
      dialog->mask_dither_type       = saved_mask_dither_type;
    }

  gimp_enum_get_value (GIMP_TYPE_COMPONENT_TYPE, component_type,
                       NULL, NULL, &enum_desc, NULL);

  blurb = g_strdup_printf (_("Convert Image to %s"), enum_desc);

  dialog->dialog =
    gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context,
                              _("Precision Conversion"),
                              "gimp-image-convert-precision",
                              GIMP_STOCK_CONVERT_PRECISION,
                              blurb,
                              parent,
                              gimp_standard_help_func,
                              GIMP_HELP_IMAGE_CONVERT_PRECISION,

                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,

                              NULL);

  g_free (blurb);

  button = gtk_dialog_add_button (GTK_DIALOG (dialog->dialog),
                                  _("C_onvert"), GTK_RESPONSE_OK);
  gtk_button_set_image (GTK_BUTTON (button),
                        gtk_image_new_from_icon_name (GIMP_STOCK_CONVERT_PRECISION,
                                                      GTK_ICON_SIZE_BUTTON));

  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog->dialog),
                                           GTK_RESPONSE_OK,
                                           GTK_RESPONSE_CANCEL,
                                           -1);

  gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE);

  g_object_weak_ref (G_OBJECT (dialog->dialog),
                     (GWeakNotify) convert_precision_dialog_free, dialog);

  g_signal_connect (dialog->dialog, "response",
                    G_CALLBACK (convert_precision_dialog_response),
                    dialog);

  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))),
                      main_vbox, TRUE, TRUE, 0);
  gtk_widget_show (main_vbox);


  /*  dithering  */

  dither_type = gimp_gegl_get_op_enum_type ("gegl:color-reduction",
                                            "dither-strategy");

  frame = gimp_frame_new (_("Dithering"));
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);

  /* gegl:color-reduction only does 16 bits */
  gtk_widget_set_sensitive (vbox, bits <= 16);

  size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);

  /*  layers  */

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("_Layers:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_size_group_add_widget (size_group, label);
  gtk_widget_show (label);

  combo = gimp_enum_combo_box_new (dither_type);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
  gtk_widget_show (combo);

  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
                              dialog->layer_dither_type,
                              G_CALLBACK (gimp_int_combo_box_get_active),
                              &dialog->layer_dither_type);

  /*  text layers  */

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("_Text Layers:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_size_group_add_widget (size_group, label);
  gtk_widget_show (label);

  combo = gimp_enum_combo_box_new (dither_type);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
  gtk_widget_show (combo);

  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
                              dialog->text_layer_dither_type,
                              G_CALLBACK (gimp_int_combo_box_get_active),
                              &dialog->text_layer_dither_type);

  gimp_help_set_help_data (combo,
                           _("Dithering text layers will make them uneditable"),
                           NULL);

  /*  channels  */

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("_Channels and Masks:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_size_group_add_widget (size_group, label);
  gtk_widget_show (label);

  combo = gimp_enum_combo_box_new (dither_type);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
  gtk_widget_show (combo);

  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
                              dialog->mask_dither_type,
                              G_CALLBACK (gimp_int_combo_box_get_active),
                              &dialog->mask_dither_type);

  g_object_unref (size_group);

  /*  gamma  */

  frame = gimp_frame_new (_("Gamma"));
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);

  hbox = gimp_int_radio_group_new (FALSE, NULL,
                                   G_CALLBACK (gimp_radio_button_update),
                                   &dialog->linear,
                                   linear,

                                   _("Perceptual gamma (sRGB)"), FALSE, NULL,
                                   _("Linear light"),            TRUE,  NULL,

                                   NULL);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  return dialog->dialog;
}
コード例 #3
0
ファイル: png-save.c プロジェクト: GNOME/gegl
gint
gegl_buffer_export_png (GeglBuffer  *gegl_buffer,
                        const gchar *path,
                        gint         compression,
                        gint         bd,
                        gint         src_x,
                        gint         src_y,
                        gint         width,
                        gint         height)
{
  FILE          *fp;
  gint           i;
  png_struct    *png;
  png_info      *info;
  guchar        *pixels;
  png_color_16   white;
  int            png_color_type;
  gchar          format_string[16];
  const Babl    *format;
  gint           bit_depth = 8;

  if (!strcmp (path, "-"))
    {
      fp = stdout;
    }
  else
    {
      fp = fopen (path, "wb");
    }
  if (!fp)
    {
      return -1;
    }

  {
    const Babl *babl = gegl_buffer_get_format (gegl_buffer);

    if (bd == 16)
      bit_depth = 16;
    else
      bit_depth = 8;

    if (babl_format_has_alpha (babl))
      if (babl_format_get_n_components (babl) != 2)
        {
          png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          strcpy (format_string, "R'G'B'A ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
          strcpy (format_string, "Y'A ");
        }
    else
      if (babl_format_get_n_components (babl) != 1)
        {
          png_color_type = PNG_COLOR_TYPE_RGB;
          strcpy (format_string, "R'G'B' ");
        }
      else
        {
          png_color_type = PNG_COLOR_TYPE_GRAY;
          strcpy (format_string, "Y' ");
        }
  }

  if (bit_depth == 16)
    strcat (format_string, "u16");
  else
    strcat (format_string, "u8");

  png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png == NULL)
    {
      if (stdout != fp)
        fclose (fp);

      return -1;
    }

  info = png_create_info_struct (png);

  if (setjmp (png_jmpbuf (png)))
    {
      if (stdout != fp)
        fclose (fp);

      return -1;
    }

  png_set_compression_level (png, compression);
  png_init_io (png, fp);

  png_set_IHDR (png, info,
     width, height, bit_depth, png_color_type,
     PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);

  if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    {
      white.red = 0xff;
      white.blue = 0xff;
      white.green = 0xff;
    }
  else
    white.gray = 0xff;
  png_set_bKGD (png, info, &white);

  png_write_info (png, info);

#if BYTE_ORDER == LITTLE_ENDIAN
  if (bit_depth > 8)
    png_set_swap (png);
#endif

  format = babl_format (format_string);
  pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format));

  for (i=0; i< height; i++)
    {
      GeglRectangle rect;

      rect.x = src_x;
      rect.y = src_y+i;
      rect.width = width;
      rect.height = 1;

      gegl_buffer_get (gegl_buffer, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      png_write_rows (png, &pixels, 1);
    }

  png_write_end (png, info);

  png_destroy_write_struct (&png, &info);
  g_free (pixels);

  if (stdout != fp)
    fclose (fp);

  return 0;
}
コード例 #4
0
static gboolean
process (GeglOperation       *operation,
         void                *in_buf,
         void                *out_buf,
         glong                samples,
         const GeglRectangle *roi,
         gint                 level)
{
  GeglProperties *o      = GEGL_PROPERTIES (operation);
  const Babl     *format = gegl_operation_get_format (operation, "input");
  gfloat         *in     = in_buf;
  gfloat         *out    = out_buf;
  gint            component_index = 0;
  gint            n_components;
  gdouble         min = 0.0;
  gdouble         max = 1.0;

  n_components = babl_format_get_n_components (format);

  switch (o->component)
    {
    case GEGL_COMPONENT_EXTRACT_RGB_RED:
    case GEGL_COMPONENT_EXTRACT_HUE:
    case GEGL_COMPONENT_EXTRACT_CMYK_CYAN:
    case GEGL_COMPONENT_EXTRACT_YCBCR_Y:
    case GEGL_COMPONENT_EXTRACT_LAB_L:
      component_index = 0;

      if (o->component == GEGL_COMPONENT_EXTRACT_LAB_L)
        {
          max = 100.0;
        }
      break;

    case GEGL_COMPONENT_EXTRACT_RGB_GREEN:
    case GEGL_COMPONENT_EXTRACT_HSV_SATURATION:
    case GEGL_COMPONENT_EXTRACT_HSL_SATURATION:
    case GEGL_COMPONENT_EXTRACT_CMYK_MAGENTA:
    case GEGL_COMPONENT_EXTRACT_YCBCR_CB:
    case GEGL_COMPONENT_EXTRACT_LAB_A:
    case GEGL_COMPONENT_EXTRACT_LCH_C:
    case GEGL_COMPONENT_EXTRACT_ALPHA:
      component_index = 1;

      if (o->component == GEGL_COMPONENT_EXTRACT_YCBCR_CB)
        {
          min = -0.5;
          max =  0.5;
        }
      else if (o->component == GEGL_COMPONENT_EXTRACT_LAB_A)
        {
          min = -127.5;
          max =  127.5;
        }
      else if (o->component == GEGL_COMPONENT_EXTRACT_LCH_C)
        {
          max = 200.0;
        }
      break;

    case GEGL_COMPONENT_EXTRACT_RGB_BLUE:
    case GEGL_COMPONENT_EXTRACT_HSV_VALUE:
    case GEGL_COMPONENT_EXTRACT_HSL_LIGHTNESS:
    case GEGL_COMPONENT_EXTRACT_CMYK_YELLOW:
    case GEGL_COMPONENT_EXTRACT_YCBCR_CR:
    case GEGL_COMPONENT_EXTRACT_LAB_B:
    case GEGL_COMPONENT_EXTRACT_LCH_H:
      component_index = 2;

      if (o->component == GEGL_COMPONENT_EXTRACT_YCBCR_CR)
        {
          min = -0.5;
          max =  0.5;
        }
      else if (o->component == GEGL_COMPONENT_EXTRACT_LAB_B)
        {
          min = -127.5;
          max =  127.5;
        }
      else if (o->component == GEGL_COMPONENT_EXTRACT_LCH_H)
        {
          min = 0.0;
          max = 360.0;
        }
      break;

    case GEGL_COMPONENT_EXTRACT_CMYK_KEY:
      component_index = 3;
      break;
    }

    while (samples--)
      {
        gdouble value = in[component_index];

        if (min != 0.0 || max != 1.0)
          {
            gdouble scale  = 1.0 / (max - min);
            gdouble offset = -min;

            value = CLAMP ((value + offset) * scale, 0.0, 1.0);
          }

        if (o->invert)
          out[0] = 1.0 - value;
        else
          out[0] = value;

        in  += n_components;
        out += 1;
      }


  return TRUE;
}