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 / zealouscrop.c < prev   
Encoding:
C/C++ Source or Header  |  2000-08-24  |  6.3 KB  |  288 lines

  1. /*
  2.  * ZealousCrop plug-in version 1.00
  3.  * by Adam D. Moss <adam@foxbox.org>
  4.  * loosely based on Autocrop by Tim Newsome <drz@froody.bloke.com>
  5.  */
  6.  
  7. /*
  8.  * BUGS:
  9.  *  Doesn't undo properly.
  10.  *  Progress bar doesn't do anything yet.
  11.  */
  12.  
  13. #include "config.h"
  14.  
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <time.h>
  18.  
  19. #include <libgimp/gimp.h>
  20.  
  21. #include "libgimp/stdplugins-intl.h"
  22.  
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. /* Declare local functions. */
  29. static void query (void);
  30. static void run   (gchar    *name,
  31.            gint     nparams,
  32.            GimpParam  *param,
  33.            gint    *nreturn_vals,
  34.            GimpParam **return_vals);
  35. static inline gint colours_equal (guchar *col1,
  36.                   guchar *col2,
  37.                   gint    bytes);
  38.  
  39. static void do_zcrop (GimpDrawable *drawable,
  40.               gint32     image_id);
  41.  
  42. GimpPlugInInfo PLUG_IN_INFO =
  43. {
  44.   NULL,  /* init_proc  */
  45.   NULL,  /* quit_proc  */
  46.   query, /* query_proc */
  47.   run,   /* run_proc   */
  48. };
  49.  
  50. static gint bytes;
  51.  
  52.  
  53. MAIN ()
  54.  
  55. static void
  56. query (void)
  57. {
  58.   static GimpParamDef args[] =
  59.   {
  60.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  61.     { GIMP_PDB_IMAGE, "image", "Input image" },
  62.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  63.   };
  64.   static gint nargs = sizeof (args) / sizeof (args[0]);
  65.  
  66.   gimp_install_procedure("plug_in_zealouscrop",
  67.              "Automagically crops unused space from the edges and middle of a picture.",
  68.              "",
  69.              "Adam D. Moss",
  70.              "Adam D. Moss",
  71.              "1997",
  72.              N_("<Image>/Image/Transforms/Zealous Crop"),
  73.              "RGB*, GRAY*, INDEXED*",
  74.              GIMP_PLUGIN,
  75.              nargs, 0,
  76.              args, NULL);
  77. }
  78.  
  79. static void
  80. run (gchar   *name,
  81.      gint     n_params,
  82.      GimpParam  *param,
  83.      gint    *nreturn_vals,
  84.      GimpParam **return_vals)
  85. {
  86.   static GimpParam values[1];
  87.   GimpDrawable *drawable;
  88.   GimpRunModeType run_mode;
  89.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  90.   gint32 image_id;
  91.  
  92.   INIT_I18N();
  93.  
  94.   *nreturn_vals = 1;
  95.   *return_vals = values;
  96.  
  97.   run_mode = param[0].data.d_int32;
  98.  
  99.   if (run_mode == GIMP_RUN_NONINTERACTIVE)
  100.     {
  101.       if (n_params != 3)
  102.     {
  103.       status = GIMP_PDB_CALLING_ERROR;
  104.     }
  105.     }
  106.  
  107.   if (status == GIMP_PDB_SUCCESS)
  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 or indexed  */
  114.       if (gimp_drawable_is_rgb (drawable->id) ||
  115.       gimp_drawable_is_gray (drawable->id) ||
  116.       gimp_drawable_is_indexed (drawable->id))
  117.     {
  118.       gimp_progress_init (_("ZealousCropping(tm)..."));
  119.  
  120.       gimp_tile_cache_ntiles (1 +
  121.                   2 * (drawable->width > drawable->height ?
  122.                        (drawable->width / gimp_tile_width()) :
  123.                        (drawable->height / gimp_tile_height())));
  124.  
  125.       do_zcrop(drawable, image_id);
  126.  
  127.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  128.         gimp_displays_flush();
  129.  
  130.       gimp_drawable_detach(drawable);
  131.     }
  132.       else
  133.     {
  134.       status = GIMP_PDB_EXECUTION_ERROR;
  135.     }
  136.     }
  137.  
  138.   values[0].type = GIMP_PDB_STATUS;
  139.   values[0].data.d_status = status;
  140. }
  141.  
  142. static void
  143. do_zcrop (GimpDrawable *drawable,
  144.       gint32     image_id)
  145. {
  146.   GimpPixelRgn srcPR, destPR;
  147.   gint    width, height, x, y;
  148.   guchar *buffer;
  149.   gint8  *killrows;
  150.   gint8  *killcols;
  151.   gint32  livingrows, livingcols, destrow, destcol;
  152.   gint    total_area, area;
  153.  
  154.   width = drawable->width;
  155.   height = drawable->height;
  156.   bytes = drawable->bpp;
  157.  
  158.   total_area = width * height * 4;
  159.   area = 0;
  160.  
  161.   killrows = g_malloc (sizeof(gint8)*height);
  162.   killcols = g_malloc (sizeof(gint8)*width);
  163.  
  164.   buffer = g_malloc ((width > height ? width : height) * bytes);
  165.  
  166.   /*  initialize the pixel regions  */
  167.   gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  168.   gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
  169.  
  170.   livingrows = 0;
  171.   for (y=0; y<height; y++)
  172.     {
  173.       gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width);
  174.  
  175.       killrows[y] = TRUE;
  176.  
  177.       for (x=0; x<width*bytes; x+=bytes)
  178.     {
  179.       if (!colours_equal (buffer, &buffer[x], bytes))
  180.         {
  181.           livingrows++;
  182.           killrows[y] = FALSE;
  183.           break;
  184.         }
  185.     }
  186.  
  187.       area += width;
  188.       if (y % 20)
  189.     gimp_progress_update ((double) area / (double) total_area);
  190.     }
  191.  
  192.  
  193.   livingcols = 0;
  194.   for (x=0; x<width; x++)
  195.     {
  196.       gimp_pixel_rgn_get_col (&srcPR, buffer, x, 0, height);
  197.  
  198.       killcols[x] = TRUE;
  199.  
  200.       for (y=0; y<height*bytes; y+=bytes)
  201.     {
  202.       if (!colours_equal(buffer, &buffer[y], bytes))
  203.         {
  204.           livingcols++;
  205.           killcols[x] = FALSE;
  206.           break;
  207.         }
  208.     }
  209.  
  210.       area += height;
  211.       if (x % 20)
  212.     gimp_progress_update ((double) area / (double) total_area);
  213.     }
  214.  
  215.  
  216.   if (((livingcols==0) || (livingrows==0)) ||
  217.       ((livingcols==width) && (livingrows==height)))
  218.     {
  219.       printf("ZealousCrop(tm): Nothing to be done.\n");
  220.       return;
  221.     }
  222.  
  223.   destrow = 0;
  224.  
  225.   for (y=0; y<height; y++)
  226.     {
  227.       if (!killrows[y])
  228.     {
  229.       gimp_pixel_rgn_get_row(&srcPR, buffer, 0, y, width);
  230.       gimp_pixel_rgn_set_row(&destPR, buffer, 0, destrow, width);
  231.       destrow++;
  232.     }
  233.  
  234.       area += width;
  235.       if (y % 20)
  236.     gimp_progress_update ((double) area / (double) total_area);
  237.     }
  238.  
  239.  
  240.   destcol = 0;
  241.   gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, TRUE);
  242.  
  243.   for (x=0; x<width; x++)
  244.     {
  245.       if (!killcols[x])
  246.     {
  247.       gimp_pixel_rgn_get_col(&srcPR, buffer, x, 0, height);
  248.       gimp_pixel_rgn_set_col(&destPR, buffer, destcol, 0, height);
  249.       destcol++;
  250.     }
  251.  
  252.       area += height;
  253.       if (x % 20)
  254.     gimp_progress_update ((double) area / (double) total_area);
  255.     }
  256.  
  257. /*  printf("dc: %d, lc: %d  - - - dr: %d, lr: %d\n",destcol, livingcols, destrow, livingrows);*/
  258.  
  259.     g_free(buffer);
  260.  
  261.     g_free(killrows);
  262.     g_free(killcols);
  263.  
  264.     gimp_progress_update(1.00);
  265.     gimp_undo_push_group_start (image_id);
  266.     gimp_drawable_flush (drawable);
  267.     gimp_drawable_merge_shadow (drawable->id, TRUE);
  268.     gimp_crop (image_id, livingcols, livingrows, 0, 0);
  269.     gimp_undo_push_group_end (image_id);
  270. }
  271.  
  272.  
  273. static inline int colours_equal(guchar *col1, guchar *col2, int bytes)
  274. {
  275.   int b;
  276.  
  277.   for (b = 0; b < bytes; b++)
  278.     {
  279.       if (col1[b] != col2[b])
  280.     {
  281.       return (FALSE);
  282.       break;
  283.     }
  284.     }
  285.  
  286.   return TRUE;
  287. }
  288.