home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gimage_mask.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  16.6 KB  |  651 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "drawable.h"
  27. #include "floating_sel.h"
  28. #include "gdisplay.h"
  29. #include "gimage_mask.h"
  30. #include "gimprc.h"
  31. #include "layer.h"
  32. #include "paint_core.h"
  33. #include "paint_options.h"
  34. #include "undo.h"
  35.  
  36. #include "channel_pvt.h"
  37. #include "tile_manager_pvt.h"
  38.  
  39. #include "libgimp/gimpintl.h"
  40.  
  41.  
  42. /*  local variables  */
  43. static int gimage_mask_stroking = FALSE;
  44.  
  45. /*  functions  */
  46. gboolean
  47. gimage_mask_boundary (GImage    *gimage,
  48.               BoundSeg **segs_in,
  49.               BoundSeg **segs_out,
  50.               gint      *num_segs_in,
  51.               gint      *num_segs_out)
  52. {
  53.   GimpDrawable *d;
  54.   Layer *layer;
  55.   gint x1, y1;
  56.   gint x2, y2;
  57.  
  58.   if ((layer = gimage_floating_sel (gimage)))
  59.     {
  60.       /*  If there is a floating selection, then
  61.        *  we need to do some slightly different boundaries.
  62.        *  Instead of inside and outside boundaries being defined
  63.        *  by the extents of the layer, the inside boundary (the one
  64.        *  that actually marches and is black/white) is the boundary of
  65.        *  the floating selection.  The outside boundary (doesn't move,
  66.        *  is black/gray) is defined as the normal selection mask
  67.        */
  68.  
  69.       /*  Find the selection mask boundary  */
  70.       channel_boundary (gimage_get_mask (gimage),
  71.             segs_in, segs_out,
  72.             num_segs_in, num_segs_out,
  73.             0, 0, 0, 0);
  74.  
  75.       /*  Find the floating selection boundary  */
  76.       *segs_in = floating_sel_boundary (layer, num_segs_in);
  77.  
  78.       return TRUE;
  79.     }
  80.   /*  Otherwise, return the boundary...if a channel is active  */
  81.   else if ((d = gimage_active_drawable (gimage)) &&
  82.        GIMP_IS_CHANNEL (d))
  83.     {
  84.       return channel_boundary (gimage_get_mask (gimage),
  85.                    segs_in, segs_out,
  86.                    num_segs_in, num_segs_out,
  87.                    0, 0, gimage->width, gimage->height);
  88.     }
  89.   /* if a layer is active, we return multiple boundaries based on the extents */
  90.   else if ((layer = gimage_get_active_layer (gimage)))
  91.     {
  92.       gint off_x, off_y;
  93.  
  94.       drawable_offsets (GIMP_DRAWABLE(layer), &off_x, &off_y);
  95.       x1 = CLAMP (off_x, 0, gimage->width);
  96.       y1 = CLAMP (off_y, 0, gimage->height);
  97.       x2 = CLAMP (off_x + drawable_width (GIMP_DRAWABLE(layer)), 0,
  98.           gimage->width);
  99.       y2 = CLAMP (off_y + drawable_height (GIMP_DRAWABLE(layer)), 0,
  100.           gimage->height);
  101.  
  102.       return channel_boundary (gimage_get_mask (gimage),
  103.                    segs_in, segs_out,
  104.                    num_segs_in, num_segs_out,
  105.                    x1, y1, x2, y2);
  106.     }
  107.   else
  108.     {
  109.       *segs_in = NULL;
  110.       *segs_out = NULL;
  111.       *num_segs_in = 0;
  112.       *num_segs_out = 0;
  113.       return FALSE;
  114.     }
  115. }
  116.  
  117.  
  118. gboolean
  119. gimage_mask_bounds (GImage *gimage,
  120.             gint   *x1,
  121.             gint   *y1,
  122.             gint   *x2,
  123.             gint   *y2)
  124. {
  125.   return channel_bounds (gimage_get_mask (gimage), x1, y1, x2, y2);
  126. }
  127.  
  128.  
  129. void
  130. gimage_mask_invalidate (GImage *gimage)
  131. {
  132.   Layer *layer;
  133.   Channel *mask;
  134.  
  135.   /*  Turn the current selection off  */
  136.   gdisplays_selection_visibility (gimage, SelectionOff);
  137.  
  138.   mask = gimage_get_mask (gimage);
  139.   mask->boundary_known = FALSE;
  140.  
  141.   /*  If there is a floating selection, update it's area...
  142.    *  we need to do this since this selection mask can act as an additional
  143.    *  mask in the composition of the floating selection
  144.    */
  145.   layer = gimage_get_active_layer (gimage);
  146.   if (layer && layer_is_floating_sel (layer))
  147.     drawable_update (GIMP_DRAWABLE(layer), 0, 0,
  148.              GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height);
  149. }
  150.  
  151.  
  152. gint
  153. gimage_mask_value (GImage *gimage,
  154.            int     x,
  155.            int     y)
  156. {
  157.   return channel_value (gimage_get_mask (gimage), x, y);
  158. }
  159.  
  160.  
  161. gboolean
  162. gimage_mask_is_empty (GImage *gimage)
  163. {
  164.   /*  in order to allow stroking of selections, we need to pretend here
  165.    *  that the selection mask is empty so that it doesn't mask the paint
  166.    *  during the stroke operation.
  167.    */
  168.   if (gimage_mask_stroking)
  169.     return TRUE;
  170.   else
  171.     return channel_is_empty (gimage_get_mask (gimage));
  172. }
  173.  
  174.  
  175. void
  176. gimage_mask_translate (GImage *gimage,
  177.                gint    off_x,
  178.                gint    off_y)
  179. {
  180.   channel_translate (gimage_get_mask (gimage), off_x, off_y);
  181. }
  182.  
  183.  
  184. TileManager *
  185. gimage_mask_extract (GImage       *gimage,
  186.              GimpDrawable *drawable,
  187.              gboolean      cut_gimage,
  188.              gboolean      keep_indexed,
  189.              gboolean      add_alpha)
  190. {
  191.   TileManager * tiles;
  192.   Channel * sel_mask;
  193.   PixelRegion srcPR, destPR, maskPR;
  194.   guchar bg[MAX_CHANNELS];
  195.   gint bytes, type;
  196.   gint x1, y1;
  197.   gint x2, y2;
  198.   gint off_x, off_y;
  199.   gboolean non_empty;
  200.  
  201.   if (!drawable) 
  202.     return NULL;
  203.  
  204.   /*  If there are no bounds, then just extract the entire image
  205.    *  This may not be the correct behavior, but after getting rid
  206.    *  of floating selections, it's still tempting to "cut" or "copy"
  207.    *  a small layer and expect it to work, even though there is no
  208.    *  actual selection mask
  209.    */
  210.   non_empty = drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  211.   if (non_empty && (!(x2 - x1) || !(y2 - y1)))
  212.     {
  213.       g_message (_("Unable to cut/copy because the selected\n"
  214.            "region is empty."));
  215.       return NULL;
  216.     }
  217.  
  218.   /*  How many bytes in the temp buffer?  */
  219.   switch (drawable_type (drawable))
  220.     {
  221.     case RGB_GIMAGE: case RGBA_GIMAGE:
  222.       bytes = add_alpha ? 4 : drawable->bytes;
  223.       type = RGB;
  224.       break;
  225.     case GRAY_GIMAGE: case GRAYA_GIMAGE:
  226.       bytes = add_alpha ? 2 : drawable->bytes;
  227.       type = GRAY;
  228.       break;
  229.     case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
  230.       if (keep_indexed)
  231.     {
  232.       bytes = add_alpha ? 2 : drawable->bytes;
  233.       type = GRAY;
  234.     }
  235.       else
  236.     {
  237.       bytes = add_alpha ? 4 : drawable->bytes;
  238.       type = INDEXED;
  239.     }
  240.       break;
  241.     default:
  242.       bytes = 3;
  243.       type  = RGB;
  244.       break;
  245.     }
  246.  
  247.   /*  get the selection mask */
  248.   if (non_empty)
  249.     sel_mask = gimage_get_mask (gimage);
  250.   else
  251.     sel_mask = NULL;
  252.  
  253.   gimage_get_background (gimage, drawable, bg);
  254.  
  255.   /*  If a cut was specified, and the selection mask is not empty,
  256.    *  push an undo
  257.    */
  258.   if (cut_gimage && non_empty)
  259.     drawable_apply_image (drawable, x1, y1, x2, y2, NULL, FALSE);
  260.  
  261.   drawable_offsets (drawable, &off_x, &off_y);
  262.  
  263.   /*  Allocate the temp buffer  */
  264.   tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
  265.   tiles->x = x1 + off_x;
  266.   tiles->y = y1 + off_y;
  267.  
  268.   /* configure the pixel regions  */
  269.   pixel_region_init (&srcPR, drawable_data (drawable),
  270.              x1, y1, (x2 - x1), (y2 - y1), cut_gimage);
  271.   pixel_region_init (&destPR, tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  272.  
  273.   /*  If there is a selection, extract from it  */
  274.   if (non_empty)
  275.     {
  276.       pixel_region_init (&maskPR, GIMP_DRAWABLE(sel_mask)->tiles,
  277.              (x1 + off_x), (y1 + off_y), (x2 - x1), (y2 - y1),
  278.              FALSE);
  279.  
  280.       extract_from_region (&srcPR, &destPR, &maskPR, drawable_cmap (drawable),
  281.                bg, type, drawable_has_alpha (drawable), cut_gimage);
  282.  
  283.       if (cut_gimage)
  284.     {
  285.       /*  Clear the region  */
  286.       channel_clear (gimage_get_mask (gimage));
  287.  
  288.       /*  Update the region  */
  289.       gdisplays_update_area (gimage, tiles->x, tiles->y,
  290.                  tiles->width, tiles->height);
  291.  
  292.       /*  Invalidate the preview  */
  293.       gimp_drawable_invalidate_preview (drawable, TRUE);
  294.     }
  295.     }
  296.   /*  Otherwise, get the entire active layer  */
  297.   else
  298.     {
  299.       /*  If the layer is indexed...we need to extract pixels  */
  300.       if (type == INDEXED && !keep_indexed)
  301.     extract_from_region (&srcPR, &destPR, NULL, drawable_cmap (drawable),
  302.                  bg, type, drawable_has_alpha (drawable), FALSE);
  303.       /*  If the layer doesn't have an alpha channel, add one  */
  304.       else if (bytes > srcPR.bytes)
  305.     add_alpha_region (&srcPR, &destPR);
  306.       /*  Otherwise, do a straight copy  */
  307.       else
  308.     copy_region (&srcPR, &destPR);
  309.  
  310.       /*  If we're cutting, remove either the layer (or floating selection),
  311.        *  the layer mask, or the channel
  312.        */
  313.       if (cut_gimage && GIMP_IS_LAYER (drawable))
  314.     {
  315.       if (layer_is_floating_sel (GIMP_LAYER (drawable)))
  316.         floating_sel_remove (GIMP_LAYER (drawable));
  317.       else
  318.         gimage_remove_layer (gimage, GIMP_LAYER (drawable));
  319.     }
  320.       else if (cut_gimage && GIMP_IS_LAYER_MASK (drawable))
  321.     {
  322.       gimage_remove_layer_mask (gimage, 
  323.                     layer_mask_get_layer (GIMP_LAYER_MASK (drawable)),
  324.                     DISCARD);
  325.     }
  326.       else if (cut_gimage && GIMP_IS_CHANNEL (drawable))
  327.     gimage_remove_channel (gimage, GIMP_CHANNEL (drawable));
  328.     }
  329.  
  330.   return tiles;
  331. }
  332.  
  333.  
  334. Layer *
  335. gimage_mask_float (GImage       *gimage,
  336.            GimpDrawable *drawable,
  337.            gint          off_x,    /* optional offset */
  338.            gint          off_y)
  339. {
  340.   Layer *layer;
  341.   Channel *mask = gimage_get_mask (gimage);
  342.   TileManager* tiles;
  343.   gboolean non_empty;
  344.   gint x1, y1;
  345.   gint x2, y2;
  346.  
  347.   /*  Make sure there is a region to float...  */
  348.   non_empty = drawable_mask_bounds ( (drawable), &x1, &y1, &x2, &y2);
  349.   if (! non_empty || (x2 - x1) == 0 || (y2 - y1) == 0)
  350.     {
  351.       g_message (_("Float Selection: No selection to float."));
  352.       return NULL;
  353.     }
  354.  
  355.   /*  Start an undo group  */
  356.   undo_push_group_start (gimage, FLOAT_MASK_UNDO);
  357.  
  358.   /*  Cut the selected region  */
  359.   tiles = gimage_mask_extract (gimage, drawable, TRUE, FALSE, TRUE);
  360.  
  361.   /*  Create a new layer from the buffer  */
  362.   layer = layer_new_from_tiles (gimage, gimp_drawable_type_with_alpha(drawable), tiles, 
  363.                 _("Floated Layer"), OPAQUE_OPACITY, NORMAL_MODE);
  364.  
  365.   /*  Set the offsets  */
  366.   GIMP_DRAWABLE(layer)->offset_x = tiles->x + off_x;
  367.   GIMP_DRAWABLE(layer)->offset_y = tiles->y + off_y;
  368.  
  369.   /*  Free the temp buffer  */
  370.   tile_manager_destroy (tiles);
  371.  
  372.   /*  Add the floating layer to the gimage  */
  373.   floating_sel_attach (layer, drawable);
  374.  
  375.   /*  End an undo group  */
  376.   undo_push_group_end (gimage);
  377.  
  378.   /*  invalidate the gimage's boundary variables  */
  379.   mask->boundary_known = FALSE;
  380.  
  381.   return layer;
  382. }
  383.  
  384.  
  385. void
  386. gimage_mask_clear (GImage *gimage)
  387. {
  388.   channel_clear (gimage_get_mask (gimage));
  389. }
  390.  
  391.  
  392. void
  393. gimage_mask_undo (GImage *gimage)
  394. {
  395.   channel_push_undo (gimage_get_mask (gimage));
  396. }
  397.  
  398.  
  399. void
  400. gimage_mask_invert (GImage *gimage)
  401. {
  402.   channel_invert (gimage_get_mask (gimage));
  403. }
  404.  
  405.  
  406. void
  407. gimage_mask_sharpen (GImage *gimage)
  408. {
  409.   /*  No need to play with the selection visibility
  410.    *  because sharpen will not change the outline
  411.    */
  412.   channel_sharpen (gimage_get_mask (gimage));
  413. }
  414.  
  415.  
  416. void
  417. gimage_mask_all (GImage *gimage)
  418. {
  419.   channel_all (gimage_get_mask (gimage));
  420. }
  421.  
  422.  
  423. void
  424. gimage_mask_none (GImage *gimage)
  425. {
  426.   channel_clear (gimage_get_mask (gimage));
  427. }
  428.  
  429.  
  430. void
  431. gimage_mask_feather (GImage  *gimage,
  432.              gdouble  feather_radius_x,
  433.              gdouble  feather_radius_y)
  434. {
  435.   /*  push the current mask onto the undo stack--need to do this here because
  436.    *  channel_feather doesn't do it
  437.    */
  438.   channel_push_undo (gimage_get_mask (gimage));
  439.  
  440.   /*  feather the region  */
  441.   channel_feather (gimage_get_mask (gimage),
  442.            gimage_get_mask (gimage),
  443.            feather_radius_x,
  444.            feather_radius_y,
  445.            REPLACE, 0, 0);
  446. }
  447.  
  448.  
  449. void
  450. gimage_mask_border (GImage *gimage,
  451.             gint    border_radius_x,
  452.             gint    border_radius_y)
  453. {
  454.   /*  feather the region  */
  455.   channel_border (gimage_get_mask (gimage),
  456.           border_radius_x,
  457.           border_radius_y);
  458. }
  459.  
  460.  
  461. void
  462. gimage_mask_grow (GImage *gimage,
  463.           int     grow_pixels_x,
  464.           int     grow_pixels_y)
  465. {
  466.   /*  feather the region  */
  467.   channel_grow (gimage_get_mask (gimage),
  468.         grow_pixels_x,
  469.         grow_pixels_y);
  470. }
  471.  
  472.  
  473. void
  474. gimage_mask_shrink (GImage   *gimage,
  475.             gint      shrink_pixels_x,
  476.             gint      shrink_pixels_y,
  477.             gboolean  edge_lock)
  478. {
  479.   /*  feather the region  */
  480.   channel_shrink (gimage_get_mask (gimage),
  481.           shrink_pixels_x,
  482.           shrink_pixels_y,
  483.           edge_lock);
  484. }
  485.  
  486.  
  487. void
  488. gimage_mask_layer_alpha (GImage *gimage,
  489.              Layer  *layer)
  490. {
  491.   /*  extract the layer's alpha channel  */
  492.   if (drawable_has_alpha (GIMP_DRAWABLE (layer)))
  493.     {
  494.       /*  load the mask with the given layer's alpha channel  */
  495.       channel_layer_alpha (gimage_get_mask (gimage), layer);
  496.     }
  497.   else
  498.     {
  499.       g_message (_("The active layer has no alpha channel\n"
  500.            "to convert to a selection."));
  501.       return;
  502.     }
  503. }
  504.  
  505.  
  506. void
  507. gimage_mask_layer_mask (GImage *gimage,
  508.             Layer  *layer)
  509. {
  510.   /*  extract the layer's alpha channel  */
  511.   if (layer_get_mask (layer))
  512.     {
  513.       /*  load the mask with the given layer's alpha channel  */
  514.       channel_layer_mask (gimage_get_mask (gimage), layer);
  515.     }
  516.   else
  517.     {
  518.       g_message (_("The active layer has no mask\n"
  519.            "to convert to a selection."));
  520.       return;
  521.     }
  522. }
  523.  
  524.  
  525. void
  526. gimage_mask_load (GImage  *gimage,
  527.           Channel *channel)
  528. {
  529.   /*  Load the specified channel to the gimage mask  */
  530.   channel_load (gimage_get_mask (gimage), (channel));
  531. }
  532.  
  533.  
  534. Channel *
  535. gimage_mask_save (GImage *gimage)
  536. {
  537.   Channel *new_channel;
  538.  
  539.   new_channel = channel_copy (gimage_get_mask (gimage));
  540.  
  541.   /*  saved selections are not visible by default  */
  542.   GIMP_DRAWABLE(new_channel)->visible = FALSE;
  543.   gimage_add_channel (gimage, new_channel, -1);
  544.  
  545.   return new_channel;
  546. }
  547.  
  548.  
  549. gboolean
  550. gimage_mask_stroke (GImage       *gimage,
  551.             GimpDrawable *drawable)
  552. {
  553.   BoundSeg  *bs_in;
  554.   BoundSeg  *bs_out;
  555.   gint       num_segs_in;
  556.   gint       num_segs_out;
  557.   BoundSeg  *stroke_segs;
  558.   gint       num_strokes;
  559.   gint       seg;
  560.   gint       offx, offy;
  561.   gint       i;
  562.   gdouble   *stroke_points;
  563.   gint       cpnt;
  564.   Argument  *return_vals;
  565.   gint       nreturn_vals;
  566.  
  567.   if (! gimage_mask_boundary (gimage, &bs_in, &bs_out,
  568.                   &num_segs_in, &num_segs_out))
  569.     {
  570.       g_message (_("No selection to stroke!"));
  571.       return FALSE;
  572.     }
  573.  
  574.   stroke_segs = sort_boundary (bs_in, num_segs_in, &num_strokes);
  575.   if (num_strokes == 0)
  576.     return TRUE;
  577.  
  578.   /*  find the drawable offsets  */
  579.   drawable_offsets (drawable, &offx, &offy);
  580.   gimage_mask_stroking = TRUE;
  581.  
  582.   /*  Start an undo group  */
  583.   undo_push_group_start (gimage, PAINT_CORE_UNDO);
  584.  
  585.   seg = 0;
  586.   cpnt = 0;
  587.   /* Largest array required (may be used in segments!) */
  588.   stroke_points = g_malloc (sizeof (gdouble) * 2 * (num_segs_in + 4));
  589.  
  590.   /* we offset all coordinates by 0.5 to align the brush with the path */
  591.  
  592.   stroke_points[cpnt++] = (gdouble)(stroke_segs[0].x1 - offx + 0.5);
  593.   stroke_points[cpnt++] = (gdouble)(stroke_segs[0].y1 - offy + 0.5);
  594.  
  595.   for (i = 0; i < num_strokes; i++)
  596.     {
  597.       while ((stroke_segs[seg].x1 != -1 ||
  598.           stroke_segs[seg].x2 != -1 ||
  599.           stroke_segs[seg].y1 != -1 ||
  600.           stroke_segs[seg].y2 != -1))
  601.     {
  602.       stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x2 - offx + 0.5);
  603.       stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y2 - offy + 0.5);
  604.       seg ++;
  605.     }
  606.  
  607.       /* Close the stroke points up */
  608.       stroke_points[cpnt++] = stroke_points[0];
  609.       stroke_points[cpnt++] = stroke_points[1];
  610.  
  611.       /* Stroke with the correct tool */
  612.       return_vals = procedural_db_run_proc (tool_active_PDB_string(),
  613.                         &nreturn_vals,
  614.                         PDB_DRAWABLE, drawable_ID (drawable),
  615.                         PDB_INT32, (gint32) cpnt,
  616.                         PDB_FLOATARRAY, stroke_points,
  617.                         PDB_END);
  618.       
  619.       if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
  620.     {
  621.       /* Not required */
  622.       /*gdisplays_flush ();*/
  623.     }
  624.       else
  625.     g_message (_("Paintbrush operation failed."));
  626.       
  627.       procedural_db_destroy_args (return_vals, nreturn_vals);
  628.       
  629.       cpnt = 0;
  630.       seg ++;
  631.       stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x1 - offx + 0.5);
  632.       stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y1 - offy + 0.5);
  633.     }
  634.  
  635.   /*  cleanup  */
  636.   gimage_mask_stroking = FALSE;
  637.   g_free (stroke_points);
  638.   g_free (stroke_segs);
  639.  
  640.   /*  End an undo group  */
  641.   undo_push_group_end (gimage);
  642.  
  643.   return TRUE;
  644. }
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.