Beispiel #1
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);
}
Beispiel #2
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);
  
}
Beispiel #3
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);
}
Beispiel #4
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);
}
Beispiel #5
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;
}
Beispiel #6
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;
}