/********************************************************************** * Stegano Plug-In (Version 1.00a) * Daniel Cotting (cotting@multimania.com) ********************************************************************** * Official homepages: http://www.multimania.com/cotting * http://cotting.citeweb.net ********************************************************************** */ /* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * 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 #include #include #include "libgimp/gimp.h" #include "gtk/gtk.h" #include "logo.h" #define ENTRY_WIDTH 200 typedef struct { gint mode; char filename[128]; gint warningmessage; } steganoValues; typedef struct { gint run; } steganoInterface; /* Declare local functions. */ static void query(void); static void run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals); static void drawstegano(GimpDrawable *drawable); static void readstegano(GimpDrawable *drawable); static gint stegano_dialog(void); static gint stegano_save_dialog(void); static gint stegano_warning_dialog(void); static gint message_dialog(char *, char *, char *); GtkWidget * stegano_logo_dialog(void); GtkWidget *maindlg; GtkWidget *globalentry; GtkWidget *saveglobalentry; GtkWidget *logodlg; GtkWidget *warningdlg; GtkWidget *messagedlg; GtkWidget *savedlg; GtkTooltips *tips; GdkColor tips_fg,tips_bg; gchar filename[128]; gint saverun; static GimpParam values[1]; GimpDrawable *drawable; GimpRunModeType run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; static steganoValues wvals = { 1,"",1 }; /* wvals */ static steganoInterface bint = { FALSE /* run */ }; MAIN() static void query(void) { static GimpParamDef args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_IMAGE, "image", "Input image (unused)" }, { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }, { GIMP_PDB_INT8, "mode", "FALSE: Hide file in image; TRUE: Get hidden file" }, { GIMP_PDB_STRING, "filename[128]", "Name of the file to hide in an image (only of importance if mode=FALSE" }, }; static GimpParamDef *return_vals = NULL; static int nargs = sizeof(args)/ sizeof(args[0]); static int nreturn_vals = 0; gimp_install_procedure("plug_in_stegano", "Hides a file in an image.", "", "Daniel Cotting (cotting@multimania.com, http://www.multimania.com/cotting)", "Daniel Cotting (cotting@multimania.com, http://www.multimania.com/cotting)", "December, 1998", "/Filters/Image/Stegano", "RGB*, GRAY*, INDEXED*", GIMP_PLUGIN, nargs, nreturn_vals, args, return_vals); } static void run(char *name, int nparams, GimpParam *param, int *nreturn_vals, GimpParam **return_vals) { gchar **argv; gint argc; run_mode = param[0].data.d_int32; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; *nreturn_vals = 1; *return_vals = values; drawable = gimp_drawable_get(param[2].data.d_drawable); switch(run_mode) { case GIMP_RUN_INTERACTIVE: /* Possibly retrieve data */ gimp_get_data("plug_in_stegano", &wvals); /* Get information from the dialog */ argc = 1; argv = g_new(gchar *, 1); argv[0] = g_strdup("apply_stegano"); gtk_init(&argc, &argv); gtk_rc_parse(gimp_gtkrc()); stegano_dialog(); return; case GIMP_RUN_NONINTERACTIVE: /* Make sure all the arguments are present */ if (nparams != 5) status = GIMP_PDB_CALLING_ERROR; if (status == GIMP_PDB_SUCCESS) wvals.mode = param[3].data.d_int8; strncpy (wvals.filename,param[4].data.d_string, 128); wvals.filename[127]='\0'; argc = 1; argv = g_new(gchar *, 1); argv[0] = g_strdup("apply_stegano"); gtk_init(&argc, &argv); gtk_rc_parse(gimp_gtkrc()); tips = gtk_tooltips_new (); gtk_tooltips_set_delay(tips, 2500); break; case GIMP_RUN_WITH_LAST_VALS: /* Possibly retrieve data */ argc = 1; argv = g_new(gchar *, 1); argv[0] = g_strdup("apply_stegano"); gtk_init(&argc, &argv); gtk_rc_parse(gimp_gtkrc()); tips = gtk_tooltips_new (); gtk_tooltips_set_delay(tips, 2500); gimp_get_data("plug_in_stegano", &wvals); break; default: break; } if (status == GIMP_PDB_SUCCESS) { if (!wvals.mode) { gimp_tile_cache_ntiles(2 *(drawable->width / gimp_tile_width() + 1)); /* gimp_progress_init("Stegano plug-in is working. Please wait..."); */ drawstegano(drawable); if(run_mode != GIMP_RUN_NONINTERACTIVE) gimp_displays_flush(); } else { readstegano(drawable); } } if(run_mode == GIMP_RUN_INTERACTIVE) gimp_set_data("plug_in_stegano", &wvals, sizeof(steganoValues)); values[0].data.d_status = status; gimp_drawable_detach(drawable); } static void set_tooltip (GtkTooltips *tooltips, GtkWidget *widget, const char *desc) { if (desc && desc[0]) gtk_tooltips_set_tip (tooltips, widget, (char *) desc, NULL); } static void drawstegano(GimpDrawable *drawable) { FILE *In; GimpPixelRgn srcPR, destPR; gint width, height; gint bytes; gint row; gint x1, y1, x2, y2, ix, iy; guchar *src, *dest; gint i, col; gint value; long count=1,smallcount=0; gfloat regionwidth, regionheight, dx, dy; gfloat a, b, x, y; glong pixelpos, pos; guchar bgr_red, bgr_blue, bgr_green; char actualchar[1]; gint made_it_once=FALSE; glong backup; gchar * point; typedef struct { gchar identity[4]; gchar filename[128]; gdouble len; } _header; _header header; point=(char*) &header; for (i=0;iid, &x1, &y1, &x2, &y2); regionwidth = x2-x1; a = regionwidth/2; regionheight = y2-y1; b = regionheight/2; width = drawable->width; height = drawable->height; bytes = drawable->bpp; gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE); src = g_malloc((x2-x1)*(y2-y1)*bytes); dest = g_malloc((x2-x1)*(y2-y1)*bytes); gimp_pixel_rgn_get_rect(&srcPR, src, x1, y1, regionwidth, regionheight); backup = ftell(In); fseek(In, 0, SEEK_END); header.len = ftell(In)-backup; fseek(In, backup, SEEK_SET); point = (char *) &header; actualchar[0]=point[0]; for(col = 0; col < regionwidth; col++) { dx = (gfloat)col - a; for(row = 0; row < regionheight; row++) { pixelpos = (col+row*regionwidth)*bytes; dy = -((gfloat)row - b); x = dx+a; y = -dy+b; ix=(int)x; iy=(int)y; pos = ((gint)(iy)*regionwidth + (gint)(ix)) * bytes; for(i = 0; i < bytes; i++) { smallcount++; if (smallcount==9) { if (count