gimpregioniterator.c 10.7 KB
Newer Older
Manish Singh's avatar
Manish Singh committed
1 2 3 4 5
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 *
 * gimpregioniterator.c
 *
6
 * This library is free software: you can redistribute it and/or
Manish Singh's avatar
Manish Singh committed
7 8
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
9
 * version 3 of the License, or (at your option) any later version.
Manish Singh's avatar
Manish Singh committed
10 11 12 13 14 15 16
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17 18
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
Manish Singh's avatar
Manish Singh committed
19 20 21 22 23 24 25 26 27
 */

#include "config.h"

#include <glib.h>

#include "gimp.h"
#include "gimpregioniterator.h"

28

29 30 31 32 33 34 35 36 37 38 39
/**
 * SECTION: gimpregioniterator
 * @title: gimpregioniterator
 * @short_description: Functions to traverse a pixel regions.
 *
 * The GimpRgnIterator functions provide a variety of common ways to
 * traverse a PixelRegion, using a pre-defined function pointer per
 * pixel.
 **/


Manish Singh's avatar
Manish Singh committed
40 41 42
struct _GimpRgnIterator
{
  GimpDrawable *drawable;
43 44 45 46
  gint          x1;
  gint          y1;
  gint          x2;
  gint          y2;
Manish Singh's avatar
Manish Singh committed
47 48
};

49 50 51 52 53

static void  gimp_rgn_iterator_iter_single (GimpRgnIterator    *iter,
                                            GimpPixelRgn       *srcPR,
                                            GimpRgnFuncSrc      func,
                                            gpointer            data);
54
static void  gimp_rgn_render_row           (const guchar       *src,
55 56 57 58 59 60 61 62 63 64 65 66 67 68
                                            guchar             *dest,
                                            gint                col,
                                            gint                bpp,
                                            GimpRgnFunc2        func,
                                            gpointer            data);
static void  gimp_rgn_render_region        (const GimpPixelRgn *srcPR,
                                            const GimpPixelRgn *destPR,
                                            GimpRgnFunc2        func,
                                            gpointer            data);


/**
 * gimp_rgn_iterator_new:
 * @drawable: a #GimpDrawable
69
 * @unused:   ignored
70
 *
71
 * Creates a new #GimpRgnIterator for @drawable. The #GimpRunMode
72 73
 * parameter is ignored. Use gimp_rgn_iterator_free() to free thsi
 * iterator.
74 75 76 77
 *
 * Return value: a newly allocated #GimpRgnIterator.
 **/
GimpRgnIterator *
Manish Singh's avatar
Manish Singh committed
78
gimp_rgn_iterator_new (GimpDrawable *drawable,
79
                       GimpRunMode   unused)
Manish Singh's avatar
Manish Singh committed
80
{
81 82 83 84 85
  GimpRgnIterator *iter;

  g_return_val_if_fail (drawable != NULL, NULL);

  iter = g_slice_new (GimpRgnIterator);
Manish Singh's avatar
Manish Singh committed
86 87

  iter->drawable = drawable;
88

Manish Singh's avatar
Manish Singh committed
89 90 91 92 93 94 95
  gimp_drawable_mask_bounds (drawable->drawable_id,
                             &iter->x1, &iter->y1,
                             &iter->x2, &iter->y2);

  return iter;
}

96 97 98 99 100 101
/**
 * gimp_rgn_iterator_free:
 * @iter: a #GimpRgnIterator
 *
 * Frees the resources allocated for @iter.
 **/
Manish Singh's avatar
Manish Singh committed
102 103 104
void
gimp_rgn_iterator_free (GimpRgnIterator *iter)
{
105 106 107
  g_return_if_fail (iter != NULL);

  g_slice_free (GimpRgnIterator, iter);
Manish Singh's avatar
Manish Singh committed
108 109 110 111 112 113 114 115 116
}

void
gimp_rgn_iterator_src (GimpRgnIterator *iter,
                       GimpRgnFuncSrc   func,
                       gpointer         data)
{
  GimpPixelRgn srcPR;

117 118
  g_return_if_fail (iter != NULL);

Manish Singh's avatar
Manish Singh committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132
  gimp_pixel_rgn_init (&srcPR, iter->drawable,
                       iter->x1, iter->y1,
                       iter->x2 - iter->x1, iter->y2 - iter->y1,
                       FALSE, FALSE);
  gimp_rgn_iterator_iter_single (iter, &srcPR, func, data);
}

