1997-11-25 06:05:25 +08:00
/* max_rgb.c -- This is a plug-in for the GIMP (1.0's API)
* Author : Shuji Narazaki < narazaki @ InetQ . or . jp >
2000-01-01 00:39:04 +08:00
* Time - stamp : < 2000 - 01 - 01 00 : 24 : 57 yasuhiro >
1997-11-25 06:05:25 +08:00
* Version : 0.35
*
* Copyright ( C ) 1997 Shuji Narazaki < narazaki @ InetQ . or . 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
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
*/
2000-01-01 00:39:04 +08:00
# include "config.h"
2000-01-07 18:39:33 +08:00
1997-11-25 06:05:25 +08:00
# include <math.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2000-01-07 18:39:33 +08:00
# include <gtk/gtk.h>
2000-01-11 23:48:00 +08:00
# include <libgimp/gimp.h>
# include <libgimp/gimpui.h>
2000-01-07 18:39:33 +08:00
2000-01-02 23:51:41 +08:00
# include "libgimp/stdplugins-intl.h"
1997-11-25 06:05:25 +08:00
/* Replace them with the right ones */
2000-01-18 01:02:26 +08:00
# define PLUG_IN_NAME "plug_in_max_rgb"
# define SHORT_NAME "max_rgb"
# define PROGRESS_UPDATE_NUM 100
1997-11-25 06:05:25 +08:00
static void query ( void ) ;
2000-01-11 23:48:00 +08:00
static void run ( gchar * name ,
gint nparams ,
GParam * param ,
gint * nreturn_vals ,
1997-11-25 06:05:25 +08:00
GParam * * return_vals ) ;
2000-01-18 01:02:26 +08:00
static GStatusType main_function ( gint32 drawable_id ) ;
static gint dialog ( void ) ;
static void ok_callback ( GtkWidget * widget ,
gpointer data ) ;
1997-11-25 06:05:25 +08:00
GPlugInInfo PLUG_IN_INFO =
{
2000-01-11 23:48:00 +08:00
NULL , /* init_proc */
2000-01-18 01:02:26 +08:00
NULL , /* quit_proc */
2000-01-11 23:48:00 +08:00
query , /* query_proc */
2000-01-18 01:02:26 +08:00
run , /* run_proc */
} ;
enum
{
MIN_CHANNELS = 0 ,
MAX_CHANNELS = 1
1997-11-25 06:05:25 +08:00
} ;
typedef struct
{
2000-01-11 23:48:00 +08:00
gint max_p ; /* gint, gdouble, and so on */
1997-11-25 06:05:25 +08:00
} ValueType ;
typedef struct
{
gint run ;
} Interface ;
2000-01-18 01:02:26 +08:00
static ValueType pvals =
{
MAX_CHANNELS
} ;
static Interface interface =
{
FALSE
} ;
1997-11-25 06:05:25 +08:00
1998-03-19 10:11:53 +08:00
MAIN ( )
1997-11-25 06:05:25 +08:00
static void
2000-01-11 23:48:00 +08:00
query ( void )
1997-11-25 06:05:25 +08:00
{
static GParamDef args [ ] =
{
{ PARAM_INT32 , " run_mode " , " Interactive, non-interactive " } ,
{ PARAM_IMAGE , " image " , " Input image (not used) " } ,
{ PARAM_DRAWABLE , " drawable " , " Input drawable " } ,
{ PARAM_INT32 , " max_p " , " 1 for maximizing, 0 for minimizing " }
} ;
static GParamDef * return_vals = NULL ;
static int nargs = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
static int nreturn_vals = 0 ;
2000-01-01 00:39:04 +08:00
INIT_I18N ( ) ;
1997-11-25 06:05:25 +08:00
gimp_install_procedure ( PLUG_IN_NAME ,
2000-01-01 00:39:04 +08:00
_ ( " Return an image in which each pixel holds only the channel that has the maximum value in three (red, green, blue) channels, and other channels are zero-cleared " ) ,
1997-11-25 06:05:25 +08:00
" the help is not yet written for this plug-in " ,
" Shuji Narazaki (narazaki@InetQ.or.jp) " ,
" Shuji Narazaki " ,
" 1997 " ,
2000-01-01 00:39:04 +08:00
N_ ( " <Image>/Filters/Colors/Max RGB... " ) ,
1997-11-25 06:05:25 +08:00
" RGB* " ,
PROC_PLUG_IN ,
nargs , nreturn_vals ,
args , return_vals ) ;
}
static void
run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals )
{
static GParam values [ 1 ] ;
GStatusType status = STATUS_EXECUTION_ERROR ;
GRunModeType run_mode ;
gint drawable_id ;
run_mode = param [ 0 ] . data . d_int32 ;
drawable_id = param [ 2 ] . data . d_int32 ;
* nreturn_vals = 1 ;
* return_vals = values ;
values [ 0 ] . type = PARAM_STATUS ;
values [ 0 ] . data . d_status = status ;
switch ( run_mode )
{
case RUN_INTERACTIVE :
2000-01-01 00:39:04 +08:00
INIT_I18N_UI ( ) ;
2000-01-18 01:02:26 +08:00
gimp_get_data ( PLUG_IN_NAME , & pvals ) ;
1997-11-25 06:05:25 +08:00
/* Since a channel might be selected, we must check wheter RGB or not. */
1999-10-25 04:49:09 +08:00
if ( ! gimp_drawable_is_rgb ( drawable_id ) )
1997-11-25 06:05:25 +08:00
{
2000-01-02 23:51:41 +08:00
gimp_message ( _ ( " RGB drawable is not selected. " ) ) ;
1997-11-25 06:05:25 +08:00
return ;
}
2000-01-18 01:02:26 +08:00
if ( ! dialog ( ) )
1997-11-25 06:05:25 +08:00
return ;
break ;
case RUN_NONINTERACTIVE :
2000-01-01 00:39:04 +08:00
INIT_I18N ( ) ;
2000-01-18 01:02:26 +08:00
/* You must copy the values of parameters to pvals or dialog variables. */
1997-11-25 06:05:25 +08:00
break ;
case RUN_WITH_LAST_VALS :
2000-01-01 00:39:04 +08:00
INIT_I18N ( ) ;
2000-01-18 01:02:26 +08:00
gimp_get_data ( PLUG_IN_NAME , & pvals ) ;
1997-11-25 06:05:25 +08:00
break ;
}
2000-01-18 01:02:26 +08:00
status = main_function ( drawable_id ) ;
1997-11-25 06:05:25 +08:00
if ( run_mode ! = RUN_NONINTERACTIVE )
gimp_displays_flush ( ) ;
if ( run_mode = = RUN_INTERACTIVE & & status = = STATUS_SUCCESS )
2000-01-18 01:02:26 +08:00
gimp_set_data ( PLUG_IN_NAME , & pvals , sizeof ( ValueType ) ) ;
1997-11-25 06:05:25 +08:00
values [ 0 ] . type = PARAM_STATUS ;
values [ 0 ] . data . d_status = status ;
}
static GStatusType
2000-01-18 01:02:26 +08:00
main_function ( gint32 drawable_id )
1997-11-25 06:05:25 +08:00
{
2000-01-18 01:02:26 +08:00
GDrawable * drawable ;
GPixelRgn src_rgn , dest_rgn ;
guchar * src , * dest ;
gpointer pr ;
gint x , y , x1 , x2 , y1 , y2 ;
gint gap , total , processed = 0 ;
gint init_value , flag ;
1997-11-25 06:05:25 +08:00
2000-01-18 01:02:26 +08:00
init_value = ( pvals . max_p > 0 ) ? 0 : 255 ;
flag = ( 0 < pvals . max_p ) ? 1 : - 1 ;
1997-11-25 06:05:25 +08:00
drawable = gimp_drawable_get ( drawable_id ) ;
gap = ( gimp_drawable_has_alpha ( drawable_id ) ) ? 1 : 0 ;
gimp_drawable_mask_bounds ( drawable_id , & x1 , & y1 , & x2 , & y2 ) ;
total = ( x2 - x1 ) * ( y2 - y1 ) ;
gimp_tile_cache_ntiles ( 2 * ( drawable - > width / gimp_tile_width ( ) + 1 ) ) ;
gimp_pixel_rgn_init ( & src_rgn , drawable , x1 , y1 , ( x2 - x1 ) , ( y2 - y1 ) , FALSE , FALSE ) ;
gimp_pixel_rgn_init ( & dest_rgn , drawable , x1 , y1 , ( x2 - x1 ) , ( y2 - y1 ) , TRUE , TRUE ) ;
pr = gimp_pixel_rgns_register ( 2 , & src_rgn , & dest_rgn ) ;
2000-01-01 00:39:04 +08:00
gimp_progress_init ( _ ( " max_rgb: scanning... " ) ) ;
1997-11-25 06:05:25 +08:00
for ( ; pr ! = NULL ; pr = gimp_pixel_rgns_process ( pr ) )
{
for ( y = 0 ; y < src_rgn . h ; y + + )
{
src = src_rgn . data + y * src_rgn . rowstride ;
dest = dest_rgn . data + y * dest_rgn . rowstride ;
for ( x = 0 ; x < src_rgn . w ; x + + )
{
gint ch , max_ch = 0 ;
guchar max , tmp_value ;
max = init_value ;
for ( ch = 0 ; ch < 3 ; ch + + )
if ( flag * max < = flag * ( tmp_value = ( * src + + ) ) )
1998-03-26 10:08:31 +08:00
{
1997-11-25 06:05:25 +08:00
if ( max = = tmp_value )
max_ch + = 1 < < ch ;
else
{
max_ch = 1 < < ch ; /* clear memories of old channels */
max = tmp_value ;
}
1998-03-26 10:08:31 +08:00
}
1997-11-25 06:05:25 +08:00
for ( ch = 0 ; ch < 3 ; ch + + )
* dest + + = ( guchar ) ( ( ( max_ch & ( 1 < < ch ) ) > 0 ) ? max : 0 ) ;
if ( gap ) * dest + + = * src + + ;
if ( ( + + processed % ( total / PROGRESS_UPDATE_NUM ) ) = = 0 )
gimp_progress_update ( ( double ) processed / ( double ) total ) ;
}
}
}
gimp_progress_update ( 1.0 ) ;
gimp_drawable_flush ( drawable ) ;
gimp_drawable_merge_shadow ( drawable - > id , TRUE ) ;
gimp_drawable_update ( drawable - > id , x1 , y1 , ( x2 - x1 ) , ( y2 - y1 ) ) ;
gimp_drawable_detach ( drawable ) ;
return STATUS_SUCCESS ;
}
/* dialog stuff */
2000-01-18 01:02:26 +08:00
static gint
dialog ( void )
1997-11-25 06:05:25 +08:00
{
2000-01-11 23:48:00 +08:00
GtkWidget * dlg ;
GtkWidget * frame ;
2000-01-18 01:02:26 +08:00
gchar * * argv ;
gint argc ;
2000-01-11 23:48:00 +08:00
argc = 1 ;
argv = g_new ( gchar * , 1 ) ;
1997-11-25 06:05:25 +08:00
argv [ 0 ] = g_strdup ( PLUG_IN_NAME ) ;
2000-01-11 23:48:00 +08:00
1997-11-25 06:05:25 +08:00
gtk_init ( & argc , & argv ) ;
gtk_rc_parse ( gimp_gtkrc ( ) ) ;
2000-01-07 18:39:33 +08:00
dlg = gimp_dialog_new ( _ ( " Max RGB " ) , " max_rgb " ,
gimp_plugin_help_func , " filters/max_rgb.html " ,
GTK_WIN_POS_MOUSE ,
FALSE , TRUE , FALSE ,
2000-01-18 01:02:26 +08:00
_ ( " OK " ) , ok_callback ,
2000-01-07 18:39:33 +08:00
NULL , NULL , NULL , TRUE , FALSE ,
_ ( " Cancel " ) , gtk_widget_destroy ,
NULL , 1 , NULL , FALSE , TRUE ,
NULL ) ;
gtk_signal_connect ( GTK_OBJECT ( dlg ) , " destroy " ,
2000-01-11 23:48:00 +08:00
GTK_SIGNAL_FUNC ( gtk_main_quit ) ,
2000-01-07 18:39:33 +08:00
NULL ) ;
2000-01-18 01:02:26 +08:00
frame = gimp_radio_group_new2 ( TRUE , _ ( " Parameter Settings " ) ,
gimp_radio_button_update ,
& pvals . max_p , ( gpointer ) pvals . max_p ,
_ ( " Hold the Maximal Channels " ) ,
( gpointer ) MAX_CHANNELS , NULL ,
_ ( " Hold the Minimal Channels " ) ,
( gpointer ) MIN_CHANNELS , NULL ,
NULL ) ;
2000-01-11 23:48:00 +08:00
gtk_container_set_border_width ( GTK_CONTAINER ( frame ) , 6 ) ;
gtk_container_add ( GTK_CONTAINER ( GTK_DIALOG ( dlg ) - > vbox ) , frame ) ;
gtk_widget_show ( frame ) ;
2000-01-07 18:39:33 +08:00
gtk_widget_show ( dlg ) ;
1997-11-25 06:05:25 +08:00
gtk_main ( ) ;
gdk_flush ( ) ;
2000-01-18 01:02:26 +08:00
return interface . run ;
1997-11-25 06:05:25 +08:00
}
static void
2000-01-18 01:02:26 +08:00
ok_callback ( GtkWidget * widget ,
gpointer data )
1997-11-25 06:05:25 +08:00
{
2000-01-18 01:02:26 +08:00
interface . run = TRUE ;
1997-11-25 06:05:25 +08:00
2000-01-18 01:02:26 +08:00
gtk_widget_destroy ( GTK_WIDGET ( data ) ) ;
1997-11-25 06:05:25 +08:00
}