home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / autocrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-13  |  7.7 KB  |  337 lines

  1. /*
  2.  * Autocrop plug-in version 1.00
  3.  * by Tim Newsome <drz@froody.bloke.com>
  4.  * thanks to quartic for finding a nasty bug for me
  5.  */
  6.  
  7. /* 1999/04/09 -- Sven Neumann <sven@gimp.org>
  8.  * Fixed bad crash that occured when running on an entirely blank image.
  9.  * Cleaned up the code a bit, while I was at it. 
  10.  */ 
  11.  
  12. #include "config.h"
  13.  
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <time.h>
  18.  
  19. #include <libgimp/gimp.h>
  20.  
  21. #include "libgimp/stdplugins-intl.h"
  22.  
  23.  
  24. /* Declare local functions. */
  25. static void query (void);
  26. static void run   (gchar   *name,
  27.            gint     nparams,
  28.            GimpParam  *param,
  29.            gint    *nreturn_vals,
  30.            GimpParam **return_vals);
  31.  
  32. static gint colors_equal  (guchar    *col1,
  33.                guchar    *col2,
  34.                gint       bytes);
  35. static gint guess_bgcolor (GimpPixelRgn *pr,
  36.                gint       width,
  37.                gint       height,
  38.                gint       bytes,
  39.                guchar    *color);
  40.  
  41. static void doit          (GimpDrawable *drawable,
  42.                gint32     image_id,
  43.                gboolean   show_progress);
  44.  
  45. GimpPlugInInfo PLUG_IN_INFO =
  46. {
  47.   NULL,      /* init_proc  */
  48.   NULL,   /* quit_proc  */
  49.   query,  /* query_proc */
  50.   run,      /* run_proc   */
  51. };
  52.  
  53. static gint bytes;
  54.  
  55. MAIN ()
  56.  
  57. static void
  58. query (void)
  59. {
  60.   static GimpParamDef args[] =
  61.   {
  62.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  63.     { GIMP_PDB_IMAGE, "image", "Input image" },
  64.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  65.   };
  66.   static gint nargs = sizeof (args) / sizeof (args[0]);
  67.  
  68.   gimp_install_procedure ("plug_in_autocrop",
  69.               "Automagically crops a picture.",
  70.               "",
  71.               "Tim Newsome",
  72.               "Tim Newsome",
  73.               "1997",
  74.               N_("<Image>/Image/Transforms/Autocrop"),
  75.               "RGB*, GRAY*, INDEXED*",
  76.               GIMP_PLUGIN,
  77.               nargs, 0,
  78.               args, NULL);
  79. }
  80.  
  81. static void
  82. run (gchar   *name,
  83.      gint     n_params,
  84.      GimpParam  *param,
  85.      gint    *nreturn_vals,
  86.      GimpParam **return_vals)
  87. {
  88.   static GimpParam values[1];
  89.   GimpDrawable *drawable;
  90.   GimpRunModeType run_mode;
  91.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  92.   gint32 image_id;
  93.   gboolean interactive;
  94.  
  95.   *nreturn_vals = 1;
  96.   *return_vals = values;
  97.   
  98.   run_mode = param[0].data.d_int32;
  99.   interactive = (run_mode != GIMP_RUN_NONINTERACTIVE);
  100.  
  101.   INIT_I18N();
  102.   
  103.   if (n_params != 3)
  104.     {
  105.       status = GIMP_PDB_CALLING_ERROR;
  106.       goto out;
  107.     }
  108.  
  109.   /*  Get the specified drawable  */
  110.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  111.   image_id = param[1].data.d_image;
  112.  
  113.   /*  Make sure that the drawable is gray or RGB color  */
  114.   if (gimp_drawable_is_rgb (drawable->id) ||
  115.       gimp_drawable_is_gray (drawable->id)  ||
  116.       gimp_drawable_is_indexed (drawable->id)) 
  117.   {
  118.     if (interactive)
  119.       gimp_progress_init (_("Cropping..."));
  120.  
  121.     gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width() + 1));
  122.  
  123.     doit (drawable, image_id, interactive);
  124.  
  125.     if (interactive)
  126.       gimp_displays_flush ();
  127.   } 
  128.   else 
  129.   {
  130.       status = GIMP_PDB_EXECUTION_ERROR;
  131.   }
  132.  
  133.  out:
  134.   values[0].type = GIMP_PDB_STATUS;
  135.   values[0].data.d_status = status;
  136. }
  137.  
  138. static void
  139. doit (GimpDrawable *drawable,
  140.       gint32        image_id,
  141.       gboolean      show_progress)
  142. {
  143.   GimpPixelRgn srcPR;
  144.   gint width, height;
  145.   gint x, y, abort;
  146.   gint32 nx, ny, nw, nh;
  147.   guchar *buffer;
  148.   guchar color[4] = {0, 0, 0, 0};
  149.   
  150.   width = drawable->width;
  151.   height = drawable->height;
  152.   bytes = drawable->bpp;
  153.   
  154.   nx = 0;
  155.   ny = 0;
  156.   nw = width;
  157.   nh = height;
  158.   
  159.   /*  initialize the pixel regions  */
  160.   gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  161.   
  162.   /* First, let's figure out what exactly to crop. */
  163.   buffer = g_malloc ((width > height ? width : height) * bytes);
  164.   
  165.   guess_bgcolor (&srcPR, width, height, bytes, color);
  166.   
  167.   /* Check how many of the top lines are uniform. */
  168.   abort = 0;
  169.   for (y = 0; y < height && !abort; y++)
  170.     {
  171.       gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width);
  172.       for (x = 0; x < width && !abort; x++)
  173.     {
  174.       abort = !colors_equal (color, buffer + x * bytes, bytes);
  175.     }
  176.     }
  177.   if (y == height && !abort)
  178.     {
  179.       g_free (buffer);
  180.       gimp_drawable_detach (drawable);
  181.       return;
  182.     }
  183.   y--;
  184.   ny = y;
  185.   nh = height - y;
  186.  
  187.   if (show_progress)
  188.     gimp_progress_update (0.25);
  189.   
  190.   /* Check how many of the bottom lines are uniform. */
  191.   abort = 0;
  192.   for (y = height - 1; y >= 0 && !abort; y--)
  193.     {
  194.       gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width);
  195.       for (x = 0; x < width && !abort; x++)
  196.     {
  197.       abort = !colors_equal (color, buffer + x * bytes, bytes);
  198.     }
  199.     }
  200.   nh = y - ny + 2;
  201.   
  202.   if (show_progress)
  203.     gimp_progress_update (0.5);
  204.   
  205.   /* Check how many of the left lines are uniform. */
  206.   abort = 0;
  207.   for (x = 0; x < width && !abort; x++)
  208.     {
  209.       gimp_pixel_rgn_get_col (&srcPR, buffer, x, ny, nh);
  210.       for (y = 0; y < nh && !abort; y++)
  211.     {
  212.       abort = !colors_equal (color, buffer + y * bytes, bytes);
  213.     }
  214.     }
  215.   x--;
  216.   nx = x;
  217.   nw = width - x;
  218.   
  219.   if (show_progress)
  220.     gimp_progress_update (0.75);
  221.   
  222.   /* Check how many of the right lines are uniform. */
  223.   abort = 0;
  224.   for (x = width - 1; x >= 0 && !abort; x--)
  225.     {
  226.       gimp_pixel_rgn_get_col (&srcPR, buffer, x, ny, nh);
  227.       for (y = 0; y < nh && !abort; y++)
  228.     {
  229.       abort = !colors_equal (color, buffer + y * bytes, bytes);
  230.     }
  231.     }
  232.   nw = x - nx + 2;
  233.   
  234.   g_free (buffer);
  235.   
  236.   gimp_drawable_detach (drawable);
  237.  
  238.   if (nw != width || nh != height)
  239.     gimp_crop (image_id, nw, nh, nx, ny);
  240.  
  241.   if (show_progress)
  242.     gimp_progress_update (1.00);
  243. }
  244.  
  245. static gint
  246. guess_bgcolor (GimpPixelRgn *pr,
  247.            gint       width,
  248.            gint       height,
  249.            gint       bytes,
  250.            guchar    *color)
  251. {
  252.   guchar tl[4], tr[4], bl[4], br[4];
  253.   
  254.   gimp_pixel_rgn_get_pixel (pr, tl, 0, 0);
  255.   gimp_pixel_rgn_get_pixel (pr, tr, width - 1, 0);
  256.   gimp_pixel_rgn_get_pixel (pr, bl, 0, height - 1);
  257.   gimp_pixel_rgn_get_pixel (pr, br, width - 1, height - 1);
  258.   
  259.   /* Algorithm pinched from pnmcrop.
  260.    * To guess the background, first see if 3 corners are equal.
  261.    * Then if two are equal.
  262.    * Otherwise average the colors.
  263.    */
  264.  
  265.   if (colors_equal (tr, bl, bytes) && colors_equal (tr, br, bytes))
  266.     {
  267.       memcpy (color, tr, bytes);
  268.       return 3;
  269.     }
  270.   else if (colors_equal (tl, bl, bytes) && colors_equal (tl, br, bytes))
  271.     {
  272.       memcpy (color, tl, bytes);
  273.       return 3;
  274.     }
  275.   else if (colors_equal (tl, tr, bytes) && colors_equal (tl, br, bytes))
  276.     {
  277.       memcpy (color, tl, bytes);
  278.       return 3;
  279.     }
  280.   else if (colors_equal (tl, tr, bytes) && colors_equal (tl, bl, bytes))
  281.     {
  282.       memcpy (color, tl, bytes);
  283.       return 3;
  284.     }
  285.   else if (colors_equal (tl, tr, bytes) || colors_equal (tl, bl, bytes) ||
  286.        colors_equal (tl, br, bytes))
  287.     {
  288.       memcpy (color, tl, bytes);
  289.       return 2;
  290.     }
  291.   else if (colors_equal (tr, bl, bytes) || colors_equal (tr, bl, bytes))
  292.     {
  293.       memcpy (color, tr, bytes);
  294.       return 2;
  295.     }
  296.   else if (colors_equal (br, bl, bytes))
  297.     {
  298.       memcpy (color, br, bytes);
  299.       return 2;
  300.     }
  301.   else
  302.     {
  303.       while (bytes--)
  304.     {
  305.       color[bytes] = (tl[bytes] + tr[bytes] + bl[bytes] + br[bytes]) / 4;
  306.     }
  307.       return 0;
  308.     }
  309. }
  310.  
  311. static gint 
  312. colors_equal (guchar *col1,
  313.           guchar *col2,
  314.           gint    bytes)
  315. {
  316.   gint equal = 1;
  317.   gint b;
  318.  
  319.   if ((bytes == 2 || bytes == 4) &&    /* HACK! */
  320.       col1[bytes-1] == 0 &&
  321.       col2[bytes-1] == 0)
  322.     {
  323.       return 1;                /* handle zero alpha */
  324.     }
  325.   
  326.   for (b = 0; b < bytes; b++)
  327.     {
  328.       if (col1[b] != col2[b])
  329.     {
  330.       equal = 0;
  331.       break;
  332.     }
  333.     }
  334.   
  335.   return equal;
  336. }
  337.