void
gimp_rgn_iterator_src_dest (GimpRgnIterator    *iter,
                            GimpRgnFuncSrcDest  func,
                            gpointer            data)
{
  GimpPixelRgn  srcPR, destPR;
  gint          x1, y1, x2, y2;
133
  gint          bpp;
134
  gint          count;
Manish Singh's avatar
Manish Singh committed
135 136 137 138
  gpointer      pr;
  gint          total_area;
  gint          area_so_far;

139 140
  g_return_if_fail (iter != NULL);

Manish Singh's avatar
Manish Singh committed
141 142 143 144 145
  x1 = iter->x1;
  y1 = iter->y1;
  x2 = iter->x2;
  y2 = iter->y2;

146 147
  total_area  = (x2 - x1) * (y2 - y1);
  area_so_far = 0;
Manish Singh's avatar
Manish Singh committed
148 149 150 151 152 153 154 155

  gimp_pixel_rgn_init (&srcPR, iter->drawable, x1, y1, x2 - x1, y2 - y1,
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, iter->drawable, x1, y1, x2 - x1, y2 - y1,
                       TRUE, TRUE);

  bpp = srcPR.bpp;

156
  for (pr = gimp_pixel_rgns_register (2, &srcPR, &destPR), count = 0;
Manish Singh's avatar
Manish Singh committed
157
       pr != NULL;
158
       pr = gimp_pixel_rgns_process (pr), count++)
Manish Singh's avatar
Manish Singh committed
159
    {
160 161 162
      const guchar *src  = srcPR.data;
      guchar       *dest = destPR.data;
      gint          y;
Manish Singh's avatar
Manish Singh committed
163 164 165

      for (y = srcPR.y; y < srcPR.y + srcPR.h; y++)
        {
166 167 168
          const guchar *s = src;
          guchar       *d = dest;
          gint          x;
Manish Singh's avatar
Manish Singh committed
169 170 171 172

          for (x = srcPR.x; x < srcPR.x + srcPR.w; x++)
            {
              func (x, y, s, d, bpp, data);
173

Manish Singh's avatar
Manish Singh committed
174 175 176 177 178 179 180 181
              s += bpp;
              d += bpp;
            }

          src  += srcPR.rowstride;
          dest += destPR.rowstride;
        }

182
      area_so_far += srcPR.w * srcPR.h;
183

184
      if ((count % 16) == 0)
185
        gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area);
Manish Singh's avatar
Manish Singh committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    }

  gimp_drawable_flush (iter->drawable);
  gimp_drawable_merge_shadow (iter->drawable->drawable_id, TRUE);
  gimp_drawable_update (iter->drawable->drawable_id,
                        x1, y1, x2 - x1, y2 - y1);
}

void
gimp_rgn_iterator_dest (GimpRgnIterator *iter,
                        GimpRgnFuncDest  func,
                        gpointer         data)
{
  GimpPixelRgn destPR;

201 202
  g_return_if_fail (iter != NULL);

Manish Singh's avatar
Manish Singh committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
  gimp_pixel_rgn_init (&destPR, iter->drawable,
                       iter->x1, iter->y1,
                       iter->x2 - iter->x1, iter->y2 - iter->y1,
                       TRUE, TRUE);
  gimp_rgn_iterator_iter_single (iter, &destPR, (GimpRgnFuncSrc) func, data);

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


void
gimp_rgn_iterate1 (GimpDrawable *drawable,
220
                   GimpRunMode   unused,
Manish Singh's avatar
Manish Singh committed
221 222 223 224 225 226 227 228
                   GimpRgnFunc1  func,
                   gpointer      data)
{
  GimpPixelRgn  srcPR;
  gint          x1, y1, x2, y2;
  gpointer      pr;
  gint          total_area;
  gint          area_so_far;
229
  gint          count;
Manish Singh's avatar
Manish Singh committed
230

231 232
  g_return_if_fail (drawable != NULL);

Manish Singh's avatar
Manish Singh committed
233 234
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

235 236
  total_area  = (x2 - x1) * (y2 - y1);
  area_so_far = 0;
Manish Singh's avatar
Manish Singh committed
237

238 239 240
  if (total_area <= 0)
    return;

Manish Singh's avatar
Manish Singh committed
241 242 243
  gimp_pixel_rgn_init (&srcPR, drawable,
                       x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);

244
  for (pr = gimp_pixel_rgns_register (1, &srcPR), count = 0;
Manish Singh's avatar
Manish Singh committed
245
       pr != NULL;
246
       pr = gimp_pixel_rgns_process (pr), count++)
Manish Singh's avatar
Manish Singh committed
247
    {
248 249
      const guchar *src = srcPR.data;
      gint          y;
Manish Singh's avatar
Manish Singh committed
250 251 252

      for (y = 0; y < srcPR.h; y++)
        {
253 254
          const guchar *s = src;
          gint          x;
Manish Singh's avatar
Manish Singh committed
255 256 257 258 259 260 261 262 263 264

          for (x = 0; x < srcPR.w; x++)
            {
              func (s, srcPR.bpp, data);
              s += srcPR.bpp;
            }

          src += srcPR.rowstride;
        }

265
      area_so_far += srcPR.w * srcPR.h;
Manish Singh's avatar
Manish Singh committed
266

267
      if ((count % 16) == 0)
268
        gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area);
Manish Singh's avatar
Manish Singh committed
269 270 271 272 273
    }
}

