/******************************************************************************* papertile.c -- This is a plug-in for the GIMP 1.0 Copyright (C) 1997 Hirotsuna Mizuno s1041150@u-aizu.ac.jp 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 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *******************************************************************************/ #include #include #include #define PLUG_IN_NAME "plug_in_paper_tile" #define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)" #define DIALOG_CAPTION "Paper Tile" /******************************************************************************/ static void query( void ); static void run( char *, int, GParam *, int *, GParam ** ); static void filter( GDrawable *drawable ); static int dialog( void ); /******************************************************************************/ #define BG_TYPE_TRANSPARENT 0 #define BG_TYPE_BLACK 1 #define BG_TYPE_WHITE 2 typedef struct { gint32 tile_width; gint32 tile_height; gint32 slide_length; gint32 bg_type; } parameter_t; /******************************************************************************/ GPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; static parameter_t parameters = { 50, 50, 10, BG_TYPE_TRANSPARENT }; static gint image_width; static gint image_height; static gint image_bpp; static gint image_has_alpha; static gint select_x1; static gint select_y1; static gint select_x2; static gint select_y2; static gint select_width; static gint select_height; /******************************************************************************/ MAIN() /******************************************************************************/ static void query( void ) { static int nargs = 7; static GParamDef args[] = { { PARAM_INT32, "run_mode", "interactive / non-interactive" }, { PARAM_IMAGE, "image", "input image" }, { PARAM_DRAWABLE, "drawable", "input drawable" }, { PARAM_INT32, "width", "tile width" }, { PARAM_INT32, "height", "tile height" }, { PARAM_INT32, "slide_length", "slide length" }, { PARAM_INT32, "bg_type", "background color " "(0=transparent, 1=black, 2=white )" } }; static int nreturn_vals = 0; static GParamDef *return_vals = NULL; gimp_install_procedure( PLUG_IN_NAME, "cut and slide image", "cut and slide image", "Hirotsuna Mizuno ", "Hirotsuna Mizuno", PLUG_IN_VERSION, "/Filters/Map/Paper Tile", "RGB*, GRAY*", PROC_PLUG_IN, nargs, nreturn_vals, args, return_vals ); } /******************************************************************************/ static void run( char *name, int paramc, GParam *params, int *returnc, GParam **returns ) { GDrawable *drawable; GRunModeType run_mode; static GParam returnv[1]; GStatusType status = STATUS_SUCCESS; run_mode = params[0].data.d_int32; drawable = gimp_drawable_get( params[2].data.d_drawable ); *returnc = 1; *returns = returnv; /* get the drawable info */ image_width = gimp_drawable_width( drawable->id ); image_height = gimp_drawable_height( drawable->id ); image_bpp = gimp_drawable_bpp( drawable->id ); image_has_alpha = gimp_drawable_has_alpha( drawable->id ); gimp_drawable_mask_bounds( drawable->id, &select_x1, &select_y1, &select_x2, &select_y2 ); select_width = select_x2 - select_x1; select_height = select_y2 - select_y1; /* switch the run mode */ switch( run_mode ){ case RUN_INTERACTIVE: gimp_get_data( PLUG_IN_NAME, ¶meters ); if( ! dialog() ) return; gimp_set_data( PLUG_IN_NAME, ¶meters, sizeof( parameter_t ) ); break; case RUN_NONINTERACTIVE: if( paramc != 7 ){ status = STATUS_CALLING_ERROR; } else { parameters.tile_width = params[3].data.d_int32; parameters.tile_height = params[4].data.d_int32; parameters.slide_length = params[5].data.d_int32; parameters.bg_type = params[6].data.d_int32; } break; case RUN_WITH_LAST_VALS: gimp_get_data( PLUG_IN_NAME, ¶meters ); break; } if( status == STATUS_SUCCESS ){ if( gimp_drawable_color( drawable->id ) || gimp_drawable_gray( drawable->id ) ){ gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) ); filter( drawable ); if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush (); } else { status = STATUS_EXECUTION_ERROR; } } returnv[0].type = PARAM_STATUS; returnv[0].data.d_status = status; gimp_drawable_detach( drawable ); } /******************************************************************************/ static void filter( GDrawable *drawable ) { GPixelRgn srcPR, destPR; guchar **pixels; guchar **destpixels; gint x, y, b; gint vx, vy, xx, yy; gimp_pixel_rgn_init( &srcPR, drawable, 0, 0, image_width, image_height, FALSE, FALSE ); gimp_pixel_rgn_init( &destPR, drawable, 0, 0, image_width, image_height, TRUE, TRUE ); pixels = (guchar **)malloc( image_height * sizeof(guchar *) ); destpixels = (guchar **)malloc( image_height * sizeof(guchar *) ); for( y = 0; y < image_height; y++ ){ pixels[y] = (guchar *)malloc( image_width * image_bpp ); destpixels[y] = (guchar *)malloc( image_width * image_bpp ); gimp_pixel_rgn_get_row( &srcPR, pixels[y], 0, y, image_width ); } for( y = select_y1; y < select_y2; y++ ){ for( x = select_x1; x < select_x2; x++ ){ switch( parameters.bg_type ){ case BG_TYPE_TRANSPARENT: for( b = 0; b < image_bpp; b++ ){ destpixels[y][x*image_bpp+b] = 0; } break; case BG_TYPE_BLACK: for( b = 0; b < image_bpp; b++ ){ if( b == image_bpp - 1 && image_has_alpha ){ destpixels[y][x*image_bpp+b] = 255; } else { destpixels[y][x*image_bpp+b] = 0; } } break; case BG_TYPE_WHITE: for( b = 0; b < image_bpp; b++ ){ destpixels[y][x*image_bpp+b] = 255; } break; } } } gimp_progress_init( PLUG_IN_NAME ); for( y = select_y1; y < select_y2; y+=parameters.tile_height ) for( x = select_x1; x < select_x2; x+=parameters.tile_width ){ vx = rand()%parameters.slide_length - parameters.slide_length/2; vy = rand()%parameters.slide_length - parameters.slide_length/2; for( xx = 0; xx < parameters.tile_width; xx++ ) if( 0 <= x+xx+vx && x+xx+vx < image_width && x+xx < image_width ) for( yy = 0; yy < parameters.tile_height; yy++ ) if( 0 <= y+yy+vy && y+yy+vy < image_height && y+yy < image_height ) for( b = 0; b < image_bpp; b++ ) destpixels[y+yy+vy][(x+xx+vx)*image_bpp+b] = pixels[y+yy][(x+xx)*image_bpp+b]; } for( y = select_y1; y < select_y2; y++ ){ gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width ); gimp_progress_update ( (double)( y - select_y1 ) / select_height ); } gimp_drawable_flush( drawable ); gimp_drawable_merge_shadow( drawable->id, TRUE ); gimp_drawable_update( drawable->id, select_x1, select_y1, select_width, select_height ); for( y = select_y1; y < select_y2; y++ ) free( pixels[y-select_y1] ); free( pixels ); for( y = select_y1; y < select_y2; y++ ) free( destpixels[y-select_y1] ); free( destpixels ); } /******************************************************************************/ static int dialog_status; static GtkWidget *entry_width; static GtkWidget *entry_height; static GtkWidget *entry_slide; static GtkWidget *button_transparent; static GtkWidget *button_black; static GtkWidget *button_white; static void dialog_destroy_handler( GtkWidget *widget, gpointer *data ) { gtk_main_quit(); } static void dialog_ok_handler( GtkWidget *widget, gpointer *data ) { dialog_status = TRUE; if( GTK_TOGGLE_BUTTON( button_white )->active ) parameters.bg_type = BG_TYPE_WHITE; if( GTK_TOGGLE_BUTTON( button_black )->active ) parameters.bg_type = BG_TYPE_BLACK; if( image_has_alpha ){ if( GTK_TOGGLE_BUTTON( button_transparent )->active ){ parameters.bg_type = BG_TYPE_TRANSPARENT; } } parameters.tile_width = (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_width ) ) ); parameters.tile_height = (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_height ) ) ); parameters.slide_length = (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_slide ) ) ); gtk_widget_destroy( GTK_WIDGET( data ) ); } static void dialog_cancel_handler( GtkWidget *widget, gpointer *data ) { dialog_status = FALSE; gtk_widget_destroy( GTK_WIDGET( data ) ); } /******************************************************************************/ static int dialog( void ) { GtkWidget *window; dialog_status = FALSE; { gint argc = 1; gchar **argv = g_new( gchar *, 1 ); argv[0] = g_strdup( DIALOG_CAPTION ); gtk_init( &argc, &argv ); gtk_rc_parse(gimp_gtkrc()); } /* dialog window */ window = gtk_dialog_new(); gtk_signal_connect( GTK_OBJECT( window ), "destroy", GTK_SIGNAL_FUNC( dialog_destroy_handler ), NULL ); gtk_container_border_width( GTK_CONTAINER( window ), 0 ); gtk_container_border_width( GTK_CONTAINER( GTK_DIALOG( window )->vbox ), 5 ); { /* buttons */ GtkWidget *button; /* ok button */ button = gtk_button_new_with_label( "OK" ); gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( dialog_ok_handler ), GTK_OBJECT( window ) ); GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT ); gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), button, TRUE, TRUE, 0 ); gtk_widget_grab_default( button ); gtk_widget_show( button ); /* cancel button */ button = gtk_button_new_with_label( "Cancel" ); gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( dialog_cancel_handler ), GTK_OBJECT( window )); gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), button, TRUE, TRUE, 0 ); gtk_widget_show( button ); } { /* text boxes */ GtkWidget *table; GtkWidget *label; char buffer[32]; /* table */ table = gtk_table_new( 3, 2, FALSE ); gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), table, TRUE, TRUE, 0 ); gtk_widget_show( table ); /* tile width */ label = gtk_label_new( "width: " ); entry_width = gtk_entry_new(); sprintf( buffer, "%d", parameters.tile_width ); gtk_entry_set_text( GTK_ENTRY( entry_width ), buffer ); gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 0, 1 ); gtk_table_attach_defaults( GTK_TABLE( table ), entry_width, 1, 2, 0, 1 ); gtk_widget_show( label ); gtk_widget_show( entry_width ); /* tile height */ label = gtk_label_new( "height: " ); entry_height = gtk_entry_new(); sprintf( buffer, "%d", parameters.tile_height ); gtk_entry_set_text( GTK_ENTRY( entry_height ), buffer ); gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 1, 2 ); gtk_table_attach_defaults( GTK_TABLE( table ), entry_height, 1, 2, 1, 2 ); gtk_widget_show( label ); gtk_widget_show( entry_height ); /* slide length */ label = gtk_label_new( "slide: " ); entry_slide = gtk_entry_new(); sprintf( buffer, "%d", parameters.slide_length ); gtk_entry_set_text( GTK_ENTRY( entry_slide ), buffer ); gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 2, 3 ); gtk_table_attach_defaults( GTK_TABLE( table ), entry_slide, 1, 2, 2, 3 ); gtk_widget_show( label ); gtk_widget_show( entry_slide ); } { /* radio buttons */ GtkWidget *frame; GtkWidget *vbox; GSList *group; frame = gtk_frame_new( "Background" ); gtk_container_border_width( GTK_CONTAINER( frame ), 0 ); gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_ETCHED_IN ); gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), frame, TRUE, TRUE, 0 ); gtk_widget_show( frame ); vbox = gtk_vbox_new( FALSE, 0 ); gtk_container_border_width( GTK_CONTAINER( vbox ), 0 ); gtk_container_add( GTK_CONTAINER( frame ), vbox ); gtk_widget_show( vbox ); group = NULL; if( image_has_alpha ){ /* transparent */ button_transparent = gtk_radio_button_new_with_label( NULL, "Transparent" ); gtk_box_pack_start( GTK_BOX( vbox ), button_transparent, TRUE, TRUE, 0 ); if( parameters.bg_type == BG_TYPE_TRANSPARENT ) gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_transparent ), TRUE ); gtk_widget_show( button_transparent ); group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_transparent ) ); } /* black */ button_black = gtk_radio_button_new_with_label( group, "Black" ); gtk_box_pack_start( GTK_BOX( vbox ), button_black, TRUE, TRUE, 0 ); if( parameters.bg_type == BG_TYPE_BLACK ) gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_black ), TRUE ); gtk_widget_show( button_black ); group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_black ) ); /* white */ button_white = gtk_radio_button_new_with_label( group, "White" ); gtk_box_pack_start( GTK_BOX( vbox ), button_white, TRUE, TRUE, 0 ); if( parameters.bg_type == BG_TYPE_WHITE ) gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_white ), TRUE ); gtk_widget_show( button_white ); } gtk_widget_show( window ); gtk_main(); return dialog_status; } /******************************************************************************/