1997-11-25 06:05:25 +08:00
/****************************************************************************
1998-07-03 02:06:30 +08:00
* This is a plugin for the GIMP v 1.0 or later . Documentation is
1997-12-09 05:37:39 +08:00
* available at http : //www.rru.com/~meo/gimp/ .
1997-11-25 06:05:25 +08:00
*
1998-07-03 02:06:30 +08:00
* Copyright ( C ) 1997 - 8 Miles O ' Neal < meo @ rru . com > http : //www.rru.com/~meo/
1997-11-25 06:05:25 +08:00
* GUI based on GTK code from :
1997-12-09 05:37:39 +08:00
* alienmap ( Copyright ( C ) 1996 , 1997 Daniel Cotting )
* plasma ( Copyright ( C ) 1996 Stephen Norris ) ,
* oilify ( Copyright ( C ) 1996 Torsten Martinsen ) ,
* ripple ( Copyright ( C ) 1997 Brian Degenhardt ) and
* whirl ( Copyright ( C ) 1997 Federico Mena Quintero ) .
1997-11-25 06:05:25 +08:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program 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 General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
1998-04-13 13:44:11 +08:00
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
1997-11-25 06:05:25 +08:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
* Randomize :
*
1998-07-03 02:06:30 +08:00
* randomize version 1.7 ( 1 May 1998 , MEO )
1997-11-25 06:05:25 +08:00
*
* Please send any patches or suggestions to the author : meo @ rru . com .
*
* This plug - in adds a user - defined amount of randomization to an
* image . Variations include :
*
* - hurling ( spewing random colors )
* - picking a nearby pixel at random
* - slurring ( a crude form of melting )
*
* In any case , for each pixel in the selection or image ,
* whether to change the pixel is decided by picking a
* random number , weighted by the user ' s " randomization " percentage .
1998-05-01 07:42:31 +08:00
* If the random number is in range , the pixel is modified . Picking
1997-11-25 06:05:25 +08:00
* one selects the new pixel value at random from the current and
* adjacent pixels . Hurling assigns a random value to the pixel .
* Slurring sort of melts downwards ; if a pixel is to be slurred ,
* there is an 80 % chance the pixel above be used ; otherwise , one
* of the pixels adjacent to the one above is used ( even odds as
* to which it will be ) .
*
1998-05-01 07:42:31 +08:00
* Picking , hurling and slurring work with any image type .
1997-11-25 06:05:25 +08:00
*
* This plug - in ' s effectiveness varies a lot with the type
* and clarity of the image being " randomized " .
*
* Hurling more than 75 % or so onto an existing image will
* make the image nearly unrecognizable . By 90 % hurl , most
* images are indistinguishable from random noise .
*
* The repeat count is especially useful with slurring .
*
* TODO List
*
1997-12-09 05:37:39 +08:00
* - add a real melt function
1997-11-25 06:05:25 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-08 23:23:28 +08:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
1998-06-12 14:34:22 +08:00
# include <stdio.h>
1997-11-25 06:05:25 +08:00
# include <stdlib.h>
1999-05-29 09:28:24 +08:00
# include <string.h>
1997-11-25 06:05:25 +08:00
# include <time.h>
2000-01-08 23:23:28 +08:00
# include <gtk/gtk.h>
# include <libgimp/gimp.h>
# include <libgimp/gimpui.h>
1998-07-03 02:06:30 +08:00
2000-01-03 21:01:51 +08:00
# include "libgimp/stdplugins-intl.h"
2000-05-02 04:22:55 +08:00
1997-12-09 05:37:39 +08:00
/*********************************
*
* PLUGIN - SPECIFIC CONSTANTS
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-25 06:05:25 +08:00
/*
* progress meter update frequency
*/
# define PROG_UPDATE_TIME ((row % 10) == 0)
2000-01-12 01:41:07 +08:00
gchar * PLUG_IN_NAME [ ] =
{
" plug_in_randomize_hurl " ,
" plug_in_randomize_pick " ,
" plug_in_randomize_slur " ,
1998-07-03 02:06:30 +08:00
} ;
2000-01-12 01:41:07 +08:00
gchar * RNDM_VERSION [ ] =
{
2000-01-03 21:01:51 +08:00
N_ ( " Random Hurl 1.7 " ) ,
N_ ( " Random Pick 1.7 " ) ,
N_ ( " Random Slur 1.7 " ) ,
1998-07-03 02:06:30 +08:00
} ;
1997-11-25 06:05:25 +08:00
1998-05-01 07:42:31 +08:00
# define RNDM_HURL 1
# define RNDM_PICK 2
# define RNDM_SLUR 3
1997-11-25 06:05:25 +08:00
# define SEED_TIME 10
# define SEED_USER 11
# define SCALE_WIDTH 100
1998-07-03 02:06:30 +08:00
gint rndm_type = RNDM_HURL ; /* hurl, pick, etc. */
1997-12-09 05:37:39 +08:00
/*********************************
*
* PLUGIN - SPECIFIC STRUCTURES AND DATA
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-12 01:41:07 +08:00
typedef struct
{
gdouble rndm_pct ; /* likelihood of randomization (as %age) */
gdouble rndm_rcount ; /* repeat count */
2000-05-02 04:22:55 +08:00
gint seed_type ; /* seed init. type - current time or user value */
gint rndm_seed ; /* seed value for rand() function */
1997-11-25 06:05:25 +08:00
} RandomizeVals ;
2000-01-12 01:41:07 +08:00
static RandomizeVals pivals =
{
50.0 ,
1.0 ,
SEED_TIME ,
0 ,
1997-11-25 06:05:25 +08:00
} ;
2000-01-12 01:41:07 +08:00
typedef struct
{
gint run ;
1997-11-25 06:05:25 +08:00
} RandomizeInterface ;
2000-01-12 01:41:07 +08:00
static RandomizeInterface rndm_int =
{
FALSE /* have we run? */
1997-11-25 06:05:25 +08:00
} ;
/*********************************
*
* LOCAL FUNCTIONS
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-08 23:23:28 +08:00
static void query ( void ) ;
2000-01-12 01:41:07 +08:00
static void run ( gchar * name ,
gint nparams ,
2000-08-22 09:26:57 +08:00
GimpParam * param ,
2000-01-12 01:41:07 +08:00
gint * nreturn_vals ,
2000-08-22 09:26:57 +08:00
GimpParam * * return_vals ) ;
1997-11-25 06:05:25 +08:00
2000-08-22 09:26:57 +08:00
static void randomize ( GimpDrawable * drawable ) ;
2000-05-02 04:22:55 +08:00
2000-08-22 09:26:57 +08:00
static inline void randomize_prepare_row ( GimpPixelRgn * pixel_rgn ,
2000-05-02 04:22:55 +08:00
guchar * data ,
gint x ,
gint y ,
gint w ) ;
static gint randomize_dialog ( void ) ;
static void randomize_ok_callback ( GtkWidget * widget ,
gpointer data ) ;
/************************************ Guts ***********************************/
2000-08-22 09:26:57 +08:00
GimpPlugInInfo PLUG_IN_INFO =
2000-01-12 01:41:07 +08:00
{
2000-01-26 01:46:56 +08:00
NULL , /* init_proc */
NULL , /* quit_proc */
query , /* query_proc */
run , /* run_proc */
1997-11-25 06:05:25 +08:00
} ;
2000-01-16 23:38:38 +08:00
MAIN ( )
1997-11-25 06:05:25 +08:00
/*********************************
*
* query ( ) - query_proc
*
* called by the GIMP to learn about this plug - in
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
2000-01-08 23:23:28 +08:00
query ( void )
1997-11-25 06:05:25 +08:00
{
2000-08-22 09:26:57 +08:00
static GimpParamDef args [ ] =
2000-01-08 23:23:28 +08:00
{
2000-08-22 09:26:57 +08:00
{ GIMP_PDB_INT32 , " run_mode " , " Interactive, non-interactive " } ,
{ GIMP_PDB_IMAGE , " image " , " Input image (unused) " } ,
{ GIMP_PDB_DRAWABLE , " drawable " , " Input drawable " } ,
{ GIMP_PDB_FLOAT , " rndm_pct " , " Randomization percentage (1.0 - 100.0) " } ,
{ GIMP_PDB_FLOAT , " rndm_rcount " , " Repeat count (1.0 - 100.0) " } ,
{ GIMP_PDB_INT32 , " seed_type " , " Seed type (10 = current time, 11 = seed value) " } ,
{ GIMP_PDB_INT32 , " rndm_seed " , " Seed value (used only if seed type is 11) " }
2000-01-08 23:23:28 +08:00
} ;
2000-01-12 01:41:07 +08:00
static gint nargs = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
2000-01-08 23:23:28 +08:00
2000-01-12 01:41:07 +08:00
const gchar * hurl_blurb =
2000-01-31 10:32:30 +08:00
" Add a random factor to the image by hurling random data at it. " ;
2000-01-12 01:41:07 +08:00
const gchar * pick_blurb =
2000-01-31 10:32:30 +08:00
" Add a random factor to the image by picking a random adjacent pixel. " ;
2000-01-12 01:41:07 +08:00
const gchar * slur_blurb =
2000-01-31 10:32:30 +08:00
" Add a random factor to the image by slurring (similar to melting). " ;
2000-01-08 23:23:28 +08:00
2000-01-12 01:41:07 +08:00
const gchar * hurl_help =
2000-01-31 10:32:30 +08:00
" This plug-in ``hurls'' randomly-valued pixels onto the selection or image. You may select the percentage of pixels to modify and the number of times to repeat the process. " ;
2000-01-12 01:41:07 +08:00
const gchar * pick_help =
2000-01-31 10:32:30 +08:00
" This plug-in replaces a pixel with a random adjacent pixel. You may select the percentage of pixels to modify and the number of times to repeat the process. " ;
2000-01-12 01:41:07 +08:00
const gchar * slur_help =
2000-01-31 10:32:30 +08:00
" This plug-in slurs (melts like a bunch of icicles) an image. You may select the percentage of pixels to modify and the number of times to repeat the process. " ;
2000-01-08 23:23:28 +08:00
2000-01-12 01:41:07 +08:00
const gchar * author = " Miles O'Neal <meo@rru.com> http://www.rru.com/~meo/ " ;
const gchar * copyrights = " Miles O'Neal, Spencer Kimball, Peter Mattis, Torsten Martinsen, Brian Degenhardt, Federico Mena Quintero, Stephen Norris, Daniel Cotting " ;
const gchar * copyright_date = " 1995-1998 " ;
2000-01-08 23:23:28 +08:00
gimp_install_procedure ( PLUG_IN_NAME [ 0 ] ,
2000-01-12 01:41:07 +08:00
( gchar * ) hurl_blurb ,
( gchar * ) hurl_help ,
( gchar * ) author ,
( gchar * ) copyrights ,
( gchar * ) copyright_date ,
2000-01-08 23:23:28 +08:00
N_ ( " <Image>/Filters/Noise/Hurl... " ) ,
" RGB*, GRAY*, INDEXED* " ,
2000-08-22 09:26:57 +08:00
GIMP_PLUGIN ,
2000-02-04 23:12:17 +08:00
nargs , 0 ,
args , NULL ) ;
2000-01-08 23:23:28 +08:00
gimp_install_procedure ( PLUG_IN_NAME [ 1 ] ,
2000-01-12 01:41:07 +08:00
( gchar * ) pick_blurb ,
( gchar * ) pick_help ,
( gchar * ) author ,
( gchar * ) copyrights ,
( gchar * ) copyright_date ,
2000-01-08 23:23:28 +08:00
N_ ( " <Image>/Filters/Noise/Pick... " ) ,
" RGB*, GRAY*, INDEXED* " ,
2000-08-22 09:26:57 +08:00
GIMP_PLUGIN ,
2000-02-04 23:12:17 +08:00
nargs , 0 ,
args , NULL ) ;
2000-01-08 23:23:28 +08:00
gimp_install_procedure ( PLUG_IN_NAME [ 2 ] ,
2000-01-12 01:41:07 +08:00
( gchar * ) slur_blurb ,
( gchar * ) slur_help ,
( gchar * ) author ,
( gchar * ) copyrights ,
( gchar * ) copyright_date ,
2000-01-08 23:23:28 +08:00
N_ ( " <Image>/Filters/Noise/Slur... " ) ,
" RGB*, GRAY*, INDEXED* " ,
2000-08-22 09:26:57 +08:00
GIMP_PLUGIN ,
2000-02-04 23:12:17 +08:00
nargs , 0 ,
args , NULL ) ;
1997-11-25 06:05:25 +08:00
}
/*********************************
*
* run ( ) - main routine
*
* This handles the main interaction with the GIMP itself ,
* and invokes the routine that actually does the work .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
2000-01-12 01:41:07 +08:00
run ( gchar * name ,
gint nparams ,
2000-08-22 09:26:57 +08:00
GimpParam * param ,
2000-01-12 01:41:07 +08:00
gint * nreturn_vals ,
2000-08-22 09:26:57 +08:00
GimpParam * * return_vals )
1997-11-25 06:05:25 +08:00
{
2000-08-22 09:26:57 +08:00
GimpDrawable * drawable ;
GimpRunModeType run_mode ;
GimpPDBStatusType status = GIMP_PDB_SUCCESS ; /* assume the best! */
2000-01-12 01:41:07 +08:00
gchar * rndm_type_str = ' \0 ' ;
gchar prog_label [ 32 ] ;
2000-08-22 09:26:57 +08:00
static GimpParam values [ 1 ] ;
2000-01-08 23:23:28 +08:00
/*
* Get the specified drawable , do standard initialization .
*/
if ( strcmp ( name , PLUG_IN_NAME [ 0 ] ) = = 0 )
rndm_type = RNDM_HURL ;
else if ( strcmp ( name , PLUG_IN_NAME [ 1 ] ) = = 0 )
rndm_type = RNDM_PICK ;
else if ( strcmp ( name , PLUG_IN_NAME [ 2 ] ) = = 0 )
rndm_type = RNDM_SLUR ;
run_mode = param [ 0 ] . data . d_int32 ;
drawable = gimp_drawable_get ( param [ 2 ] . data . d_drawable ) ;
2000-08-22 09:26:57 +08:00
values [ 0 ] . type = GIMP_PDB_STATUS ;
2000-01-08 23:23:28 +08:00
values [ 0 ] . data . d_status = status ;
* nreturn_vals = 1 ;
* return_vals = values ;
/*
* Make sure the drawable type is appropriate .
*/
if ( gimp_drawable_is_rgb ( drawable - > id ) | |
1999-10-17 08:07:55 +08:00
gimp_drawable_is_gray ( drawable - > id ) | |
2000-01-08 23:23:28 +08:00
gimp_drawable_is_indexed ( drawable - > id ) )
{
switch ( run_mode )
{
/*
* If we ' re running interactively , pop up the dialog box .
*/
2000-08-22 09:26:57 +08:00
case GIMP_RUN_INTERACTIVE :
2000-01-08 23:23:28 +08:00
INIT_I18N_UI ( ) ;
gimp_get_data ( PLUG_IN_NAME [ rndm_type - 1 ] , & pivals ) ;
if ( ! randomize_dialog ( ) ) /* return on Cancel */
return ;
break ;
/*
* If we ' re not interactive ( probably scripting ) , we
* get the parameters from the param [ ] array , since
* we don ' t use the dialog box . Make sure they all
* parameters have legitimate values .
*/
2000-08-22 09:26:57 +08:00
case GIMP_RUN_NONINTERACTIVE :
2000-01-08 23:23:28 +08:00
if ( nparams ! = 7 )
{
2000-08-22 09:26:57 +08:00
status = GIMP_PDB_CALLING_ERROR ;
2000-01-08 23:23:28 +08:00
}
2000-02-05 06:18:50 +08:00
else
2000-01-08 23:23:28 +08:00
{
pivals . rndm_pct = ( gdouble ) param [ 3 ] . data . d_float ;
pivals . rndm_rcount = ( gdouble ) param [ 4 ] . data . d_float ;
pivals . seed_type = ( gint ) param [ 5 ] . data . d_int32 ;
pivals . rndm_seed = ( gint ) param [ 6 ] . data . d_int32 ;
2000-02-05 06:18:50 +08:00
if ( ( rndm_type ! = RNDM_PICK & &
rndm_type ! = RNDM_SLUR & &
rndm_type ! = RNDM_HURL ) | |
( pivals . rndm_pct < 1.0 | | pivals . rndm_pct > 100.0 ) | |
( pivals . rndm_rcount < 1.0 | | pivals . rndm_rcount > 100.0 ) )
{
2000-08-22 09:26:57 +08:00
status = GIMP_PDB_CALLING_ERROR ;
2000-02-05 06:18:50 +08:00
}
2000-01-08 23:23:28 +08:00
}
break ;
/*
* If we ' re running with the last set of values , get those values .
*/
2000-08-22 09:26:57 +08:00
case GIMP_RUN_WITH_LAST_VALS :
2000-02-05 06:18:50 +08:00
gimp_get_data ( PLUG_IN_NAME [ rndm_type - 1 ] , & pivals ) ;
2000-01-08 23:23:28 +08:00
break ;
/*
* Hopefully we never get here !
*/
default :
break ;
1998-05-01 07:42:31 +08:00
}
2000-08-22 09:26:57 +08:00
if ( status = = GIMP_PDB_SUCCESS )
2000-01-08 23:23:28 +08:00
{
/*
* JUST DO IT !
*/
switch ( rndm_type )
{
case RNDM_HURL : rndm_type_str = " hurl " ; break ;
case RNDM_PICK : rndm_type_str = " pick " ; break ;
case RNDM_SLUR : rndm_type_str = " slur " ; break ;
1998-02-20 18:41:20 +08:00
}
2000-01-08 23:23:28 +08:00
sprintf ( prog_label , " %s (%s) " , gettext ( RNDM_VERSION [ rndm_type - 1 ] ) ,
2000-02-13 08:11:26 +08:00
gettext ( rndm_type_str ) ) ;
2000-01-08 23:23:28 +08:00
gimp_progress_init ( prog_label ) ;
gimp_tile_cache_ntiles ( 2 * ( drawable - > width / gimp_tile_width ( ) + 1 ) ) ;
/*
* Initialize the rand ( ) function seed
*/
if ( pivals . seed_type = = SEED_TIME )
2000-01-26 01:46:56 +08:00
pivals . rndm_seed = time ( NULL ) ;
srand ( pivals . rndm_seed ) ;
2000-01-08 23:23:28 +08:00
2000-01-26 01:46:56 +08:00
randomize ( drawable ) ;
2000-01-08 23:23:28 +08:00
/*
* If we ran interactively ( even repeating ) update the display .
*/
2000-08-22 09:26:57 +08:00
if ( run_mode ! = GIMP_RUN_NONINTERACTIVE )
2000-01-08 23:23:28 +08:00
{
gimp_displays_flush ( ) ;
1998-05-01 07:42:31 +08:00
}
2000-01-08 23:23:28 +08:00
/*
* If we use the dialog popup , set the data for future use .
*/
2000-08-22 09:26:57 +08:00
if ( run_mode = = GIMP_RUN_INTERACTIVE )
2000-01-08 23:23:28 +08:00
{
gimp_set_data ( PLUG_IN_NAME [ rndm_type - 1 ] , & pivals ,
sizeof ( RandomizeVals ) ) ;
1998-05-01 07:42:31 +08:00
}
1998-02-20 18:41:20 +08:00
}
1997-11-25 06:05:25 +08:00
}
2000-01-08 23:23:28 +08:00
else
{
/*
* If we got the wrong drawable type , we need to complain .
*/
2000-08-22 09:26:57 +08:00
status = GIMP_PDB_EXECUTION_ERROR ;
2000-01-08 23:23:28 +08:00
}
/*
* DONE !
* Set the status where the GIMP can see it , and let go
* of the drawable .
*/
values [ 0 ] . data . d_status = status ;
gimp_drawable_detach ( drawable ) ;
1997-11-25 06:05:25 +08:00
}
/*********************************
*
* randomize_prepare_row ( )
*
* Get a row of pixels . If the requested row
* is off the edge , clone the edge row .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-02-20 18:41:20 +08:00
static inline void
2000-08-22 09:26:57 +08:00
randomize_prepare_row ( GimpPixelRgn * pixel_rgn ,
2000-01-08 23:23:28 +08:00
guchar * data ,
int x ,
int y ,
int w )
1997-11-25 06:05:25 +08:00
{
2000-01-08 23:23:28 +08:00
gint b ;
1997-11-25 06:05:25 +08:00
2000-01-08 23:23:28 +08:00
if ( y = = 0 )
{
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_get_row ( pixel_rgn , data , x , ( y + 1 ) , w ) ;
2000-01-08 23:23:28 +08:00
}
else if ( y = = pixel_rgn - > h )
{
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_get_row ( pixel_rgn , data , x , ( y - 1 ) , w ) ;
2000-01-08 23:23:28 +08:00
}
else
{
1997-11-25 06:05:25 +08:00
gimp_pixel_rgn_get_row ( pixel_rgn , data , x , y , w ) ;
}
2000-01-08 23:23:28 +08:00
/*
* Fill in edge pixels
*/
for ( b = 0 ; b < pixel_rgn - > bpp ; b + + )
{
data [ - ( gint ) pixel_rgn - > bpp + b ] = data [ b ] ;
data [ w * pixel_rgn - > bpp + b ] = data [ ( w - 1 ) * pixel_rgn - > bpp + b ] ;
1997-11-25 06:05:25 +08:00
}
}
/*********************************
*
* randomize ( )
*
* Actually mess with the image .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
2000-08-22 09:26:57 +08:00
randomize ( GimpDrawable * drawable )
1997-11-25 06:05:25 +08:00
{
2000-08-22 09:26:57 +08:00
GimpPixelRgn srcPR , destPR , destPR2 , * sp , * dp , * tp ;
2000-01-08 23:23:28 +08:00
gint width , height ;
gint bytes ;
guchar * dest , * d ;
guchar * prev_row , * pr ;
guchar * cur_row , * cr ;
guchar * next_row , * nr ;
guchar * tmp ;
gint row , col ;
gint x1 , y1 , x2 , y2 ;
gint cnt ;
gint has_alpha , ind ;
/*
* Get the input area . This is the bounding box of the selection in
* the image ( or the entire image if there is no selection ) . Only
* operating on the input area is simply an optimization . It doesn ' t
* need to be done for correct operation . ( It simply makes it go
* faster , since fewer pixels need to be operated on ) .
*/
gimp_drawable_mask_bounds ( drawable - > id , & x1 , & y1 , & x2 , & y2 ) ;
/*
* Get the size of the input image . ( This will / must be the same
* as the size of the output image . Also get alpha info .
*/
width = drawable - > width ;
height = drawable - > height ;
bytes = drawable - > bpp ;
has_alpha = gimp_drawable_has_alpha ( drawable - > id ) ;
/*
* allocate row buffers
*/
2000-01-12 01:41:07 +08:00
prev_row = g_new ( guchar , ( x2 - x1 + 2 ) * bytes ) ;
cur_row = g_new ( guchar , ( x2 - x1 + 2 ) * bytes ) ;
next_row = g_new ( guchar , ( x2 - x1 + 2 ) * bytes ) ;
dest = g_new ( guchar , ( x2 - x1 ) * bytes ) ;
2000-01-08 23:23:28 +08:00
/*
* 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 ) ;
gimp_pixel_rgn_init ( & destPR2 , drawable , 0 , 0 , width , height , TRUE , TRUE ) ;
sp = & srcPR ;
dp = & destPR ;
tp = NULL ;
pr = prev_row + bytes ;
cr = cur_row + bytes ;
nr = next_row + bytes ;
for ( cnt = 1 ; cnt < = pivals . rndm_rcount ; cnt + + )
{
/*
* prepare the first row and previous row
*/
randomize_prepare_row ( sp , pr , x1 , y1 - 1 , ( x2 - x1 ) ) ;
randomize_prepare_row ( dp , cr , x1 , y1 , ( x2 - x1 ) ) ;
/*
* loop through the rows , applying the selected convolution
*/
for ( row = y1 ; row < y2 ; row + + )
{
/* prepare the next row */
randomize_prepare_row ( sp , nr , x1 , row + 1 , ( x2 - x1 ) ) ;
d = dest ;
ind = 0 ;
for ( col = 0 ; col < ( x2 - x1 ) * bytes ; col + + )
{
if ( ( ( rand ( ) % 100 ) ) < = ( gint ) pivals . rndm_pct )
{
switch ( rndm_type )
{
/*
* HURL
* Just assign a random value .
*/
case RNDM_HURL :
* d + + = rand ( ) % 256 ;
1998-05-01 07:42:31 +08:00
break ;
2000-01-08 23:23:28 +08:00
/*
* PICK
* pick at random from a neighboring pixel .
*/
case RNDM_PICK :
switch ( rand ( ) % 9 )
{
case 0 :
* d + + = ( gint ) pr [ col - bytes ] ;
break ;
case 1 :
* d + + = ( gint ) pr [ col ] ;
break ;
case 2 :
* d + + = ( gint ) pr [ col + bytes ] ;
break ;
case 3 :
* d + + = ( gint ) cr [ col - bytes ] ;
break ;
case 4 :
* d + + = ( gint ) cr [ col ] ;
break ;
case 5 :
* d + + = ( gint ) cr [ col + bytes ] ;
break ;
case 6 :
* d + + = ( gint ) nr [ col - bytes ] ;
break ;
case 7 :
* d + + = ( gint ) nr [ col ] ;
break ;
case 8 :
* d + + = ( gint ) nr [ col + bytes ] ;
break ;
1998-05-01 07:42:31 +08:00
}
break ;
2000-01-08 23:23:28 +08:00
/*
* SLUR
* 80 % chance it ' s from directly above ,
* 10 % from above left ,
* 10 % from above right .
*/
case RNDM_SLUR :
switch ( rand ( ) % 10 )
{
case 0 :
* d + + = ( gint ) pr [ col - bytes ] ;
break ;
case 9 :
* d + + = ( gint ) pr [ col + bytes ] ;
break ;
default :
* d + + = ( gint ) pr [ col ] ;
break ;
1998-05-01 07:42:31 +08:00
}
break ;
}
2000-01-08 23:23:28 +08:00
/*
* Otherwise , this pixel was not selected for randomization ,
* so use the current value .
*/
}
else
{
* d + + = ( gint ) cr [ col ] ;
1998-05-01 07:42:31 +08:00
}
}
2000-01-08 23:23:28 +08:00
/*
* Save the modified row , shuffle the row pointers , and every
* so often , update the progress meter .
*/
gimp_pixel_rgn_set_row ( dp , dest , x1 , row , ( x2 - x1 ) ) ;
tmp = pr ;
pr = cr ;
cr = nr ;
nr = tmp ;
if ( PROG_UPDATE_TIME )
gimp_progress_update ( ( double ) row / ( double ) ( y2 - y1 ) ) ;
1998-05-01 07:42:31 +08:00
}
2000-01-08 23:23:28 +08:00
/*
* if we have more cycles to perform , swap the src and dest Pixel Regions
*/
if ( cnt < pivals . rndm_rcount )
{
if ( tp ! = NULL )
{
tp = dp ;
dp = sp ;
sp = tp ;
}
else
{
tp = & srcPR ;
sp = & destPR ;
dp = & destPR2 ;
1998-05-01 07:42:31 +08:00
}
1997-12-09 05:37:39 +08:00
}
1997-11-25 06:05:25 +08:00
}
2000-01-08 23:23:28 +08:00
gimp_progress_update ( ( double ) 100 ) ;
/*
* update the randomized region
*/
gimp_drawable_flush ( drawable ) ;
gimp_drawable_merge_shadow ( drawable - > id , TRUE ) ;
gimp_drawable_update ( drawable - > id , x1 , y1 , ( x2 - x1 ) , ( y2 - y1 ) ) ;
/*
* clean up after ourselves .
*/
2000-01-12 01:41:07 +08:00
g_free ( prev_row ) ;
g_free ( cur_row ) ;
g_free ( next_row ) ;
g_free ( dest ) ;
1997-11-25 06:05:25 +08:00
}
/*********************************
*
* GUI ROUTINES
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*********************************
*
* randomize_dialog ( ) - set up the plug - in ' s dialog box
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static gint
2000-01-08 23:23:28 +08:00
randomize_dialog ( void )
1997-11-25 06:05:25 +08:00
{
2000-01-08 23:23:28 +08:00
GtkWidget * dlg ;
GtkWidget * frame ;
GtkWidget * table ;
2000-01-26 01:46:56 +08:00
GtkWidget * seed_hbox ;
2000-01-16 23:38:38 +08:00
GtkObject * adj ;
2000-01-08 23:23:28 +08:00
2000-05-02 04:22:55 +08:00
gimp_ui_init ( " randomize " , FALSE ) ;
2000-01-08 23:23:28 +08:00
dlg = gimp_dialog_new ( gettext ( RNDM_VERSION [ rndm_type - 1 ] ) , " randomize " ,
2000-05-23 01:10:28 +08:00
gimp_standard_help_func , " filters/randomize.html " ,
2000-01-08 23:23:28 +08:00
GTK_WIN_POS_MOUSE ,
FALSE , TRUE , FALSE ,
_ ( " OK " ) , randomize_ok_callback ,
NULL , NULL , NULL , TRUE , FALSE ,
_ ( " Cancel " ) , gtk_widget_destroy ,
NULL , 1 , NULL , FALSE , TRUE ,
NULL ) ;
gtk_signal_connect ( GTK_OBJECT ( dlg ) , " destroy " ,
GTK_SIGNAL_FUNC ( gtk_main_quit ) ,
NULL ) ;
2000-01-26 01:46:56 +08:00
gimp_help_init ( ) ;
2000-01-08 23:23:28 +08:00
/*
* Parameter settings
*
* First set up the basic containers , label them , etc .
*/
frame = gtk_frame_new ( _ ( " Parameter Settings " ) ) ;
gtk_frame_set_shadow_type ( GTK_FRAME ( frame ) , GTK_SHADOW_ETCHED_IN ) ;
gtk_container_set_border_width ( GTK_CONTAINER ( frame ) , 6 ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dlg ) - > vbox ) , frame , TRUE , TRUE , 0 ) ;
2000-01-26 01:46:56 +08:00
table = gtk_table_new ( 3 , 3 , FALSE ) ;
2000-01-08 23:23:28 +08:00
gtk_table_set_col_spacings ( GTK_TABLE ( table ) , 4 ) ;
gtk_table_set_row_spacings ( GTK_TABLE ( table ) , 2 ) ;
gtk_container_set_border_width ( GTK_CONTAINER ( table ) , 4 ) ;
gtk_container_add ( GTK_CONTAINER ( frame ) , table ) ;
gtk_widget_show ( table ) ;
2000-01-12 01:41:07 +08:00
2000-01-26 01:46:56 +08:00
/* Random Seed */
2000-02-23 23:52:33 +08:00
seed_hbox = gimp_random_seed_new ( & pivals . rndm_seed ,
& pivals . seed_type ,
2000-01-26 01:46:56 +08:00
SEED_TIME , SEED_USER ) ;
2000-01-31 11:13:02 +08:00
gimp_table_attach_aligned ( GTK_TABLE ( table ) , 0 , 0 ,
2000-01-26 01:46:56 +08:00
_ ( " Random Seed: " ) , 1.0 , 0.5 ,
2000-01-31 11:13:02 +08:00
seed_hbox , 1 , TRUE ) ;
2000-01-16 23:38:38 +08:00
2000-01-08 23:23:28 +08:00
/*
* Randomization percentage label & scale ( 1 to 100 )
*/
2000-01-26 01:46:56 +08:00
adj = gimp_scale_entry_new ( GTK_TABLE ( table ) , 0 , 1 ,
2000-02-05 06:18:50 +08:00
_ ( " Randomization (%): " ) , SCALE_WIDTH , 0 ,
2000-01-16 23:38:38 +08:00
pivals . rndm_pct , 1.0 , 100.0 , 1.0 , 10.0 , 0 ,
2000-02-04 23:12:17 +08:00
TRUE , 0 , 0 ,
2000-01-16 23:38:38 +08:00
_ ( " Percentage of pixels to be filtered " ) , NULL ) ;
gtk_signal_connect ( GTK_OBJECT ( adj ) , " value_changed " ,
GTK_SIGNAL_FUNC ( gimp_int_adjustment_update ) ,
2000-01-12 01:41:07 +08:00
& pivals . rndm_pct ) ;
2000-01-16 23:38:38 +08:00
2000-01-08 23:23:28 +08:00
/*
* Repeat count label & scale ( 1 to 100 )
*/
2000-01-26 01:46:56 +08:00
adj = gimp_scale_entry_new ( GTK_TABLE ( table ) , 0 , 2 ,
2000-01-16 23:38:38 +08:00
_ ( " Repeat: " ) , SCALE_WIDTH , 0 ,
pivals . rndm_rcount , 1.0 , 100.0 , 1.0 , 10.0 , 0 ,
2000-02-04 23:12:17 +08:00
TRUE , 0 , 0 ,
2000-01-16 23:38:38 +08:00
_ ( " Number of times to apply filter " ) , NULL ) ;
gtk_signal_connect ( GTK_OBJECT ( adj ) , " value_changed " ,
2000-02-10 08:08:27 +08:00
GTK_SIGNAL_FUNC ( gimp_double_adjustment_update ) ,
2000-01-12 01:41:07 +08:00
& pivals . rndm_rcount ) ;
2000-01-16 23:38:38 +08:00
2000-01-08 23:23:28 +08:00
gtk_widget_show ( frame ) ;
2000-01-16 23:38:38 +08:00
2000-01-08 23:23:28 +08:00
gtk_widget_show ( dlg ) ;
gtk_main ( ) ;
2000-01-12 01:41:07 +08:00
gimp_help_free ( ) ;
2000-01-08 23:23:28 +08:00
gdk_flush ( ) ;
2000-01-16 23:38:38 +08:00
2000-01-08 23:23:28 +08:00
return rndm_int . run ;
1997-11-25 06:05:25 +08:00
}
static void
2000-01-08 23:23:28 +08:00
randomize_ok_callback ( GtkWidget * widget ,
gpointer data )
{
rndm_int . run = TRUE ;
gtk_widget_destroy ( GTK_WIDGET ( data ) ) ;
1997-11-25 06:05:25 +08:00
}