Пример #1
0
  gboolean
  gegl_rectangle_intersect (GeglRectangle       *dest,
                            const GeglRectangle *src1,
                            const GeglRectangle *src2)
  {
    gint x1, x2, y1, y2;

    x1 = MAX (src1->x, src2->x);
    x2 = MIN (src1->x + src1->width, src2->x + src2->width);

    if (x2 <= x1)
      {
        if (dest)
          gegl_rectangle_set (dest, 0, 0, 0, 0);
        return FALSE;
      }

    y1 = MAX (src1->y, src2->y);
    y2 = MIN (src1->y + src1->height, src2->y + src2->height);

    if (y2 <= y1)
      {
        if (dest)
          gegl_rectangle_set (dest, 0, 0, 0, 0);
        return FALSE;
      }

    if (dest)
      gegl_rectangle_set (dest, x1, y1, x2 - x1, y2 - y1);
    return TRUE;
  }
Пример #2
0
MyPaintGeglTiledSurface *
mypaint_gegl_tiled_surface_new(void)
{
    MyPaintGeglTiledSurface *self = (MyPaintGeglTiledSurface *)malloc(sizeof(MyPaintGeglTiledSurface));

    mypaint_tiled_surface_init(&self->parent, tile_request_start, tile_request_end);

    // MyPaintSurface vfuncs
    self->parent.parent.destroy = free_gegl_tiledsurf;
    self->parent.parent.save_png = save_png;

    self->parent.threadsafe_tile_requests = TRUE;

    self->buffer = NULL;

    gegl_rectangle_set(&self->extent_rect, 0, 0, 0, 0);

    self->format = babl_format_new(babl_model ("R'aG'aB'aA"), babl_type ("u15"),
                             babl_component("R'a"), babl_component("G'a"), babl_component("B'a"), babl_component("A"),
                             NULL);
    g_assert(self->format);

    mypaint_gegl_tiled_surface_set_buffer(self, NULL);

    return self;
}
Пример #3
0
static void
tile_request_end(MyPaintTiledSurface *tiled_surface, MyPaintTileRequest *request)
{
    MyPaintGeglTiledSurface *self = (MyPaintGeglTiledSurface *)tiled_surface;

    if (buffer_is_native(self)) {
        GeglBufferIterator *iterator = (GeglBufferIterator *)request->context;

        if (iterator) {
            gegl_buffer_iterator_next(iterator);
            request->context = NULL;
        }
    } else {
        // Push our linear buffer back into the GeglBuffer
        const int tile_size = tiled_surface->tile_size;
        GeglRectangle tile_bbox;

        g_assert(request->buffer);
        gegl_rectangle_set(&tile_bbox, request->tx*tile_size, request->ty*tile_size, tile_size, tile_size);
        gegl_buffer_set(self->buffer, &tile_bbox, 0, self->format,
                        request->buffer, GEGL_AUTO_ROWSTRIDE);
        gegl_free(request->buffer);
    }

}
Пример #4
0
  void
  gegl_rectangle_bounding_box (GeglRectangle       *dest,
                               const GeglRectangle *src1,
                               const GeglRectangle *src2)
  {
    gboolean s1_has_area = src1->width && src1->height;
    gboolean s2_has_area = src2->width && src2->height;

    if (!s1_has_area && !s2_has_area)
      gegl_rectangle_set (dest, 0, 0, 0, 0);
    else if (!s1_has_area)
      gegl_rectangle_copy (dest, src2);
    else if (!s2_has_area)
      gegl_rectangle_copy (dest, src1);
    else
      {
        gint x1 = MIN (src1->x, src2->x);
        gint x2 = MAX (src1->x + src1->width, src2->x + src2->width);
        gint y1 = MIN (src1->y, src2->y);
        gint y2 = MAX (src1->y + src1->height, src2->y + src2->height);

        dest->x      = x1;
        dest->y      = y1;
        dest->width  = x2 - x1;
        dest->height = y2 - y1;
      }
  }