void
gimp_rgn_iterate2 (GimpDrawable *drawable,
274
                   GimpRunMode   unused,
Manish Singh's avatar
Manish Singh committed
275 276 277 278 279 280 281 282
                   GimpRgnFunc2  func,
                   gpointer      data)
{
  GimpPixelRgn  srcPR, destPR;
  gint          x1, y1, x2, y2;
  gpointer      pr;
  gint          total_area;
  gint          area_so_far;
283
  gint          count;
Manish Singh's avatar
Manish Singh committed
284

285 286
  g_return_if_fail (drawable != NULL);

Manish Singh's avatar
Manish Singh committed
287 288
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

289 290
  total_area  = (x2 - x1) * (y2 - y1);
  area_so_far = 0;
Manish Singh's avatar
Manish Singh committed
291

292 293 294
  if (total_area <= 0)
    return;

Manish Singh's avatar
Manish Singh committed
295 296 297 298 299 300
  /* Initialize the pixel regions. */
  gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, (x2 - x1), (y2 - y1),
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, x1, y1, (x2 - x1), (y2 - y1),
                       TRUE, TRUE);

301
  for (pr = gimp_pixel_rgns_register (2, &srcPR, &destPR), count = 0;
Manish Singh's avatar
Manish Singh committed
302
       pr != NULL;
303
       pr = gimp_pixel_rgns_process (pr), count++)
Manish Singh's avatar
Manish Singh committed
304 305 306
    {
      gimp_rgn_render_region (&srcPR, &destPR, func, data);

307
      area_so_far += srcPR.w * srcPR.h;
Manish Singh's avatar
Manish Singh committed
308

309
      if ((count % 16) == 0)
310
        gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area);
Manish Singh's avatar
Manish Singh committed
311 312 313 314 315 316 317
    }

  /*  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));
}
318 319 320 321 322 323 324 325 326 327

static void
gimp_rgn_iterator_iter_single (GimpRgnIterator *iter,
                               GimpPixelRgn    *srcPR,
                               GimpRgnFuncSrc   func,
                               gpointer         data)
{
  gpointer  pr;
  gint      total_area;
  gint      area_so_far;
328
  gint      count;
329

330 331
  total_area  = (iter->x2 - iter->x1) * (iter->y2 - iter->y1);
  area_so_far = 0;
332

333
  for (pr = gimp_pixel_rgns_register (1, srcPR), count = 0;
334
       pr != NULL;
335
       pr = gimp_pixel_rgns_process (pr), count++)
336
    {
337 338
      const guchar *src = srcPR->data;
      gint          y;
339 340 341

      for (y = srcPR->y; y < srcPR->y + srcPR->h; y++)
        {
342 343
          const guchar *s = src;
          gint          x;
344 345 346 347 348 349 350 351 352 353 354

          for (x = srcPR->x; x < srcPR->x + srcPR->w; x++)
            {
              func (x, y, s, srcPR->bpp, data);
              s += srcPR->bpp;
            }

          src += srcPR->rowstride;
        }

      area_so_far += srcPR->w * srcPR->h;
355

356
      if ((count % 16) == 0)
357
        gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area);
358 359 360 361
    }
}

static void
362
gimp_rgn_render_row (const guchar *src,
363 364 365 366 367 368 369 370 371
                     guchar       *dest,
                     gint          col,    /* row width in pixels */
                     gint          bpp,
                     GimpRgnFunc2  func,
                     gpointer      data)
{
  while (col--)
    {
      func (src, dest, bpp, data);
372 373

      src  += bpp;
374 375 376 377 378 379 380 381 382 383
      dest += bpp;
    }
}

static void
gimp_rgn_render_region (const GimpPixelRgn *srcPR,
                        const GimpPixelRgn *destPR,
                        GimpRgnFunc2        func,
                        gpointer            data)
{
384 385 386
  const guchar *src  = srcPR->data;
  guchar       *dest = destPR->data;
  gint          row;
387 388 389 390 391 392 393 394 395

  for (row = 0; row < srcPR->h; row++)
    {
      gimp_rgn_render_row (src, dest, srcPR->w, srcPR->bpp, func, data);

      src  += srcPR->rowstride;
      dest += destPR->rowstride;
    }
}