Example #1
0
static void
color_rotate (GimpDrawable *drawable)
{
  GimpPixelRgn srcPR, destPR;
  gint         width, height;
  gint         bytes;
  guchar      *src_row, *dest_row;
  gint         row;
  gint         x, y;

  if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &x, &y, &width, &height))
    {
      return;
    }

  bytes = drawable->bpp;

  src_row  = g_new (guchar, width * bytes);
  dest_row = g_new (guchar, width * bytes);

  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0,
                       drawable->width,
                       drawable->height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0,
                       drawable->width,
                       drawable->height, TRUE, TRUE);

  for (row = y; row < (y + height); row++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x, row, width);

      color_rotate_row (src_row, dest_row, row, width, bytes);

      gimp_pixel_rgn_set_row (&destPR, dest_row, x, row, width);

      if ((row % 10) == 0)
        gimp_progress_update ((double) row / (double) height);
    }

  /*  update the processed region  */

  gimp_progress_update (1.0);
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x, y, width, height);

  g_free (src_row);
  g_free (dest_row);
}
static gint32 load_raw(
    char*            filename,
    FILE*            file,
    enum             pix_fmt fmt,
    struct raw_data* img_data,
    const gchar*     plugin_name
) {
    gint nr_chls;
    gint x, y;
    gint32 img;
    gint32 layer;
    GimpDrawable* drawable;
    GimpPixelRgn pixel_rgn;
    guchar *pix_row;

    guint width = img_data->size[0];
    guint height = img_data->size[1];
    if (width <= 0 || height <= 0) {
	return ERROR;
    }
    img = create_new_image(filename, NULL, width, height, GIMP_RGB, &layer,
						    &drawable, &pixel_rgn);
    nr_chls = gimp_drawable_bpp(drawable->drawable_id);
    pix_row = g_new(guchar, nr_chls * width);
    x = 0;
    y = 0;
    while (1) {
        guchar rgb[3];
	if (read_rgb_pixel(file, fmt, rgb) == ERROR)
	    return ERROR;
	pix_row[nr_chls * x]     = rgb[IDX_RED];
	pix_row[nr_chls * x + 1] = rgb[IDX_GREEN];
	pix_row[nr_chls * x + 2] = rgb[IDX_BLUE];
	x++;
	if (x == width) {
	    gimp_pixel_rgn_set_row(&pixel_rgn, pix_row, 0, y, width);
	    x = 0;
	    y++;
	}
	if (y == height) break;
    }
    if (fgetc(file) != EOF) {
	printf("%s: warning: file contains more data\n", plugin_name);
    }

    return img;
}
Example #3
0
static void blur (GimpDrawable *drawable) {
	gint i, j, k, channels;
	gint x1, y1, x2, y2;
	GimpPixelRgn rgn_in, rgn_out;
	guchar *row1, *row2, *row3;
	guchar *outrow;

	gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
	channels = gimp_drawable_bpp (drawable->drawable_id);

	gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, x2 - x1, y2 - y1, FALSE, FALSE);
	gimp_pixel_rgn_init (&rgn_out, drawable, x1, y1, x2 - x1, y2 - y1, TRUE, TRUE);

	/* Initialise enough memory for row1, row2, row3, outrow */
	row1 = g_new (guchar, channels * (x2 - x1));
	outrow = g_new (guchar, channels * (x2 - x1));

	for (i = y1; i < y2; i++) {
		/* Get row i-1, i, i+1 */
		gimp_pixel_rgn_get_row (&rgn_in, row1, x1, MAX (y1, i - 1), x2 - x1);

		for (j = x1; j < x2; j++) {
			/* For each layer, compute the average of the nine pixels */
			for (k = 0; k < channels; k++) {
				int in = row1[channels * (j - x1) + k];
				int a = (1.0 - (in / 255.0)) * 100.0;
				int r = rand() % 100;
				outrow[channels * (j - x1) + k] = r < a ? 0 : 255;
			}
		}

		gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1);

		if (i % 10 == 0)
			gimp_progress_update ((gdouble) (i - y1) / (gdouble) (y2 - y1));
	}

	g_free (row1);
	g_free (outrow);

	gimp_drawable_flush (drawable);
	gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
	gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
}
Example #4
0
/* do the exchanging */
static void
exchange (GimpDrawable *drawable,
          GimpPreview  *preview)
{
  GimpPixelRgn  srcPR, destPR;
  guchar        min_red,  min_green,  min_blue;
  guchar        max_red,  max_green,  max_blue;
  guchar        from_red, from_green, from_blue;
  guchar        to_red,   to_green,   to_blue;
  guchar       *src_row, *dest_row;
  gint          x, y, bpp = drawable->bpp;
  gboolean      has_alpha;
  gint          x1, y1, y2;
  gint          width, height;
  GimpRGB       min;
  GimpRGB       max;

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
    }
  else if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                           &x1, &y1, &width, &height))
    {
      return;
    }

  y2 = y1 + height;

  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
  /* allocate memory */
  src_row = g_new (guchar, drawable->width * bpp);

  gimp_rgb_get_uchar (&xargs.from, &from_red, &from_green, &from_blue);
  gimp_rgb_get_uchar (&xargs.to,   &to_red,   &to_green,   &to_blue);

  /* get boundary values */
  min = xargs.from;
  gimp_rgb_subtract (&min, &xargs.threshold);
  gimp_rgb_clamp (&min);
  gimp_rgb_get_uchar (&min, &min_red, &min_green, &min_blue);

  max = xargs.from;
  gimp_rgb_add (&max, &xargs.threshold);
  gimp_rgb_clamp (&max);
  gimp_rgb_get_uchar (&max, &max_red, &max_green, &max_blue);

  dest_row = g_new (guchar, drawable->width * bpp);

  gimp_pixel_rgn_init (&srcPR, drawable,
                       x1, y1, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable,
                       x1, y1, width, height, (preview == NULL), TRUE);

  for (y = y1; y < y2; y++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, width);

      for (x = 0; x < width; x++)
        {
          guchar pixel_red, pixel_green, pixel_blue;
          guchar new_red, new_green, new_blue;
          guint  idx;

          /* get current pixel-values */
          pixel_red   = src_row[x * bpp];
          pixel_green = src_row[x * bpp + 1];
          pixel_blue  = src_row[x * bpp + 2];

          idx = x * bpp;

          /* want this pixel? */
          if (pixel_red >= min_red &&
              pixel_red <= max_red &&
              pixel_green >= min_green &&
              pixel_green <= max_green &&
              pixel_blue >= min_blue &&
              pixel_blue <= max_blue)
            {
              guchar red_delta, green_delta, blue_delta;

              red_delta   = pixel_red > from_red ?
                pixel_red - from_red : from_red - pixel_red;
              green_delta = pixel_green > from_green ?
                pixel_green - from_green : from_green - pixel_green;
              blue_delta  = pixel_blue > from_blue ?
                pixel_blue - from_blue : from_blue - pixel_blue;

              new_red   = CLAMP (to_red   + red_delta,   0, 255);
              new_green = CLAMP (to_green + green_delta, 0, 255);
              new_blue  = CLAMP (to_blue  + blue_delta,  0, 255);
            }
          else
            {
              new_red   = pixel_red;
              new_green = pixel_green;
              new_blue  = pixel_blue;
            }

          /* fill buffer */
          dest_row[idx + 0] = new_red;
          dest_row[idx + 1] = new_green;
          dest_row[idx + 2] = new_blue;

          /* copy alpha-channel */
          if (has_alpha)
            dest_row[idx + 3] = src_row[x * bpp + 3];
        }
      /* store the dest */
      gimp_pixel_rgn_set_row (&destPR, dest_row, x1, y, width);

      /* and tell the user what we're doing */
      if (!preview && (y % 10) == 0)
        gimp_progress_update ((gdouble) y / (gdouble) height);
    }

  g_free (src_row);
  g_free (dest_row);

  if (preview)
    {
      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         &destPR);
    }
  else
    {
      gimp_progress_update (1.0);
      /* update the processed region */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }
}
Example #5
0
static void
neon (GimpDrawable *drawable,
      gdouble       radius,
      gdouble       amount,
      GimpPreview  *preview)
{
    GimpPixelRgn  src_rgn, dest_rgn;
    gint          width, height;
    gint          bytes, bpp;
    gboolean      has_alpha;
    guchar       *dest;
    guchar       *src, *src2, *sp_p, *sp_m;
    gdouble       n_p[5], n_m[5];
    gdouble       d_p[5], d_m[5];
    gdouble       bd_p[5], bd_m[5];
    gdouble      *val_p, *val_m, *vp, *vm;
    gint          x1, y1, x2, y2;
    gint          i, j;
    gint          row, col, b;
    gint          terms;
    gint          progress = 0, max_progress = 1;
    gint          initial_p[4];
    gint          initial_m[4];
    gdouble       std_dev;
    guchar       *preview_buffer1 = NULL;
    guchar       *preview_buffer2 = NULL;

    if (preview)
    {
        gimp_preview_get_position (preview, &x1, &y1);
        gimp_preview_get_size (preview, &width, &height);
        x2 = x1 + width;
        y2 = y1 + height;
    }
    else
    {
        gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
        width  = (x2 - x1);
        height = (y2 - y1);
    }

    if (radius < 1.0)
        return;

    bytes     = drawable->bpp;
    bpp       = bytes;
    has_alpha = gimp_drawable_has_alpha(drawable->drawable_id);
    if (has_alpha)
        bpp--;

    val_p = g_new (gdouble, MAX (width, height) * bytes);
    val_m = g_new (gdouble, MAX (width, height) * bytes);

    src  = g_new (guchar, MAX (width, height) * bytes);
    src2 = g_new (guchar, MAX (width, height) * bytes);
    dest = g_new (guchar, MAX (width, height) * bytes);

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

    if (preview)
    {
        preview_buffer1 = g_new (guchar, width * height * bytes);
        preview_buffer2 = g_new (guchar, width * height * bytes);
    }
    else
    {
        gimp_pixel_rgn_init (&dest_rgn, drawable,
                             0, 0, drawable->width, drawable->height, TRUE, TRUE);

        progress = 0;
        max_progress = (radius < 1.0 ) ? 0 : width * height * radius * 2;
    }

    /*  First the vertical pass  */
    radius  = fabs (radius) + 1.0;
    std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0)));

    /*  derive the constants for calculating the gaussian from the std dev  */
    find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);

    for (col = 0; col < width; col++)
    {
        memset (val_p, 0, height * bytes * sizeof (gdouble));
        memset (val_m, 0, height * bytes * sizeof (gdouble));

        gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1));

        sp_p = src;
        sp_m = src + (height - 1) * bytes;
        vp = val_p;
        vm = val_m + (height - 1) * bytes;

        /*  Set up the first vals  */
        for (i = 0; i < bytes; i++)
        {
            initial_p[i] = sp_p[i];
            initial_m[i] = sp_m[i];
        }

        for (row = 0; row < height; row++)
        {
            gdouble *vpptr, *vmptr;

            terms = (row < 4) ? row : 4;

            for (b = 0; b < bpp; b++)
            {
                vpptr = vp + b;
                vmptr = vm + b;

                for (i = 0; i <= terms; i++)
                {
                    *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
                              d_p[i] * vp[(-i * bytes) + b];
                    *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
                              d_m[i] * vm[(i * bytes) + b];
                }

                for (j = i; j <= 4; j++)
                {
                    *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
                    *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
                }
            }
            if (has_alpha)
            {
                vp[bpp] = sp_p[bpp];
                vm[bpp] = sp_m[bpp];
            }

            sp_p += bytes;
            sp_m -= bytes;
            vp   += bytes;
            vm   -= bytes;
        }

        transfer_pixels (val_p, val_m, dest, bytes, height);

        if (preview)
        {
            for (row = 0 ; row < height ; row++)
                memcpy (preview_buffer1 + (row * width + col) * bytes,
                        dest + bytes * row,
                        bytes);
        }
        else
        {
            gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1));

            progress += height * radius;

            if ((col % 20) == 0)
                gimp_progress_update ((double) progress / (double) max_progress);
        }
    }

    /*  Now the horizontal pass  */
    gimp_pixel_rgn_init (&src_rgn, drawable,
                         0, 0, drawable->width, drawable->height, FALSE, FALSE);

    for (row = 0; row < height; row++)
    {
        memset (val_p, 0, width * bytes * sizeof (gdouble));
        memset (val_m, 0, width * bytes * sizeof (gdouble));

        gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1));
        if (preview)
        {
            memcpy (src2,
                    preview_buffer1 + row * width * bytes,
                    width * bytes);
        }
        else
        {
            gimp_pixel_rgn_get_row (&dest_rgn, src2, x1, row + y1, (x2 - x1));
        }

        sp_p = src;
        sp_m = src + (width - 1) * bytes;
        vp = val_p;
        vm = val_m + (width - 1) * bytes;

        /*  Set up the first vals  */
        for (i = 0; i < bytes; i++)
        {
            initial_p[i] = sp_p[i];
            initial_m[i] = sp_m[i];
        }

        for (col = 0; col < width; col++)
        {
            gdouble *vpptr, *vmptr;

            terms = (col < 4) ? col : 4;

            for (b = 0; b < bpp; b++)
            {
                vpptr = vp + b;
                vmptr = vm + b;

                for (i = 0; i <= terms; i++)
                {
                    *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
                              d_p[i] * vp[(-i * bytes) + b];
                    *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
                              d_m[i] * vm[(i * bytes) + b];
                }

                for (j = i; j <= 4; j++)
                {
                    *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
                    *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
                }
            }
            if (has_alpha)
            {
                vp[bpp] = sp_p[bpp];
                vm[bpp] = sp_m[bpp];
            }

            sp_p += bytes;
            sp_m -= bytes;
            vp   += bytes;
            vm   -= bytes;
        }

        transfer_pixels (val_p, val_m, dest, bytes, width);

        combine_to_gradient (dest, src2, bytes, width, amount);

        if (preview)
        {
            memcpy (preview_buffer2 + row * width * bytes,
                    dest,
                    width * bytes);
        }
        else
        {
            gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1));

            progress += width * radius;
            if ((row % 20) == 0)
                gimp_progress_update ((double) progress / (double) max_progress);
        }
    }

    if (preview)
    {
        gimp_preview_draw_buffer (preview, preview_buffer2, width * bytes);
        g_free (preview_buffer1);
        g_free (preview_buffer2);
    }
    else
    {
        gimp_progress_update (1.0);
        /*  now, merge horizontal and vertical into a magnitude  */
        gimp_pixel_rgn_init (&src_rgn, drawable,
                             0, 0, drawable->width, drawable->height,
                             FALSE, TRUE);

        /*  merge the shadow, update the drawable  */
        gimp_drawable_flush (drawable);
        gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
        gimp_drawable_update (drawable->drawable_id,
                              x1, y1, (x2 - x1), (y2 - y1));
    }
    /*  free up buffers  */
    g_free (val_p);
    g_free (val_m);
    g_free (src);
    g_free (src2);
    g_free (dest);
}
Example #6
0
static void
sobel (TileDrawable *drawable,
	   gint       do_horizontal,
	   gint       do_vertical,
	   gint       keep_sign)
{
  GPixelRgn srcPR, destPR;
  gint width, height;
  gint num_channels;

  guchar *dest;
  guchar *prev_row;
  guchar *cur_row;
  guchar *next_row;
  guchar *pr;
  guchar *cr;
  guchar *nr;
  guchar *tmp;

  gint row, col;
  gint x1, y1, x2, y2;
  gint alpha;
  gint counter;
  GPrecisionType precision = gimp_drawable_precision (drawable->id);

  /* Get the input area. This is the bounding box of the selection in
   *  the image (or the entire image if there is no selection). Only
   *  operating on the input area is simply an optimization. It doesn't
   *  need to be done for correct operation. (It simply makes it go
   *  faster, since fewer pixels need to be operated on).
   */

  gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  gimp_progress_init (_("Sobel Edge Detect"));

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  width = drawable->width;
  height = drawable->height;
  num_channels = drawable->num_channels;
  alpha = gimp_drawable_has_alpha (drawable -> id);

  /*  allocate generic data row buffers  */
  prev_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  cur_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  next_row = (guchar *) malloc ((x2 - x1 + 2) * drawable->bpp);
  dest = (guchar *) malloc ((x2 - x1) * drawable->bpp);

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);

  /* generic data pointers to the three rows */ 
  pr = prev_row + drawable->bpp;
  cr = cur_row + drawable->bpp;
  nr = next_row + drawable->bpp;

  sobel_prepare_row (&srcPR, pr, x1, y1 - 1, (x2 - x1));
  sobel_prepare_row (&srcPR, cr, x1, y1, (x2 - x1));
  counter = 0;

  /*  loop through the rows, applying the sobel convolution  */
  for (row = y1; row < y2; row++)
    {
      /*  prepare the next row  */
      sobel_prepare_row (&srcPR, nr, x1, row + 1, (x2 - x1));

      switch(precision)
      {
	  case PRECISION_U8:
	    {
	      guint8* d = (guint8*)dest;
	      guint8* p = (guint8*)pr; 
	      guint8* c = (guint8*)cr;
	      guint8* n = (guint8*)nr;
  	      gint gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = ROUND_TO_INT (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = 127 + (ROUND_TO_INT ((hor_gradient + ver_gradient) / 8.0));
		       else
			 gradient =  ROUND_TO_INT (abs (hor_gradient + ver_gradient) / 4.0);
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0 : 255;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > 10) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_U16:
	    {
	      guint16* d = (guint16*)dest;
	      guint16* p = (guint16*)pr; 
	      guint16* c = (guint16*)cr;
	      guint16* n = (guint16*)nr;
  	      gint gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = ROUND_TO_INT (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = 32767 + (ROUND_TO_INT ((hor_gradient + ver_gradient) / 8.0));
		       else
			 gradient =  ROUND_TO_INT (abs (hor_gradient + ver_gradient) / 4.0);
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0 : 65535;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > (10/255.0) * 65535) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_FLOAT:
	    {
	      gfloat* d = (gfloat*)dest;
	      gfloat* p = (gfloat*)pr; 
	      gfloat* c = (gfloat*)cr;
	      gfloat* n = (gfloat*)nr;
  	      gfloat gradient, hor_gradient, ver_gradient;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (p[col - num_channels] + 2 * p[col] + p[col + num_channels]) -
				   (n[col - num_channels] + 2 * n[col] + n[col + num_channels]);
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (p[col - num_channels] + 2 * c[col - num_channels] + n[col - num_channels]) -
				   (p[col + num_channels] + 2 * c[col + num_channels] + n[col + num_channels]);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = .5 + (hor_gradient + ver_gradient) / 8.0;
		       else
			 gradient =  abs (hor_gradient + ver_gradient) / 4.0;
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0.0 : 1.0;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = gradient;
		    if (gradient > (10/255.0)) counter ++;
		  }
	       }
	     }
	    break;
	  case PRECISION_FLOAT16: 
	    {
	      guint16* d = (guint16*)dest;
	      guint16* p = (guint16*)pr; 
	      guint16* c = (guint16*)cr;
	      guint16* n = (guint16*)nr;
  	      gfloat gradient, hor_gradient, ver_gradient;
	      ShortsFloat u,v,s, u1, v1, s1;

	      for (col = 0; col < (x2 - x1) * num_channels; col++) {
		  if (do_horizontal)
		    hor_gradient = (
				      FLT(p[col - num_channels],u) +     
				      2 * FLT(p[col], v) +             
				      FLT(p[col + num_channels], s)          
								) -
				    (
				      FLT(n[col - num_channels],u1) + 
				      2 * FLT(n[col], v1) 
				      + FLT(n[col + num_channels], s1)
								   );
		  else
		    hor_gradient = 0;

		  if (do_vertical)
		    ver_gradient = (
				     FLT(p[col - num_channels], u) + 
				     2 * FLT (c[col - num_channels],v) + 
				     FLT(n[col - num_channels],s)
								) -
				   (
				     FLT(p[col + num_channels], u1) + 
				     2 * FLT (c[col + num_channels],v1) + 
				     FLT(n[col + num_channels], s1)
								);
		  else
		    ver_gradient = 0;

		  if (do_vertical && do_horizontal)
		      gradient = (RMS (hor_gradient, ver_gradient)) / 5.66;
		  else
		    {
		       if (keep_sign)
			 gradient = .5 + (hor_gradient + ver_gradient) / 8.0;
		       else
			 gradient =  abs (hor_gradient + ver_gradient) / 4.0;
		    }

		  if (alpha && (((col + 1) % num_channels) == 0))  
		  { 
		    *d++ = (counter == 0) ? 0.0 : 1.0;
		    counter = 0; 
		  }
		  else 
		  {
		    *d++ = FLT16(gradient, u);
		    if (gradient > (10/255.0)) counter ++;
		  }
	       }
	     }
	    break;
      }

      /*  store the dest  */
      gimp_pixel_rgn_set_row (&destPR, dest, x1, row, (x2 - x1));

      /*  shuffle the row pointers  */
      tmp = pr;
      pr = cr;
      cr = nr;
      nr = tmp;

      if ((row % 5) == 0)
	gimp_progress_update ((double) row / (double) (y2 - y1));
    }

  /*  update the sobeled region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->id, TRUE);
  gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));

  free (prev_row);
  free (cur_row);
  free (next_row);
  free (dest);
}
Example #7
0
/*  -  Filter function  -  I wish all filter functions had a pmode :) */
static void
glasstile (GimpDrawable *drawable,
           GimpPreview  *preview)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height;
  gint          bytes;
  guchar       *dest, *d;
  guchar       *cur_row;
  gint          row, col, i;
  gint          x1, y1, x2, y2;

  /* Translations of variable names from Maswan
   * rutbredd = grid width
   * ruthojd = grid height
   * ymitt = y middle
   * xmitt = x middle
   */

  gint rutbredd, xpixel1, xpixel2;
  gint ruthojd , ypixel2;
  gint xhalv, xoffs, xmitt, xplus;
  gint yhalv, yoffs, ymitt, yplus;

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
      x2 = x1 + width;
      y2 = y1 + height;
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      width  = x2 - x1;
      height = y2 - y1;
    }
  bytes  = drawable->bpp;

  cur_row = g_new (guchar, width * bytes);
  dest    = g_new (guchar, width * bytes);

  /* initialize the pixel regions, set grid height/width */
  gimp_pixel_rgn_init (&srcPR, drawable,
                        x1, y1, width, height,
                        FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable,
                       x1, y1, width, height,
                       preview == NULL, TRUE);

  rutbredd = gtvals.xblock;
  ruthojd  = gtvals.yblock;

  xhalv = rutbredd / 2;
  yhalv = ruthojd  / 2;

  xplus = rutbredd % 2;
  yplus = ruthojd  % 2;

  ymitt = y1;
  yoffs = 0;

  /*  Loop through the rows */
  for (row = y1; row < y2; row++)
    {
      d = dest;

      ypixel2 = ymitt + yoffs * 2;
      ypixel2 = CLAMP (ypixel2, 0, y2 - 1);

      gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, ypixel2, width);
      yoffs++;

      /* if current offset = half, do a displacement next time around */
      if (yoffs == yhalv)
        {
          ymitt += ruthojd;
          yoffs = - (yhalv + yplus);
        }

      xmitt = 0;
      xoffs = 0;

      for (col = 0; col < x2 - x1; col++) /* one pixel */
        {
          xpixel1 = (xmitt + xoffs) * bytes;
          xpixel2 = (xmitt + xoffs * 2) * bytes;

          if (xpixel2 < (x2 - x1) * bytes)
            {
              if (xpixel2 < 0)
                xpixel2 = 0;
              for (i = 0; i < bytes; i++)
                d[xpixel1 + i] = cur_row[xpixel2 + i];
            }
          else
            {
              for (i = 0; i < bytes; i++)
                d[xpixel1 + i] = cur_row[xpixel1 + i];
            }

          xoffs++;

          if (xoffs == xhalv)
            {
              xmitt += rutbredd;
              xoffs = - (xhalv + xplus);
            }
        }

      /*  Store the dest  */
      gimp_pixel_rgn_set_row (&destPR, dest, x1, row, width);

      if (!preview && ((row % 5) == 0))
        {
          gimp_progress_update ((gdouble) row / (gdouble) height);
        }
    }

  /*  Update region  */
  if (preview)
    {
      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         &destPR);
    }
  else
    {
      gimp_progress_update (1.0);
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id,
                            x1, y1, width, height);
    }

  g_free (cur_row);
  g_free (dest);
}
static void
explorer (GimpDrawable * drawable)
{
  GimpPixelRgn  srcPR;
  GimpPixelRgn  destPR;
  gint          width;
  gint          height;
  gint          bpp;
  gint          row;
  gint          x1;
  gint          y1;
  gint          x2;
  gint          y2;
  guchar       *src_row;
  guchar       *dest_row;

  /* Get the input area. This is the bounding box of the selection in
   *  the image (or the entire image if there is no selection). Only
   *  operating on the input area is simply an optimization. It doesn't
   *  need to be done for correct operation. (It simply makes it go
   *  faster, since fewer pixels need to be operated on).
   */
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  width  = drawable->width;
  height = drawable->height;
  bpp  = drawable->bpp;

  /*  allocate row buffers  */
  src_row  = g_new (guchar, bpp * (x2 - x1));
  dest_row = g_new (guchar, bpp * (x2 - x1));

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);

  xbild = width;
  ybild = height;
  xdiff = (xmax - xmin) / xbild;
  ydiff = (ymax - ymin) / ybild;

  /* for grayscale drawables */
  if (bpp < 3)
    {
      gint     i;
      for (i = 0; i < MAXNCOLORS; i++)
          valuemap[i] = GIMP_RGB_LUMINANCE (colormap[i].r,
                                            colormap[i].g,
                                            colormap[i].b);
    }

  for (row = y1; row < y2; row++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x1, row, (x2 - x1));

      explorer_render_row (src_row,
                           dest_row,
                           row,
                           (x2 - x1),
                           bpp);

      /*  store the dest  */
      gimp_pixel_rgn_set_row (&destPR, dest_row, x1, row, (x2 - x1));

      if ((row % 10) == 0)
        gimp_progress_update ((double) row / (double) (y2 - y1));
    }

  /*  update the processed region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));

  g_free (src_row);
  g_free (dest_row);
}
Example #9
0
static void sinusrow (GimpDrawable *drawable)
{
  gint         i, j, k, channels;
  gint         x1, y1, x2, y2;
  GimpPixelRgn rgn_in, rgn_out;

   guchar      *inrow;
   guchar      *outrow;
 /* guchar       output[4];  */

  /* Gets upper left and lower right coordinates,
   * and layers number in the image */
  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &x1, &y1,
                             &x2, &y2);
  channels = gimp_drawable_bpp (drawable->drawable_id);

  /* Initialises two PixelRgns, one to read original data,
   * and the other to write output data. That second one will
   * be merged at the end by the call to
   * gimp_drawable_merge_shadow() */
  gimp_pixel_rgn_init (&rgn_in,
                       drawable,
                       x1, y1,
                       x2 - x1, y2 - y1,
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&rgn_out,
                       drawable,
                       x1, y1,
                       x2 - x1, y2 - y1,
                       TRUE, TRUE);

 /* Initialise enough memory for inrow, outrow */
        inrow = g_new (guchar, channels * (x2 - x1));
        outrow = g_new (guchar, channels * (x2 - x1));

  guchar minp[4],maxp[4];
  getrange(drawable, minp, maxp, x1, x2, y1, y2);
  
  for (i = y1; i < y2; i++)
     {
         /* Get row i */
         gimp_pixel_rgn_get_row (&rgn_in, inrow, x1, i, x2 - x1);

         for (j = x1; j < x2; j++)
              {
                /* For each layer, compute the average of the nine
                 * pixels */
                for (k = 0; k < channels; k++) 
            {
                double angle = inrow[channels * (j - x1) + k], max=255;
                angle = M_2_PI * (angle / max ) ;
                outrow[channels * (j - x1) + k] = (guchar)(255*(1+sin(angle))/2);
            }

        } /*end for j each pixel of the row*/

      gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1);

      if (i % 10 == 0)
        gimp_progress_update ((gdouble) (i - x1) / (gdouble) (x2 - x1));

    } /*end for i each row*/

  g_free (inrow);
  g_free (outrow);

  /* Update the modified region */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id,
                        x1, y1,
                        x2 - x1, y2 - y1);
}
Example #10
0
static void
do_zcrop (GimpDrawable *drawable,
          gint32        image_id)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height, x, y;
  gint          bytes;
  guchar       *buffer;
  gint8        *killrows;
  gint8        *killcols;
  gint32        livingrows, livingcols, destrow, destcol;
  gint          total_area, area;
  gboolean      has_alpha;

  width  = drawable->width;
  height = drawable->height;
  bytes  = drawable->bpp;

  total_area = width * height * 4;
  area = 0;

  killrows = g_new (gint8, height);
  killcols = g_new (gint8, width);

  buffer = g_malloc ((width > height ? width : height) * bytes);

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);

  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  livingrows = 0;
  for (y = 0; y < height; y++)
    {
      gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width);

      killrows[y] = TRUE;

      for (x = 0; x < width * bytes; x += bytes)
        {
          if (! colors_equal (buffer, &buffer[x], bytes, has_alpha))
            {
              livingrows++;
              killrows[y] = FALSE;
              break;
            }
        }

      area += width;
      if (y % 20 == 0)
        gimp_progress_update ((double) area / (double) total_area);
    }


  livingcols = 0;
  for (x = 0; x < width; x++)
    {
      gimp_pixel_rgn_get_col (&srcPR, buffer, x, 0, height);

      killcols[x] = TRUE;

      for (y = 0; y < height * bytes; y += bytes)
        {
          if (! colors_equal (buffer, &buffer[y], bytes, has_alpha))
            {
              livingcols++;
              killcols[x] = FALSE;
              break;
            }
        }

      area += height;
      if (x % 20 == 0)
        gimp_progress_update ((double) area / (double) total_area);
    }


  if ((livingcols == 0 || livingrows==0) ||
      (livingcols == width && livingrows == height))
    {
      g_message (_("Nothing to crop."));
      g_free (killrows);
      g_free (killcols);
      return;
    }

  destrow = 0;

  for (y = 0; y < height; y++)
    {
      if (!killrows[y])
        {
          gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width);
          gimp_pixel_rgn_set_row (&destPR, buffer, 0, destrow, width);
          destrow++;
        }

      area += width;
      if (y % 20 == 0)
        gimp_progress_update ((double) area / (double) total_area);
    }


  destcol = 0;
  gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, TRUE);

  for (x = 0; x < width; x++)
    {
      if (!killcols[x])
        {
          gimp_pixel_rgn_get_col (&srcPR, buffer, x, 0, height);
          gimp_pixel_rgn_set_col (&destPR, buffer, destcol, 0, height);
          destcol++;
        }

      area += height;
      if (x % 20 == 0)
        gimp_progress_update ((double) area / (double) total_area);
    }

  g_free (buffer);

  g_free (killrows);
  g_free (killcols);

  gimp_progress_update (1.00);

  gimp_image_undo_group_start (image_id);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_image_crop (image_id, livingcols, livingrows, 0, 0);

  gimp_image_undo_group_end (image_id);
}
Example #11
0
static void
sharpen (GimpDrawable *drawable)
{
  GimpPixelRgn  src_rgn;        /* Source image region */
  GimpPixelRgn  dst_rgn;        /* Destination image region */
  guchar       *src_rows[4];    /* Source pixel rows */
  guchar       *src_ptr;        /* Current source pixel */
  guchar       *dst_row;        /* Destination pixel row */
  intneg       *neg_rows[4];    /* Negative coefficient rows */
  intneg       *neg_ptr;        /* Current negative coefficient */
  gint          i;              /* Looping vars */
  gint          y;              /* Current location in image */
  gint          row;            /* Current row in src_rows */
  gint          count;          /* Current number of filled src_rows */
  gint          width;          /* Byte width of the image */
  gint          x1;             /* Selection bounds */
  gint          y1;
  gint          y2;
  gint          sel_width;      /* Selection width */
  gint          sel_height;     /* Selection height */
  gint          img_bpp;        /* Bytes-per-pixel in image */
  void          (*filter)(int, guchar *, guchar *, intneg *, intneg *, intneg *);

  filter = NULL;

  if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &x1, &y1, &sel_width, &sel_height))
    return;

  y2 = y1 + sel_height;

  img_bpp = gimp_drawable_bpp (drawable->drawable_id);

  /*
   * Let the user know what we're doing...
   */
  gimp_progress_init (_("Sharpening"));

  /*
   * Setup for filter...
   */

  gimp_pixel_rgn_init (&src_rgn, drawable,
                       x1, y1, sel_width, sel_height, FALSE, FALSE);
  gimp_pixel_rgn_init (&dst_rgn, drawable,
                       x1, y1, sel_width, sel_height, TRUE, TRUE);

  compute_luts ();

  width = sel_width * img_bpp;

  for (row = 0; row < 4; row ++)
    {
      src_rows[row] = g_new (guchar, width);
      neg_rows[row] = g_new (intneg, width);
    }

  dst_row = g_new (guchar, width);

  /*
   * Pre-load the first row for the filter...
   */

  gimp_pixel_rgn_get_row (&src_rgn, src_rows[0], x1, y1, sel_width);

  for (i = width, src_ptr = src_rows[0], neg_ptr = neg_rows[0];
       i > 0;
       i --, src_ptr ++, neg_ptr ++)
    *neg_ptr = neg_lut[*src_ptr];

  row   = 1;
  count = 1;

  /*
   * Select the filter...
   */

  switch (img_bpp)
    {
    case 1 :
      filter = gray_filter;
      break;
    case 2 :
      filter = graya_filter;
      break;
    case 3 :
      filter = rgb_filter;
      break;
    case 4 :
      filter = rgba_filter;
      break;
    };

  /*
   * Sharpen...
   */

  for (y = y1; y < y2; y ++)
    {
      /*
       * Load the next pixel row...
       */

      if ((y + 1) < y2)
        {
          /*
           * Check to see if our src_rows[] array is overflowing yet...
           */

          if (count >= 3)
            count --;

          /*
           * Grab the next row...
           */

          gimp_pixel_rgn_get_row (&src_rgn, src_rows[row],
                                  x1, y + 1, sel_width);
          for (i = width, src_ptr = src_rows[row], neg_ptr = neg_rows[row];
               i > 0;
               i --, src_ptr ++, neg_ptr ++)
            *neg_ptr = neg_lut[*src_ptr];

          count ++;
          row = (row + 1) & 3;
        }
      else
        {
          /*
           * No more pixels at the bottom...  Drop the oldest samples...
           */

          count --;
        }

      /*
       * Now sharpen pixels and save the results...
       */

      if (count == 3)
        {
          (* filter) (sel_width, src_rows[(row + 2) & 3], dst_row,
                      neg_rows[(row + 1) & 3] + img_bpp,
                      neg_rows[(row + 2) & 3] + img_bpp,
                      neg_rows[(row + 3) & 3] + img_bpp);

          /*
           * Set the row...
           */

          gimp_pixel_rgn_set_row (&dst_rgn, dst_row, x1, y, sel_width);
        }
      else if (count == 2)
        {
          if (y == y1)      /* first row */
            gimp_pixel_rgn_set_row (&dst_rgn, src_rows[0],
                                    x1, y, sel_width);
          else                  /* last row  */
            gimp_pixel_rgn_set_row (&dst_rgn, src_rows[(sel_height - 1) & 3],
                                    x1, y, sel_width);
        }

      if ((y & 15) == 0)
        gimp_progress_update ((gdouble) (y - y1) / (gdouble) sel_height);
    }

  /*
   * OK, we're done.  Free all memory used...
   */

  for (row = 0; row < 4; row ++)
    {
      g_free (src_rows[row]);
      g_free (neg_rows[row]);
    }

  g_free (dst_row);

  /*
   * Update the screen...
   */

  gimp_progress_update (1.0);
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id,
                        x1, y1, sel_width, sel_height);
}
Example #12
0
static void dofilter (GimpDrawable *drawable)
{
  gint         i, j, k, channels;
  gint         x1, y1, x2, y2;
  GimpPixelRgn rgn_in, rgn_out;

   guchar      *inrow;
   guchar      *outrow;

  /* Gets upper left and lower right coordinates,
   * and layers number in the image */
  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &x1, &y1,                             &x2, &y2);
  channels = gimp_drawable_bpp (drawable->drawable_id);

  /* Initialises two PixelRgns, one to read original data,
   * and the other to write output data. That second one will
   * be merged at the end by the call to
   * gimp_drawable_merge_shadow() */
  gimp_pixel_rgn_init (&rgn_in,        drawable,
                       x1, y1,        x2 - x1, y2 - y1,         FALSE, FALSE);
  gimp_pixel_rgn_init (&rgn_out,    drawable,
                       x1, y1,        x2 - x1, y2 - y1,         TRUE, TRUE);

 /* Initialise enough memory for inrow, outrow */
        inrow = g_new (guchar, channels * (x2 - x1));
        outrow = g_new (guchar, channels * (x2 - x1));