Пример #5
0
static void
tile_request_start(MyPaintTiledSurface *tiled_surface, MyPaintTileRequest *request)
{
    MyPaintGeglTiledSurface *self = (MyPaintGeglTiledSurface *)tiled_surface;

    const int tile_size = tiled_surface->tile_size;
    GeglRectangle tile_bbox;
    gegl_rectangle_set(&tile_bbox, request->tx * tile_size, request->ty * tile_size, tile_size, tile_size);

    int read_write_flags;

    if (request->readonly) {
        read_write_flags = GEGL_BUFFER_READ;
    } else {
        read_write_flags = GEGL_BUFFER_READWRITE;

        // Extend the bounding box
        gegl_rectangle_bounding_box(&self->extent_rect, &self->extent_rect, &tile_bbox);
        gboolean success = gegl_buffer_set_extent(self->buffer, &self->extent_rect);
        g_assert(success);
    }

    if (buffer_is_native(self)) {
        GeglBufferIterator *iterator = gegl_buffer_iterator_new(self->buffer, &tile_bbox, 0, self->format,
                                      read_write_flags, GEGL_ABYSS_NONE);

        // Read out
        gboolean completed = gegl_buffer_iterator_next(iterator);
        g_assert(completed);

        if (iterator->length != tile_size*tile_size) {
            g_critical("Unable to get tile aligned access to GeglBuffer");
            request->buffer = NULL;
        } else {
            request->buffer = (uint16_t *)(iterator->data[0]);
        }

        // So we can finish the iterator in tile_request_end()
        request->context = (void *)iterator;
    } else {
        // Extract a linear rectangular chunk of appropriate BablFormat,
        // potentially triggering copying and color conversions
        request->buffer = alloc_for_format(self->format, tile_size*tile_size);
        gegl_buffer_get(self->buffer, &tile_bbox, 1, self->format,
                        request->buffer, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
        g_assert(request->buffer);
    }
}
Пример #6
0
/* Create a layer with the provided image data and add it to the image */
gboolean create_layer(gint32   image_ID,
                      uint8_t *layer_data,
                      gint32   position,
                      gchar   *name,
                      gint     width,
                      gint     height,
                      gint32   offsetx,
                      gint32   offsety)
{
    gint32        layer_ID;
#ifdef GIMP_2_9
    GeglBuffer   *geglbuffer;
    GeglRectangle extent;
#else
    GimpDrawable *drawable;
    GimpPixelRgn  region;
#endif

    layer_ID = gimp_layer_new(image_ID,
                              name,
                              width, height,
	                          GIMP_RGBA_IMAGE,
	                          100,
                              GIMP_NORMAL_MODE);

#ifdef GIMP_2_9
	/* Retrieve the buffer for the layer */
	geglbuffer = gimp_drawable_get_buffer(layer_ID);

	/* Copy the image data to the region */
    gegl_rectangle_set(&extent, 0, 0, width, height);
    gegl_buffer_set(geglbuffer, &extent, 0, NULL, layer_data, GEGL_AUTO_ROWSTRIDE);

	/* Flush the drawable and detach */
    gegl_buffer_flush(geglbuffer);

	g_object_unref(geglbuffer);
#else
    /* Retrieve the drawable for the layer */
    drawable = gimp_drawable_get(layer_ID);

    /* Get a pixel region from the layer */
    gimp_pixel_rgn_init(&region,
                        drawable,
                        0, 0,
                        width, height,
                        FALSE, FALSE);

    /* Copy the image data to the region */
    gimp_pixel_rgn_set_rect(&region,
                            layer_data,
                            0, 0,
                            width, height);

    /* Flush the drawable and detach */
    gimp_drawable_flush(drawable);
    gimp_drawable_detach(drawable);
#endif

    /* Add the new layer to the image */
    gimp_image_insert_layer(image_ID, layer_ID, -1, position);

    /* If layer offsets were provided, use them to position the image */
    if (offsetx || offsety) {
        gimp_layer_set_offsets(layer_ID, offsetx, offsety);
    }

    /* TODO: fix this */
    return TRUE;
}
Пример #7
0
static gint
gegl_buffer_import_png (GeglBuffer  *gegl_buffer,
                        GInputStream *stream,
                        gint         dest_x,
                        gint         dest_y,
                        gint        *ret_width,
                        gint        *ret_height,
                        const Babl  *format, // can be NULL
                        GError **err)
{
  gint           width;
  gint           bit_depth;
  gint           bpp;
  gint           number_of_passes=1;
  png_uint_32    w;
  png_uint_32    h;
  png_structp    load_png_ptr;
  png_infop      load_info_ptr;
  guchar        *pixels;
  /*png_bytep     *rows;*/


  unsigned   int i;
  png_bytep  *row_p = NULL;

  g_return_val_if_fail(stream, -1);

  if (!check_valid_png_header(stream, err))
    {
      return -1;
    }

  load_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, error_fn, NULL);

  if (!load_png_ptr)
    {
      return -1;
    }

  load_info_ptr = png_create_info_struct (load_png_ptr);
  if (!load_info_ptr)
    {
      png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
      return -1;
    }

  if (setjmp (png_jmpbuf (load_png_ptr)))
    {
      png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
     if (row_p)
        g_free (row_p);
      return -1;
    }

  png_set_read_fn(load_png_ptr, stream, read_fn);

  png_set_sig_bytes (load_png_ptr, 8); // we already read header
  png_read_info (load_png_ptr, load_info_ptr);
  {
    int color_type;
    int interlace_type;

    png_get_IHDR (load_png_ptr,
                  load_info_ptr,
                  &w, &h,
                  &bit_depth,
                  &color_type,
                  &interlace_type,
                  NULL, NULL);
    width = w;
    if (ret_width)
      *ret_width = w;
    if (ret_height)
      *ret_height = h;

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      {
        png_set_expand (load_png_ptr);
        bit_depth = 8;
      }

    if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_tRNS))
      {
        png_set_tRNS_to_alpha (load_png_ptr);
        color_type |= PNG_COLOR_MASK_ALPHA;
      }

    switch (color_type)
      {
        case PNG_COLOR_TYPE_GRAY:
          bpp = 1;
          break;
        case PNG_COLOR_TYPE_GRAY_ALPHA:
          bpp = 2;
          break;
        case PNG_COLOR_TYPE_RGB:
          bpp = 3;
          break;
        case PNG_COLOR_TYPE_RGB_ALPHA:
          bpp = 4;
          break;
        case (PNG_COLOR_TYPE_PALETTE | PNG_COLOR_MASK_ALPHA):
          bpp = 4;
          break;
        case PNG_COLOR_TYPE_PALETTE:
          bpp = 3;
          break;
        default:
          g_warning ("color type mismatch");
          png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
          return -1;
      }

    if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb (load_png_ptr);

    if (bit_depth == 16)
      bpp = bpp << 1;

    if (!format)
      format = get_babl_format(bit_depth, color_type);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth == 16)
      png_set_swap (load_png_ptr);