/* EXAMPLE USAGE of the functions to get the range */
//  guchar minp[4],maxp[4];
// getrange(drawable, minp, maxp, x1, x2, y1, y2);



  
  for (i = y1; i < y2; i++)
     {
         /* Get row i  into inrow array*/
         gimp_pixel_rgn_get_row (&rgn_in, inrow, x1, i, x2 - x1);

         for (j = x1; j < x2; j++)
              {
                /* For each layer get the color
                 * pixels */
            guchar rgb[4];
            for (k = 0; k < 4; k++) 
            {
                if (k<channels)
			rgb[k] = inrow[channels * (j - x1) + k];
		else	rgb[k] = 0;
	    }





/* YOUR MAIN CODE HERE : should modify the values inside the rgb array*/

/* EXAMPLE OF CODE : */
            float h,s,b;
            RGBtoHSB (rgb,&h,&s,&b);
	    h=180.0f*(1.0f + cos(h * M_2_PI / 360.0f));
	    HSBtoRGB(h,s,b,rgb);

/* END OF YOUR MAIN CODE HERE */





/* write the new rgb values to the pixels of the outrow */
            for (k = 0; k < channels; k++){ 
                outrow[channels * (j - x1) + k] = rgb[k];
            }

        } /*end for j each pixel of the row*/

      gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1);

      if (i % 10 == 0)
        gimp_progress_update ((gdouble) (i - x1) / (gdouble) (x2 - x1));

    } /*end for i each row*/



  g_free (inrow);
  g_free (outrow);


  /* Update the modified region */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id,                  x1, y1,              x2 - x1, y2 - y1);

}
Example #13
0
static void
rotate_drawable (GimpDrawable *drawable)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height;
  gint          longside;
  gint          bytes;
  gint          row, col;
  gint          offsetx, offsety;
  gboolean      was_lock_alpha = FALSE;
  guchar       *buffer;
  guchar       *src_row, *dest_row;

  /* initialize */

  row = 0;

  /* Get the size of the input drawable. */
  width = drawable->width;
  height = drawable->height;
  bytes = drawable->bpp;

  if (gimp_layer_get_lock_alpha (drawable->drawable_id))
    {
      was_lock_alpha = TRUE;
      gimp_layer_set_lock_alpha (drawable->drawable_id, FALSE);
    }

  if (rotvals.angle == 2)  /* we're rotating by 180° */
    {
      gimp_tile_cache_ntiles (2 * (width / gimp_tile_width() + 1));

      gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height,
                           FALSE, FALSE);
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height,
                           TRUE, TRUE);

      src_row  = (guchar *) g_malloc (width * bytes);
      dest_row = (guchar *) g_malloc (width * bytes);

      for (row = 0; row < height; row++)
        {
          gimp_pixel_rgn_get_row (&srcPR, src_row, 0, row, width);
          for (col = 0; col < width; col++)
            {
              memcpy (dest_row + col * bytes,
                      src_row + (width - 1 - col) * bytes,
                      bytes);
            }
          gimp_pixel_rgn_set_row (&destPR, dest_row, 0, (height - row - 1),
                                  width);

          if ((row % 5) == 0)
            gimp_progress_update ((double) row / (double) height);
        }

      g_free (src_row);
      g_free (dest_row);

      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, 0, 0, width, height);

    }
  else                     /* we're rotating by 90° or 270° */
    {
      (width > height) ? (longside = width) : (longside = height);

      gimp_layer_resize (drawable->drawable_id, longside, longside, 0, 0);
      drawable = gimp_drawable_get (drawable->drawable_id);
      gimp_drawable_flush (drawable);

      gimp_tile_cache_ntiles ((longside / gimp_tile_width () + 1) +
                              (longside / gimp_tile_height () + 1));

      gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, longside, longside,
                           FALSE, FALSE);
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0, longside, longside,
                           TRUE, TRUE);

      buffer = g_malloc (longside * bytes);

      if (rotvals.angle == 1)     /* we're rotating by 90° */
        {
          for (row = 0; row < height; row++)
            {
              gimp_pixel_rgn_get_row (&srcPR, buffer, 0, row, width);
              gimp_pixel_rgn_set_col (&destPR, buffer, (height - row - 1), 0,
                                      width);

              if ((row % 5) == 0)
                gimp_progress_update ((double) row / (double) height);
            }
        }
      else                        /* we're rotating by 270° */
        {
          for (col = 0; col < width; col++)
            {
              gimp_pixel_rgn_get_col (&srcPR, buffer, col, 0, height);
              gimp_pixel_rgn_set_row (&destPR, buffer, 0, (width - col - 1),
                                      height);

              if ((col % 5) == 0)
                gimp_progress_update ((double) col / (double) width);
            }
        }

      g_free (buffer);

      gimp_progress_update (1.0);

      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, 0, 0, height, width);

      gimp_layer_resize (drawable->drawable_id, height, width, 0, 0);
      drawable = gimp_drawable_get (drawable->drawable_id);
      gimp_drawable_flush (drawable);
      gimp_drawable_update (drawable->drawable_id, 0, 0, height, width);
    }

  gimp_drawable_offsets (drawable->drawable_id, &offsetx, &offsety);
  rotate_compute_offsets (&offsetx, &offsety,
                          gimp_image_width (image_ID),
                          gimp_image_height (image_ID),
                          width, height);
  gimp_layer_set_offsets (drawable->drawable_id, offsetx, offsety);

  if (was_lock_alpha)
    gimp_layer_set_lock_alpha (drawable->drawable_id, TRUE);

  return;
}
Example #14
0
static void
randomize (GimpDrawable *drawable,
           GimpPreview  *preview)
{
  GimpPixelRgn srcPR, destPR, destPR2, *sp, *dp, *tp;
  gint width, height;
  gint bytes;
  guchar *dest, *d;
  guchar *prev_row, *pr;
  guchar *cur_row, *cr;
  guchar *next_row, *nr;
  guchar *tmp;
  gint row, col;
  gint x, y;
  gint cnt;
  gint i, j, k;

  if (preview)
    {
      gimp_preview_get_position (preview, &x, &y);
      gimp_preview_get_size (preview, &width, &height);
    }
  else
    {
      if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                          &x, &y, &width, &height))
        return;
    }

  bytes = drawable->bpp;

  /*
   *  allocate row buffers
   */
  prev_row = g_new (guchar, (width + 2) * bytes);
  cur_row = g_new (guchar, (width + 2) * bytes);
  next_row = g_new (guchar, (width + 2) * bytes);
  dest = g_new (guchar, width * bytes);

  /*
   *  initialize the pixel regions
   */
  gimp_pixel_rgn_init (&srcPR, drawable, x, y, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, x, y, width, height, TRUE, TRUE);
  gimp_pixel_rgn_init (&destPR2, drawable, x, y, width, height, TRUE, TRUE);
  sp = &srcPR;
  dp = &destPR;
  tp = NULL;

  pr = prev_row + bytes;
  cr = cur_row + bytes;
  nr = next_row + bytes;

  for (cnt = 1; cnt <= pivals.rndm_rcount; cnt++)
    {
      /*
       *  prepare the first row and previous row
       */
      randomize_prepare_row (sp, pr, x, y - 1, width);
      randomize_prepare_row (sp, cr, x, y, width);
      /*
       *  loop through the rows, applying the selected convolution
       */
      for (row = y; row < y + height; row++)
        {
          /*  prepare the next row  */
          randomize_prepare_row (sp, nr, x, row + 1, width);

          d = dest;
          for (col = 0; col < width; col++)
            {
              if (g_rand_int_range (gr, 0, 100) <= (gint) pivals.rndm_pct)
                {
                  switch (rndm_type)
                    {
                      /*
                       *  HURL
                       *      Just assign a random value.
                       */
                    case RNDM_HURL:
                      for (j = 0; j < bytes; j++)
                        *d++ = g_rand_int_range (gr, 0, 256);
                      break;
                      /*
                       *  PICK
                       *      pick at random from a neighboring pixel.
                       */
                    case RNDM_PICK:
                      k = g_rand_int_range (gr, 0, 9);
                      for (j = 0; j < bytes; j++)
                        {
                          i = col * bytes + j;

                          switch (k)
                            {
                            case 0:
                              *d++ = (gint) pr[i - bytes];
                              break;
                            case 1:
                              *d++ = (gint) pr[i];
                              break;
                            case 2:
                              *d++ = (gint) pr[i + bytes];
                              break;
                            case 3:
                              *d++ = (gint) cr[i - bytes];
                              break;
                            case 4:
                              *d++ = (gint) cr[i];
                              break;
                            case 5:
                              *d++ = (gint) cr[i + bytes];
                              break;
                            case 6:
                              *d++ = (gint) nr[i - bytes];
                              break;
                            case 7:
                              *d++ = (gint) nr[i];
                              break;
                            case 8:
                              *d++ = (gint) nr[i + bytes];
                              break;
                            }
                        }
                      break;
                      /*
                       *  SLUR
                       *      80% chance it's from directly above,
                       *      10% from above left,
                       *      10% from above right.
                       */
                    case RNDM_SLUR:
                      k = g_rand_int_range (gr, 0, 10);
                      for (j = 0; j < bytes; j++)
                        {
                          i = col*bytes + j;

                          switch (k )
                            {
                            case 0:
                              *d++ = (gint) pr[i - bytes];
                              break;
                            case 9:
                              *d++ = (gint) pr[i + bytes];
                              break;
                            default:
                              *d++ = (gint) pr[i];
                              break;
                            }
                        }
                      break;
                    }
                  /*
                   *  Otherwise, this pixel was not selected for randomization,
                   *  so use the current value.
                   */
                }
              else
                {
                  for (j = 0; j < bytes; j++)
                    *d++ = (gint) cr[col*bytes + j];
                }
            }
          /*
           *  Save the modified row, shuffle the row pointers, and every
           *  so often, update the progress meter.
           */
          gimp_pixel_rgn_set_row (dp, dest, x, row, width);

          tmp = pr;
          pr = cr;
          cr = nr;
          nr = tmp;

          if (! preview && PROG_UPDATE_TIME)
            {
              gdouble base = (gdouble) cnt / pivals.rndm_rcount;
              gdouble inc  = (gdouble) row / (height * pivals.rndm_rcount);

              gimp_progress_update (base + inc);
            }
        }

      /*
       *  if we have more cycles to perform, swap the src and dest Pixel Regions
       */
      if (cnt < pivals.rndm_rcount)
        {
          if (tp != NULL)
            {
              tp = dp;
              dp = sp;
              sp = tp;
            }
          else
            {
              tp = &srcPR;
              sp = &destPR;
              dp = &destPR2;
            }
        }
    }

  if (! preview)
    gimp_progress_update (1.0);

  /*
   *  update the randomized region
   */
  if (preview)
    {
      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         dp);
    }
  else
    {
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x, y, width, height);
    }

  /*
   *  clean up after ourselves.
   */
  g_free (prev_row);
  g_free (cur_row);
  g_free (next_row);
  g_free (dest);
}
Example #15
0
static void
c2g_region (GimpPixelRgn *srcPR,
                GimpPixelRgn *destPR,
                gint          bytes, /* Bytes per pixel */
                gdouble       radius,
                gdouble       amount_p,
                gdouble       gamma_p,
                gint          x1,    /* Corners of subregion */
                gint          x2,
                gint          y1,
                gint          y2,
                gboolean      show_progress)
{
  guchar  *src;
  guchar  *dest;
  guchar *bigsrc;
  guchar *bigdest;
  guchar *tmpdest;
 
  gint     width   = x2 - x1;
  gint     height  = y2 - y1;
  gdouble *cmatrix = NULL;
  gint     cmatrix_length;
  gdouble *ctable;
  gint     row, col, idx;
  gint w = c2g_params.radius+10;

  gdouble amount = c2g_params.amount;
  gdouble gamma = c2g_params.gamma;
    
  if (show_progress)
    gimp_progress_init (_("Blurring..."));
  
  iir_init(c2g_params.radius);

  /* allocate buffers */
  src  = g_new (guchar, MAX (width, height) * bytes);
  dest = g_new (guchar, MAX (width, height) * bytes);
  iir.p = g_new(gdouble, MAX (width, height)+2*w);

 
  bigsrc = g_new(guchar, width * height * bytes);
  bigdest = g_new(guchar, width * height * bytes);
  tmpdest = g_new(guchar, width * height * bytes);

  if (show_progress)
    gimp_progress_init (_("Colour converting..."));
  
  // 1. Calculate Nayatani Grey and Blur in LAB
  gimp_pixel_rgn_get_rect (srcPR, bigsrc, x1, y1, width, height);
  extract_lab(bigsrc, bytes, width * height, bigdest);
  nayatani(bigdest,bytes,width * height, bigdest);
  gimp_pixel_rgn_set_rect (destPR, bigdest, x1, y1, width, height);

  // 2. Make a blur of Grey LAB
  for (row = 0, idx=0; row < height; row++, idx+=width)
    {
      gimp_pixel_rgn_get_row (destPR, src, x1, y1 + row, width);
      blur_line (ctable, cmatrix, cmatrix_length, src, dest, width, bytes);   
      gimp_pixel_rgn_set_row (destPR, dest, x1, y1 + row, width);
    }

  for (col = 0; col < width; col++)
    {
      gimp_pixel_rgn_get_col (destPR, src, x1 + col, y1, height);
      blur_line (ctable, cmatrix, cmatrix_length, src, dest, height, bytes);
      gimp_pixel_rgn_set_col (destPR, dest, x1 + col, y1, height);

      if (show_progress && col % 8 == 0)
        gimp_progress_update ((gdouble) col / (3 * width) + 0.33);
    }

  // 3. Convert grey and blur back to RGB.
  compose_lab(bigdest, width * height, bytes, bigdest); // bigdest=greyRGB
  gimp_pixel_rgn_get_rect (destPR, bigsrc, x1, y1, width, height);
  compose_lab(bigsrc, width * height, bytes, bigsrc); // bigsrc= blurgreyRGB

  // 4. Blur Colour RGB and write into destPR
  gimp_pixel_rgn_get_rect (srcPR, tmpdest, x1, y1, width, height);
  gimp_pixel_rgn_set_rect (destPR, tmpdest, x1, y1, width, height);

  for (row = 0, idx=0; row < height; row++, idx+=width)
    {
      gimp_pixel_rgn_get_row (destPR, src, x1, y1 + row, width);
      blur_line (ctable, cmatrix, cmatrix_length, src, dest, width, bytes);   
      gimp_pixel_rgn_set_row (destPR, dest, x1, y1 + row, width);
    }

  for (col = 0; col < width; col++)
    {
      gimp_pixel_rgn_get_col (destPR, src, x1 + col, y1, height);
      blur_line (ctable, cmatrix, cmatrix_length, src, dest, height, bytes);
      gimp_pixel_rgn_set_col (destPR, dest, x1 + col, y1, height);

      if (show_progress && col % 8 == 0)
        gimp_progress_update ((gdouble) col / (3 * width) + 0.33);
    }

  // destPR = blur colour RGB
  chromaunsharp( srcPR, destPR, bigdest, bigsrc, bytes, x1, y1, width, height, amount, gamma, tmpdest );
  compose_lab(tmpdest, width * height, bytes, tmpdest); // tmpdest has unsharp
  gimp_pixel_rgn_set_rect (destPR, tmpdest, x1, y1, width, height);
  

  if (show_progress)
    gimp_progress_update (0.0);

  g_free (bigsrc);
  g_free (bigdest);
  g_free (tmpdest);
  g_free (iir.p);
  g_free (dest);
  g_free (src);
  
}
Example #16
0
static void
sobel (GimpDrawable *drawable,
       gboolean      do_horizontal,
       gboolean      do_vertical,
       gboolean      keep_sign,
       GimpPreview  *preview)
{
  GimpPixelRgn  srcPR, destPR;
  gint          width, height;
  gint          bytes;
  gint          gradient, hor_gradient, ver_gradient;
  guchar       *dest, *d;
  guchar       *prev_row, *pr;
  guchar       *cur_row, *cr;
  guchar       *next_row, *nr;
  guchar       *tmp;
  gint          row, col;
  gint          x1, y1, x2, y2;
  gboolean      alpha;
  gint          counter;
  guchar       *preview_buffer = NULL;

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
      x2 = x1 + width;
      y2 = y1 + height;
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      gimp_progress_init (_("Sobel edge detecting"));
      width  = x2 - x1;
      height = y2 - y1;
    }

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  bytes  = drawable->bpp;
  alpha  = gimp_drawable_has_alpha (drawable->drawable_id);

  /*  allocate row buffers  */
  prev_row = g_new (guchar, (width + 2) * bytes);
  cur_row  = g_new (guchar, (width + 2) * bytes);
  next_row = g_new (guchar, (width + 2) * bytes);
  dest     = g_new (guchar, width * bytes);

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0,
                       drawable->width, drawable->height,
                       FALSE, FALSE);

  if (preview)
    {
      preview_buffer = g_new (guchar, width * height * bytes);
    }
  else
    {
      gimp_pixel_rgn_init (&destPR, drawable, 0, 0,
                           drawable->width, drawable->height,
                           TRUE, TRUE);
    }

  pr = prev_row + bytes;
  cr = cur_row  + bytes;
  nr = next_row + bytes;

  sobel_prepare_row (&srcPR, pr, x1, y1 - 1, width);
  sobel_prepare_row (&srcPR, cr, x1, y1, width);
  counter =0;
  /*  loop through the rows, applying the sobel convolution  */
  for (row = y1; row < y2; row++)
    {
      /*  prepare the next row  */
      sobel_prepare_row (&srcPR, nr, x1, row + 1, width);

      d = dest;
      for (col = 0; col < width * bytes; col++)
        {
          hor_gradient = (do_horizontal ?
                          ((pr[col - bytes] +  2 * pr[col] + pr[col + bytes]) -
                           (nr[col - bytes] + 2 * nr[col] + nr[col + bytes]))
                          : 0);
          ver_gradient = (do_vertical ?
                          ((pr[col - bytes] + 2 * cr[col - bytes] + nr[col - bytes]) -
                           (pr[col + bytes] + 2 * cr[col + bytes] + nr[col + bytes]))
                          : 0);
          gradient = (do_vertical && do_horizontal) ?
            (ROUND (RMS (hor_gradient, ver_gradient)) / 5.66) /* always >0 */
            : (keep_sign ? (127 + (ROUND ((hor_gradient + ver_gradient) / 8.0)))
               : (ROUND (abs (hor_gradient + ver_gradient) / 4.0)));

          if (alpha && (((col + 1) % bytes) == 0))
            { /* the alpha channel */
              *d++ = (counter == 0) ? 0 : 255;
              counter = 0;
            }
          else
            {
              *d++ = gradient;
              if (gradient > 10) counter ++;
            }
        }
      /*  shuffle the row pointers  */
      tmp = pr;
      pr = cr;
      cr = nr;
      nr = tmp;

      /*  store the dest  */
      if (preview)
        {
          memcpy (preview_buffer + width * (row - y1) * bytes,
                  dest,
                  width * bytes);
        }
      else
        {
          gimp_pixel_rgn_set_row (&destPR, dest, x1, row, width);

          if ((row % 20) == 0)
            gimp_progress_update ((double) row / (double) (y2 - y1));
        }
    }

  if (preview)
    {
      gimp_preview_draw_buffer (preview, preview_buffer, width * bytes);
      g_free (preview_buffer);
    }
  else
    {
      gimp_progress_update (1.0);
      /*  update the sobeled region  */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }

  g_free (prev_row);
  g_free (cur_row);
  g_free (next_row);
  g_free (dest);
}
Example #17
0
static void
blur (GimpDrawable *drawable)
{
  gint         i, ii, channels;
  gint         x1, y1, x2, y2;
  GimpPixelRgn rgn_in, rgn_out;
  guchar     **row;
  guchar      *outrow;
  gint         width, height;

  gimp_progress_init ("My Blur...");

  /* Gets upper left and lower right coordinates,
   * and layers number in the image */
  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &x1, &y1,
                             &x2, &y2);
  width  = x2 - x1;
  height = y2 - y1;

  channels = gimp_drawable_bpp (drawable->drawable_id);

  /* Allocate a big enough tile cache */
  gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));

  /* Initialises two PixelRgns, one to read original data,
   * and the other to write output data. That second one will
   * be merged at the end by the call to
   * gimp_drawable_merge_shadow() */
  gimp_pixel_rgn_init (&rgn_in,
                       drawable,
                       x1, y1,
                       width, height,
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&rgn_out,
                       drawable,
                       x1, y1,
                       width, height,
                       TRUE, TRUE);

  /* Allocate memory for input and output tile rows */
  init_mem (&row, &outrow, width * channels);

  for (ii = -radius; ii <= radius; ii++)
    {
      gimp_pixel_rgn_get_row (&rgn_in,
                              row[radius + ii],
                              x1, y1 + CLAMP (ii, 0, height - 1),
                              width);
    }

  for (i = 0; i < height; i++)
    {
      /* To be done for each tile row */
      process_row (row,
                   outrow,
                   x1, y1,
                   width, height,
                   channels,
                   i);
      gimp_pixel_rgn_set_row (&rgn_out,
                              outrow,
                              x1, i + y1,
                              width);
      /* shift tile rows to insert the new one at the end */
      shuffle (&rgn_in,
               row,
               x1, y1,
               width, height,
               i);
      if (i % 10 == 0)
        gimp_progress_update ((gdouble) i / (gdouble) height);
    }

  /* We could also put that in a separate function but it's
   * rather simple */
  for (ii = 0; ii < 2 * radius + 1; ii++)
    g_free (row[ii]);

  g_free (row);
  g_free (outrow);

  /*  Update the modified region */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id,
                        x1, y1,
                        width, height);
}
Example #18
0
static void
value_propagate_body (GimpDrawable *drawable,
                      GimpPreview  *preview)
{
  GimpImageType  dtype;
  ModeParam      operation;
  GimpPixelRgn   srcRgn, destRgn;
  guchar        *here, *best, *dest;
  guchar        *dest_row, *prev_row, *cur_row, *next_row;
  guchar        *pr, *cr, *nr, *swap;
  gint           width, height, bytes, index;
  gint           begx, begy, endx, endy, x, y, dx;
  gint           left_index, right_index, up_index, down_index;
  gpointer       tmp;
  GimpRGB        foreground;

  /* calculate neighbors' indexes */
  left_index  = (vpvals.direction_mask & (1 << Left2Right)) ? -1 : 0;
  right_index = (vpvals.direction_mask & (1 << Right2Left)) ?  1 : 0;
  up_index    = (vpvals.direction_mask & (1 << Top2Bottom)) ? -1 : 0;
  down_index  = (vpvals.direction_mask & (1 << Bottom2Top)) ?  1 : 0;
  operation   = modes[vpvals.propagate_mode];
  tmp         = NULL;

  dtype = gimp_drawable_type (drawable->drawable_id);
  bytes = drawable->bpp;

  /* Here I use the algorithm of blur.c */
  if (preview)
    {
       gimp_preview_get_position (preview, &begx, &begy);
       gimp_preview_get_size (preview, &width, &height);

       endx = begx + width;
       endy = begy + height;
    }
  else
    {
      if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                          &begx, &begy, &width, &height))
        return;

      endx = begx + width;
      endy = begy + height;
    }

  gimp_tile_cache_ntiles (2 * ((width) / gimp_tile_width () + 1));

  prev_row = g_new (guchar, (width + 2) * bytes);
  cur_row  = g_new (guchar, (width + 2) * bytes);
  next_row = g_new (guchar, (width + 2) * bytes);
  dest_row = g_new (guchar, width * bytes);

  gimp_pixel_rgn_init (&srcRgn, drawable,
                       begx, begy, width, height,
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&destRgn, drawable,
                       begx, begy, width, height,
                       (preview == NULL), TRUE);

  pr = prev_row + bytes;
  cr = cur_row + bytes;
  nr = next_row + bytes;

  prepare_row (&srcRgn, pr, begx, (0 < begy) ? begy : begy - 1, endx-begx);
  prepare_row (&srcRgn, cr, begx, begy, endx-begx);

  best = g_new (guchar, bytes);

  if (!preview)
    gimp_progress_init (_("Value Propagate"));

  gimp_context_get_foreground (&foreground);
  gimp_rgb_get_uchar (&foreground, fore+0, fore+1, fore+2);

  /* start real job */
  for (y = begy ; y < endy ; y++)
    {
      prepare_row (&srcRgn, nr, begx, ((y+1) < endy) ? y+1 : endy, endx-begx);

      for (index = 0; index < (endx - begx) * bytes; index++)
        dest_row[index] = cr[index];

      for (x = 0 ; x < endx - begx; x++)
        {
          dest = dest_row + (x * bytes);
          here = cr + (x * bytes);

          /* *** copy source value to best value holder *** */
          memcpy (best, here, bytes);

          if (operation.initializer)
            (* operation.initializer)(dtype, bytes, best, here, &tmp);

          /* *** gather neighbors' values: loop-unfolded version *** */
          if (up_index == -1)
            for (dx = left_index ; dx <= right_index ; dx++)
              (* operation.updater)(dtype, bytes, here, pr+((x+dx)*bytes), best, tmp);
          for (dx = left_index ; dx <= right_index ; dx++)
            if (dx != 0)
              (* operation.updater)(dtype, bytes, here, cr+((x+dx)*bytes), best, tmp);
          if (down_index == 1)
            for (dx = left_index ; dx <= right_index ; dx++)
              (* operation.updater)(dtype, bytes, here, nr+((x+dx)*bytes), best, tmp);
          /* *** store it to dest_row*** */
          (* operation.finalizer)(dtype, bytes, best, here, dest, tmp);
        }

      /* now store destline to destRgn */
      gimp_pixel_rgn_set_row (&destRgn, dest_row, begx, y, endx - begx);

      /* shift the row pointers  */
      swap = pr;
      pr = cr;
      cr = nr;
      nr = swap;


      if (((y % 16) == 0) && !preview)
        gimp_progress_update ((gdouble) y / (gdouble) (endy - begy));
    }

  if (preview)
    {
      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         &destRgn);
    }
  else
    {
      /*  update the region  */
      gimp_progress_update (1.0);
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, begx, begy, endx-begx, endy-begy);
    }
}
Example #19
0
static void
grid (gint32        image_ID,
      GimpDrawable *drawable,
      GimpPreview  *preview)
{
  GimpPixelRgn  srcPR, destPR;
  gint          bytes;
  gint          x_offset, y_offset;
  guchar       *dest, *buffer = NULL;
  gint          x, y;
  gboolean      alpha;
  gboolean      blend;
  guchar        hcolor[4];
  guchar        vcolor[4];
  guchar        icolor[4];
  guchar       *cmap;
  gint          ncolors;

  gimp_rgba_get_uchar (&grid_cfg.hcolor,
                       hcolor, hcolor + 1, hcolor + 2, hcolor + 3);
  gimp_rgba_get_uchar (&grid_cfg.vcolor,
                       vcolor, vcolor + 1, vcolor + 2, vcolor + 3);
  gimp_rgba_get_uchar (&grid_cfg.icolor,
                       icolor, icolor + 1, icolor + 2, icolor + 3);

  switch (gimp_image_base_type (image_ID))
    {
    case GIMP_RGB:
      blend = TRUE;
      break;

    case GIMP_GRAY:
      hcolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.hcolor);
      vcolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.vcolor);
      icolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.icolor);
      blend = TRUE;
      break;

    case GIMP_INDEXED:
      cmap = gimp_image_get_colormap (image_ID, &ncolors);

      hcolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.hcolor);
      vcolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.vcolor);
      icolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.icolor);

      g_free (cmap);
      blend = FALSE;
      break;

    default:
      g_assert_not_reached ();
      blend = FALSE;
    }

  bytes = drawable->bpp;
  alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  if (preview)
    {
      gimp_preview_get_position (preview, &sx1, &sy1);
      gimp_preview_get_size (preview, &sx2, &sy2);

      buffer = g_new (guchar, bytes * sx2 * sy2);

      sx2 += sx1;
      sy2 += sy1;
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &sx1, &sy1, &sx2, &sy2);

      gimp_pixel_rgn_init (&destPR,
                           drawable, 0, 0, sx2 - sx1, sy2 - sy1, TRUE, TRUE);
    }

  gimp_pixel_rgn_init (&srcPR,
                       drawable, 0, 0, sx2 - sx1, sy2 - sy1, FALSE, FALSE);

  dest = g_new (guchar, (sx2 - sx1) * bytes);

  for (y = sy1; y < sy2; y++)
    {
      gimp_pixel_rgn_get_row (&srcPR, dest, sx1, y, (sx2 - sx1));

      y_offset = y - grid_cfg.hoffset;
      while (y_offset < 0)
        y_offset += grid_cfg.hspace;

      if ((y_offset +
           (grid_cfg.hwidth / 2)) % grid_cfg.hspace < grid_cfg.hwidth)
        {
          for (x = sx1; x < sx2; x++)
            {
              pix_composite (&dest[(x-sx1) * bytes],
                             hcolor, bytes, blend, alpha);
            }
        }

      for (x = sx1; x < sx2; x++)
        {
          x_offset = grid_cfg.vspace + x - grid_cfg.voffset;
          while (x_offset < 0)
            x_offset += grid_cfg.vspace;

          if ((x_offset +
               (grid_cfg.vwidth / 2)) % grid_cfg.vspace < grid_cfg.vwidth)
            {
              pix_composite (&dest[(x-sx1) * bytes],
                             vcolor, bytes, blend, alpha);
            }

          if ((x_offset +
               (grid_cfg.iwidth / 2)) % grid_cfg.vspace < grid_cfg.iwidth
              &&
              ((y_offset % grid_cfg.hspace >= grid_cfg.ispace
                &&
                y_offset % grid_cfg.hspace < grid_cfg.ioffset)
               ||
               (grid_cfg.hspace -
                (y_offset % grid_cfg.hspace) >= grid_cfg.ispace
                &&
                grid_cfg.hspace -
                (y_offset % grid_cfg.hspace) < grid_cfg.ioffset)))
            {
              pix_composite (&dest[(x-sx1) * bytes],
                             icolor, bytes, blend, alpha);
            }
        }

      if ((y_offset +
           (grid_cfg.iwidth / 2)) % grid_cfg.hspace < grid_cfg.iwidth)
        {
          for (x = sx1; x < sx2; x++)
            {
              x_offset = grid_cfg.vspace + x - grid_cfg.voffset;
              while (x_offset < 0)
                x_offset += grid_cfg.vspace;

              if ((x_offset % grid_cfg.vspace >= grid_cfg.ispace
                   &&
                   x_offset % grid_cfg.vspace < grid_cfg.ioffset)
                  ||
                  (grid_cfg.vspace -
                   (x_offset % grid_cfg.vspace) >= grid_cfg.ispace
                   &&
                   grid_cfg.vspace -
                   (x_offset % grid_cfg.vspace) < grid_cfg.ioffset))
                {
                  pix_composite (&dest[(x-sx1) * bytes],
                                 icolor, bytes, blend, alpha);
                }
            }
        }

      if (preview)
        {
          memcpy (buffer + (y - sy1) * (sx2 - sx1) * bytes,
                  dest,
                  (sx2 - sx1) * bytes);
        }
      else
        {
          gimp_pixel_rgn_set_row (&destPR, dest, sx1, y, (sx2 - sx1));

          if (y % 16 == 0)
            gimp_progress_update ((gdouble) y / (gdouble) (sy2 - sy1));
        }
    }

  g_free (dest);

  if (preview)
    {
      gimp_preview_draw_buffer (preview, buffer, bytes * (sx2 - sx1));
      g_free (buffer);
    }
  else
    {
      gimp_progress_update (1.0);
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id,
                            sx1, sy1, sx2 - sx1, sy2 - sy1);
    }
}
Example #20
0
static void
gauss_rle (GimpDrawable *drawable,
           gdouble       radius,
           gint          pass,
           gboolean      show_progress)
{
  GimpPixelRgn src_rgn, dest_rgn;
  gint     width, height;
  gint     bytes;
  gint     has_alpha;
  guchar  *dest, *dp;
  guchar  *src, *sp;
  gint    *buf, *bb;
  gint     pixels;
  gint     total = 1;
  gint     x1, y1, x2, y2;
  gint     i, row, col, b;
  gint     start, end;
  gdouble  progress, max_progress;
  gint    *curve;
  gint    *sum = NULL;
  gint     val;
  gint     length;
  gint     initial_p, initial_m;
  gdouble  std_dev;

  if (radius <= 0.0)
    return;

  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  width  = (x2 - x1);
  height = (y2 - y1);

  if (width < 1 || height < 1)
    return;

  bytes = drawable->bpp;
  has_alpha = gimp_drawable_has_alpha(drawable->drawable_id);

  buf = g_new (gint, MAX (width, height) * 2);

  /*  allocate buffers for source and destination pixels  */
  src = g_new (guchar, MAX (width, height) * bytes);
  dest = g_new (guchar, MAX (width, height) * bytes);

  gimp_pixel_rgn_init (&src_rgn,
                       drawable, 0, 0, drawable->width, drawable->height,
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&dest_rgn,
                       drawable, 0, 0, drawable->width, drawable->height,
                       TRUE, TRUE);

  progress = 0.0;
  max_progress  = 2 * width * height;

  /*  First the vertical pass  */
  radius = fabs (radius) + 1.0;
  std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0)));

  curve = make_curve (std_dev, &length);
  sum = g_new (gint, 2 * length + 1);

  sum[0] = 0;

  for (i = 1; i <= length*2; i++)
    sum[i] = curve[i-length-1] + sum[i-1];
  sum += length;

  total = sum[length] - sum[-length];

  for (col = 0; col < width; col++)
    {
      gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1));

      if (has_alpha)
        multiply_alpha (src, height, bytes);

      sp = src;
      dp = dest;

      for (b = 0; b < bytes; b++)
        {
          initial_p = sp[b];
          initial_m = sp[(height-1) * bytes + b];

          /*  Determine a run-length encoded version of the row  */
          run_length_encode (sp + b, buf, bytes, height);

          for (row = 0; row < height; row++)
            {
              start = (row < length) ? -row : -length;
              end = (height <= (row + length) ?
                     (height - row - 1) : length);

              val = 0;
              i = start;
              bb = buf + (row + i) * 2;

              if (start != -length)
                val += initial_p * (sum[start] - sum[-length]);

              while (i < end)
                {
                  pixels = bb[0];
                  i += pixels;

                  if (i > end)
                    i = end;

                  val += bb[1] * (sum[i] - sum[start]);
                  bb += (pixels * 2);
                  start = i;
                }

              if (end != length)
                val += initial_m * (sum[length] - sum[end]);

              dp[row * bytes + b] = val / total;
            }
        }

      if (has_alpha)
        separate_alpha (dest, height, bytes);

      gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1));

      if (show_progress)
        {
          progress += height;

          if ((col % 32) == 0)
            gimp_progress_update (0.5 * (pass + (progress / max_progress)));
        }
    }

  /*  prepare for the horizontal pass  */
  gimp_pixel_rgn_init (&src_rgn,
                       drawable, 0, 0, drawable->width, drawable->height,
                       FALSE, TRUE);

  /*  Now the horizontal pass  */
  for (row = 0; row < height; row++)
    {
      gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1));
      if (has_alpha)
        multiply_alpha (src, width, bytes);

      sp = src;
      dp = dest;

      for (b = 0; b < bytes; b++)
        {
          initial_p = sp[b];
          initial_m = sp[(width-1) * bytes + b];

          /*  Determine a run-length encoded version of the row  */
          run_length_encode (sp + b, buf, bytes, width);

          for (col = 0; col < width; col++)
            {
              start = (col < length) ? -col : -length;
              end = (width <= (col + length)) ? (width - col - 1) : length;

              val = 0;
              i = start;
              bb = buf + (col + i) * 2;

              if (start != -length)
                val += initial_p * (sum[start] - sum[-length]);

              while (i < end)
                {
                  pixels = bb[0];
                  i += pixels;

                  if (i > end)
                    i = end;

                  val += bb[1] * (sum[i] - sum[start]);
                  bb += (pixels * 2);
                  start = i;
                }

              if (end != length)
                val += initial_m * (sum[length] - sum[end]);

              dp[col * bytes + b] = val / total;
            }
        }

      if (has_alpha)
        separate_alpha (dest, width, bytes);

      gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1));

      if (show_progress)
        {
          progress += width;

          if ((row % 32) == 0)
            gimp_progress_update (0.5 * (pass + (progress / max_progress)));
        }
    }

  /*  merge the shadow, update the drawable  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));

  /*  free buffers  */
  g_free (buf);
  g_free (src);
  g_free (dest);
}
Example #21
0
static int
pr_ass_sub(PyGimpPixelRgn *self, PyObject *v, PyObject *w)
{
    GimpPixelRgn *pr = &(self->pr);
    PyObject *x, *y;
    const guchar *buf;
    Py_ssize_t len, x1, x2, xs, y1, y2, ys;

    if (w == NULL) {
        PyErr_SetString(PyExc_TypeError, "can't delete subscripts");
        return -1;
    }

    if (!PyString_Check(w)) {
        PyErr_SetString(PyExc_TypeError, "must assign string to subscript");
        return -1;
    }

    if (!PyTuple_Check(v) || PyTuple_Size(v) != 2) {
        PyErr_SetString(PyExc_TypeError, "subscript must be a 2-tuple");
        return -1;
    }

    if (!PyArg_ParseTuple(v, "OO", &x, &y))
        return -1;

    buf = (const guchar *)PyString_AsString(w);
    len = PyString_Size(w);
    if (!buf || len > INT_MAX) {
        return -1;
    }

    if (PyInt_Check(x)) {
        x1 = PyInt_AsSsize_t(x);
        if (x1 < pr->x || x1 >= pr->x + pr->w) {
            PyErr_SetString(PyExc_IndexError, "x subscript out of range");
            return -1;
        }

        if (PyInt_Check(y)) {
            y1 = PyInt_AsSsize_t(y);

            if (y1 < pr->y || y1 >= pr->y + pr->h) {
                PyErr_SetString(PyExc_IndexError, "y subscript out of range");
                return -1;
            }

            if (len != pr->bpp) {
                PyErr_SetString(PyExc_TypeError, "string is wrong length");
                return -1;
            }
            gimp_pixel_rgn_set_pixel(pr, buf, x1, y1);

        } else if (PySlice_Check(y)) {
            if (PySlice_GetIndices((PySliceObject *)y, pr->y + pr->h,
                                   &y1, &y2, &ys) ||
                y1 >= y2 || ys != 1) {
                PyErr_SetString(PyExc_IndexError, "invalid y slice");
                return -1;
            }
            if (y1 == 0)
                y1 = pr->y;

            if(y1 < pr->y || y2 < pr->y) {
                PyErr_SetString(PyExc_IndexError, "y subscript out of range");
                return -1;
            }
            if (len != pr->bpp * (y2 - y1)) {
                PyErr_SetString(PyExc_TypeError, "string is wrong length");
                return -1;
            }
            gimp_pixel_rgn_set_col(pr, buf, x1, y1, y2 - y1);

        } else {
            PyErr_SetString(PyExc_IndexError,"invalid y subscript");
            return -1;
        }
    } else if (PySlice_Check(x)) {
        if (PySlice_GetIndices((PySliceObject *)x, pr->x + pr->w,
                               &x1, &x2, &xs) ||
	        x1 >= x2 || xs != 1) {
            PyErr_SetString(PyExc_IndexError, "invalid x slice");
	        return -1;
        }
        if(x1 == 0)
            x1 = pr->x;

        if(x1 < pr->x || x2 < pr->x) {
            PyErr_SetString(PyExc_IndexError, "x subscript out of range");
            return -1;
        }

        if (PyInt_Check(y)) {
            y1 = PyInt_AsSsize_t(y);

            if (y1 < pr->y || y1 >= pr->y + pr->h) {
                PyErr_SetString(PyExc_IndexError, "y subscript out of range");
                return -1;
            }

            if (len != pr->bpp * (x2 - x1)) {
                PyErr_SetString(PyExc_TypeError, "string is wrong length");
                return -1;
            }
            gimp_pixel_rgn_set_row(pr, buf, x1, y1, x2 - x1);

        } else if (PySlice_Check(y)) {
            if (PySlice_GetIndices((PySliceObject *)y, pr->y + pr->h,
                                   &y1, &y2, &ys) ||
                y1 >= y2 || ys != 1) {
                PyErr_SetString(PyExc_IndexError, "invalid y slice");
                return -1;
            }
            if (y1 == 0)
                y1 = pr->y;

            if(y1 < pr->y || y2 < pr->y) {
                PyErr_SetString(PyExc_IndexError, "y subscript out of range");
                return -1;
            }
            if (len != pr->bpp * (x2 - x1) * (y2 - y1)) {
                PyErr_SetString(PyExc_TypeError, "string is wrong length");
                return -1;
            }
            gimp_pixel_rgn_set_rect(pr, buf, x1, y1, x2 - x1, y2 - y1);

        } else {
            PyErr_SetString(PyExc_IndexError,"invalid y subscript");
            return -1;
        }
    } else {
        PyErr_SetString(PyExc_TypeError, "invalid x subscript");
        return -1;
    }
    return 0;
}