#endif

    if (interlace_type == PNG_INTERLACE_ADAM7)
      number_of_passes = png_set_interlace_handling (load_png_ptr);

    if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_gAMA))
      {
        gdouble gamma;
        png_get_gAMA (load_png_ptr, load_info_ptr, &gamma);
        png_set_gamma (load_png_ptr, 2.2, gamma);
      }
    else
      {
        png_set_gamma (load_png_ptr, 2.2, 0.45455);
      }

    png_read_update_info (load_png_ptr, load_info_ptr);
  }

  pixels = g_malloc0 (width*bpp);

  {
    gint           pass;
    GeglRectangle  rect;

    for (pass=0; pass<number_of_passes; pass++)
      {
        for(i=0; i<h; i++)
          {
            gegl_rectangle_set (&rect, 0, i, width, 1);

            if (pass != 0)
              gegl_buffer_get (gegl_buffer, &rect, 1.0, format, pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

            png_read_rows (load_png_ptr, &pixels, NULL, 1);
            gegl_buffer_set (gegl_buffer, &rect, 0, format, pixels,
                             GEGL_AUTO_ROWSTRIDE);
          }
      }
  }


  png_read_end (load_png_ptr, NULL);
  png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);

  g_free (pixels);

  return 0;
}
Пример #8
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *roi,
         gint                 level)
{
    gint          components;
    gint          col, c;
    gfloat       *rowbefore;
    gfloat       *rowthis;
    gfloat       *rowafter;
    gfloat       *dest;
    gfloat       *ninepix;
    gboolean      has_alpha;
    guint         alpha;
    const Babl   *format = gegl_operation_get_format (operation, "input");

    /* The rectangle of the current row we are working on */
    GeglRectangle rowrect;

    /* The rectangle of the sample we are going to take for the
     * next line (this does include the interpolation distance!) */
    GeglRectangle rownext_bufrect;

    components = babl_format_get_n_components (format);
    has_alpha  = babl_format_has_alpha (format);
    alpha      = components - 1;

    /* The original algorithm that appeared in GIMP did a manual clamping
     * of samples outside the input rectangle, by always allocating a
     * buffer which is 1-pixel wider than necessary, and then filling the
     * edges of the buffer with repetitions of the edges.
     * We don't need this complexity here thanks to the CLAMP abyss policy
     * which is implemented by GEGL. We still allocate buffers which are
     * larger, but we let GEGL fill the edges with the clamped values.
     */

    rowbefore  = g_new (gfloat, (roi->width + 2) * components);
    rowthis    = g_new (gfloat, (roi->width + 2) * components);
    rowafter   = g_new (gfloat, (roi->width + 2) * components);
    dest       = g_new (gfloat, roi->width * components);
    ninepix    = g_new (gfloat, 9 * components);

    gegl_rectangle_set (&rowrect, roi->x, roi->y, roi->width, 1);
    gegl_rectangle_set (&rownext_bufrect, roi->x - 1, roi->y - 1, roi->width + 2, 1);

    gegl_buffer_get (input, &rownext_bufrect, 1.0, format,
                     rowbefore, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
    ++rownext_bufrect.y;

    gegl_buffer_get (input, &rownext_bufrect, 1.0, format,
                     rowthis, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
    ++rownext_bufrect.y;

    gegl_buffer_get (input, &rownext_bufrect, 1.0, format,
                     rowafter, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
    ++rownext_bufrect.y;

    for (rowrect.y = roi->y; rowrect.y < (roi->y + roi->height); ++rowrect.y)
    {
        gfloat *tmp;

        /* this macro returns the current pixel if it has some opacity. Otherwise
         * it returns the center pixel of the current 3x3 area. */
#define USE_IF_ALPHA(p) (((!has_alpha) || *((p)+alpha)) ? (p) : &rowthis[(col+1) * components])

        for (col = 0; col < roi->width; ++col)
        {
            /* do 9x extrapolation pass */
            if (((!has_alpha) || (rowthis[(col + 1) * components + alpha] > 0)) &&
                    extrapolate9 (components,
                                  &ninepix[0 * components],
                                  &ninepix[1 * components],
                                  &ninepix[2 * components],
                                  &ninepix[3 * components],
                                  &ninepix[4 * components],
                                  &ninepix[5 * components],
                                  &ninepix[6 * components],
                                  &ninepix[7 * components],
                                  &ninepix[8 * components],
                                  USE_IF_ALPHA (&rowbefore[(col + 0) * components]),
                                  USE_IF_ALPHA (&rowbefore[(col + 1) * components]),
                                  USE_IF_ALPHA (&rowbefore[(col + 2) * components]),
                                  USE_IF_ALPHA (&rowthis  [(col + 0) * components]),
                                  &rowthis  [(col + 1) * components],
                                  USE_IF_ALPHA (&rowthis  [(col + 2) * components]),
                                  USE_IF_ALPHA (&rowafter [(col + 0) * components]),
                                  USE_IF_ALPHA (&rowafter [(col + 1) * components]),
                                  USE_IF_ALPHA (&rowafter [(col + 2) * components])
                                 ))
            {
                /* subsample results and put into dest */
                for (c = 0; c < components; ++c)
                {
#define NINEPIX(index, c) ninepix[(index) * components + (c)]
                    dest[(col * components) + c] =
                        (3 * NINEPIX(0, c) + 5 * NINEPIX(1, c) + 3 * NINEPIX(2, c) +
                         5 * NINEPIX(3, c) + 6 * NINEPIX(4, c) + 5 * NINEPIX(5, c) +
                         3 * NINEPIX(6, c) + 5 * NINEPIX(7, c) + 3 * NINEPIX(8, c)
                         /* The GIMP implementation added 19 (out of 255) here before
                          * normalizing (dividing by 38), which is equivalent to a
                          * call to "ceil". We don't need this since we are working
                          * with floating point numbers... */
                        ) / 38;
#undef NINEPIX
                }
            }
            else
            {
                memcpy (&dest[col * components], &rowthis[(col + 1) * components], components * sizeof(gfloat));
            }
        }

#undef USE_IF_ALPHA

        /* write result row to dest */
        gegl_buffer_set (output, &rowrect, 0, format, &dest[0], GEGL_AUTO_ROWSTRIDE);

        /* rotate pointers */
        tmp       = rowbefore;
        rowbefore = rowthis;
        rowthis   = rowafter;
        rowafter  = tmp;

        /* populate new after-row */
        gegl_buffer_get (input, &rownext_bufrect, 1.0, format,
                         rowafter, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
        ++rownext_bufrect.y;
    }

    g_free (rowbefore);
    g_free (rowthis);
    g_free (rowafter);
    g_free (dest);
    g_free (ninepix);

    return  TRUE;
}