#include <libgimp/gimp.h>
#include <gegl.h>
#include <gegl-buffer.h>
#include <math.h> //for ceil and sin
#include <stdio.h>
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
static int draw_dimetric_projection_lines_7_42(GimpDrawable* drawable);
GimpPlugInInfo PLUG_IN_INFO =
{
NULL,
NULL,
query,
run
};
MAIN()
static void query (void)
{
static GimpParamDef args[] =
{
{
GIMP_PDB_INT32,
"run-mode",
"Run mode"
},
{
GIMP_PDB_IMAGE,
"image",
"Input image"
},
{
GIMP_PDB_DRAWABLE,
"drawable",
"Input drawable"
}
};
gimp_install_procedure (
"perspective_lines",
"perspective_lines V1.1",
"draws lines for isometric perspective",
"David Suliga",
"Copyright David Suliga",
"2021",
"_perspective_lines",
"RGB*, GRAY*",
GIMP_PLUGIN,
G_N_ELEMENTS (args), 0,
args, NULL);
gimp_plugin_menu_register ("perspective_lines",
"<Image>/Filters/Misc");
}
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
static GimpParam values[1];
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpRunMode run_mode;
GimpDrawable *drawable;
gint32 drawable_id;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get(param[2].data.d_drawable);
//INIT_I18N (); ???
gegl_init (NULL, NULL);
babl_init();
drawable_id = param[2].data.d_drawable;
if (run_mode != GIMP_RUN_NONINTERACTIVE)
{
if (draw_dimetric_projection_lines_7_42(drawable) == FALSE)
{
status = GIMP_PDB_EXECUTION_ERROR;
values[0].data.d_status = status;
}
}
// gimp_displays_flush ();
// gimp_drawable_detach (drawable);
return;
}
/************************************************************************************************************************
* draw_dimetric_projection_lines_7_42
*
*************************************************************************************************************************
This function draws raster of horizontal lines with an angel of 7 degrees and
vertical lines of 42 degrees.
Problems:
Either the pixels are not set or not given back to the core correctly (see
Main Problem below).
Further Problems:
How can I add an alpha-channel ?
How can I draw the raster into a new layer ?
*/
static int draw_dimetric_projection_lines_7_42(GimpDrawable* drawable)
{
printf("perspective_lines: start draw_dimetric_projection_lines_7_42 \n" );
gint i, j, k, channels;
gint x1, y1, x2, y2;
// GimpPixelRgn rgn_in, rgn_out;
GeglBuffer* rgn_in;
GeglBuffer* rgn_out;
guchar output[4];
gint32 drawable_id = drawable->drawable_id;
// GeglBuffer *drawable_buffer;
//rgn_in = gimp_drawable_get_buffer(drawable_id);
const Babl *format;
format = babl_format ("R'G'B'A u8");
gint32 image_id = gimp_item_get_image(drawable_id);
/* Gets upper left and lower right coordinates,
* and layers number in the image */
gimp_drawable_mask_bounds (drawable_id,
&x1, &y1,
&x2, &y2);
channels = gimp_drawable_bpp(drawable_id);
if (gimp_drawable_has_alpha (drawable_id)==FALSE)
{
printf("perspective_lines: No Alpha_Channel \n");
g_message("The plugin perspective lines needs an alpha channel
in it's source-image\n");
return FALSE;
/*How can I create an alpha-channel ?
gimp_image_insert_channel () needs a parent id. Where can I get
one?
Where is the term "channel" defined ? Is this the right command
?*/
//this doesn'T work:
/* GimpRGB channel_color;
channel_color.a = 0;channel_color.g = 0;channel_color.b =
0;channel_color.a = 0;
gint32 channel_id = gimp_channel_new (
image_id,"alpha-channel",x2,y2,0,&channel_color);
gint32 parent_id = gimp_item_get_parent(channel_id);
if(gimp_image_insert_channel(image_id,channel_id,parent_id,-1)==
FALSE)
{
g_message("The plugin perspective lines needs an alpha
channel in it's source-image\n");
return FALSE;
}
*/
}
// Okay this are the newer commands than gimp_drawable_mask_bounds
// x2 = gimp_drawable_width (drawable_id);
// y2 = gimp_drawable_height (drawable_id);
GeglRectangle pixel_to_set;//This rectangle describes a singel
pixel and is used in the gegl_buffer_set command later.
rgn_in = gimp_drawable_get_buffer(drawable_id);//The buffer with
source image and its' tiles. Which is the image in the active layer before
//we called the
plugin
rgn_out = gimp_drawable_get_shadow_buffer(drawable_id);//The buffer
with destination image and its' tiles.
//The image
in that we do our modifications and
//which is
plug in's result if merged with the source image
// Are this definitions correct ? Where is the term shadow_buffer
defined ?
const int bitmap_size = x2 * y2;
guchar pixel [bitmap_size] [4]; // array for the image data. Used
as source in the gegl_buffer_set- command later.
int new_line_distance =ceil(y2/40);
int new_column_distance = ceil(x2/40);
int xp_out = 0; //x-position for the pixel which is set by the
gegl_buffer_set- command later.
int yp_out = 0; //y-position for the pixel which is set by the
gegl_buffer_set- command later.
int xp_multi_yp = 0;//The pixel's position in the array pixel[]
int hypo_length = 0;
double aspect_ratio = 2;
printf("perspective_lines: start creating a layer\n");
/*----------------------------------------------------------------------------------------------------------
- Trying to create a new layer
-
------------------------------------------------------------------------------------------------------------*/
/*Unsolved Problem:
I want create a new layer and storing the plug in's result in
it's image/drawable(?).
I only found out how to create a new layer but how can I get
access to it's image/drawable ?*/
if(gimp_image_is_valid(image_id) == FALSE )
{
printf("perspective_lines: Image is invalid \n");
return FALSE;
}
/*
if(gimp_drawable_set_image(drawable->drawable_id,image_id)==FALSE)
{
printf("perspective_lines: Can't set image to drawable.
Image_ID: %i \n",image_id);
return ;
}
*/
/* gint32 new_layer =
gimp_layer_new(image_id,"lines",x2,y2,GIMP_RGBA_IMAGE,0,GIMP_NORMAL_MODE);
// gint32 active_layer = gimp_image_get_active_layer(image_id);
// gint32 new_layer = gimp_layer_new_from_drawable
(drawable_id,image_id);
if(gimp_image_insert_layer(image_id,new_layer,0,-1)==FALSE)
{
printf("perspective_lines: Can't create layer. \n");
return ;
}
if(gimp_image_set_active_layer(image_id,new_layer)== FALSE)
{
printf("perspective_lines: Can't set layer active. \n");
return ;
}
//
--------------------------------------------------------------------------------------------------------------
*/
//We want a transparent background.
gimp_drawable_fill (drawable_id,GIMP_TRANSPARENT_FILL);
// Print informations for debugging
printf("perspective_lines: rgn_in width: %i rgn_in height: %i
\n",gegl_buffer_get_width(rgn_in),gegl_buffer_get_height(rgn_in));
printf("perspective_lines: rgn_out width: %i rgn_out height: %i
\n",gegl_buffer_get_width(rgn_out),gegl_buffer_get_height(rgn_out));
printf("perspective_lines: x2: %i y2: %i drawable_bpp: %i
\n",x2,y2,channels);
// printf("perspective_lines: rgn_in bpp: %i rgn_out bpp: %i
\n",gimp_buffer_get_bytes(rgn_in), gimp_buffer_get_bytes(rgn_out));
// return ;
printf("perspective_lines: start plotting\n");
/*-------------------------------------------------------------------------------------------------------------
- Drawing the
horizon lines with a 7 degree angle -
-------------------------------------------------------------------------------------------------------------*/
for(j = y1; j < y2; j = j+new_line_distance)//go through
y-positions
{
for (i = x1; i < x2; ++i)//go through x-positions
{
printf("perspective_lines: start calculating
rectangle\n");
xp_out = round(i * aspect_ratio);
hypo_length = round(i / sin(83));
yp_out = j + round(hypo_length * cos(83) );
printf("perspective_lines: stop calculating rectangle\n");
xp_multi_yp = xp_out * yp_out;
if((xp_multi_yp < bitmap_size)&&(xp_multi_yp >
-1))//check if access to pixel[] array is in size
{
if((xp_out < x2-1)&&(yp_out < y2-1))// check if
xp_out and yp_out are in limits.
{
if((xp_out > 0)&&(yp_out > 0))
{
printf("perspective_lines: setting
xp_multi_yp %i\n",xp_multi_yp);
//sets the pixel black and intransparent.
//pixel[xp_multi_yp][0] =
R,pixel[xp_multi_yp][1] = G,pixel[xp_multi_yp][2] == B,pixel[xp_multi_yp][3]=
Alpha
pixel[xp_multi_yp][0] =
0,pixel[xp_multi_yp][1] = 0,pixel[xp_multi_yp][2] = 0,pixel[xp_multi_yp][3] =
255;
printf("perspective_lines: setting x %i and y
%i pos\n",i,j);
//defining a rectangular for a single pixel:
pixel_to_set.x = xp_out; pixel_to_set.y =
yp_out; pixel_to_set.width = 1; pixel_to_set.height = 1;
//setting the pixel:
//
gegl_buffer_set(rgn_out,&pixel_to_set,1,format,pixel[xp_multi_yp],GEGL_AUTO_ROWSTRIDE);//setting
the pixel
gegl_buffer_set(rgn_out,&pixel_to_set,1,format,pixel[xp_multi_yp],GEGL_AUTO_ROWSTRIDE);
}
}
}
}// end loop for x-positions
if (j % 10 == 0)
{
gimp_progress_update ((gdouble) (j - y1) / (gdouble) (y2 -
y1));
}
}
printf("perspective_lines: start with y columns\n");
/*------------------------------------------------------------------------------------------------------------------------
* - Drawing the
vertical lines with a 42 degree angle -
--------------------------------------------------------------------------------------------------------------------------*/
for(i = x1; i < x2;i = i + new_column_distance)//go through
x-positions
{
for (j = y1; j < y2; j = ++j)//go through y-positions
{
printf("perspective_lines: start calculating
rectangle\n");
yp_out = j;
hypo_length = round(j / cos(48));
xp_out = i - round(hypo_length * sin(48)) ;
printf("perspective_lines: stop calculating rectangle\n");
xp_multi_yp = xp_out * yp_out;
if((xp_multi_yp < bitmap_size)&&(xp_multi_yp > -1))
{
if((xp_out < x2-1)&&(yp_out < y2-1))
{
if((xp_out > 0)&&(yp_out > 0))
{
printf("perspective_lines: setting
xp_multi_yp %i\n",xp_multi_yp);
//sets the pixel black and intransparent.
//pixel[xp_multi_yp][0] =
R,pixel[xp_multi_yp][1] = G,pixel[xp_multi_yp][2] = B,pixel[xp_multi_yp][3]=
Alpha
pixel[xp_multi_yp][0] =
0,pixel[xp_multi_yp][1] = 0,pixel[xp_multi_yp][2] = 0,pixel[xp_multi_yp][3] =
255;
printf("perspective_lines: setting x %i and y
%i pos\n",i,j);
pixel_to_set.x = xp_out; pixel_to_set.y =
yp_out; pixel_to_set.width = 1; pixel_to_set.height = 1;
//gegl_buffer_set(rgn_out,&pixel_to_set,1,format,pixel[xp_multi_yp],GEGL_AUTO_ROWSTRIDE);
gegl_buffer_set(rgn_out,&pixel_to_set,1,format,pixel[xp_multi_yp],GEGL_AUTO_ROWSTRIDE);
}
}
}
}
//printf("perspective_lines: new_line_distance is: %i
\n",new_line_distance);
if (i % 10 == 0)
{
gimp_progress_update ((gdouble) (j - y1) / (gdouble) (y2 -
y1));
}
}
/* Update the modified region */
//gimp_drawable_flush (drawable);
// gegl_buffer_flush(rgn_out);
//Writing the shadow buffer to disc for debugging reason's
GeglRectangle buffer_save_rect;
buffer_save_rect.x = x1;buffer_save_rect.y = y1;
buffer_save_rect.width = x2; buffer_save_rect.height = y2;
printf("perspective_lines: Try to save buffer\n");
gegl_buffer_save(rgn_out,"/home/david/rgn_out_buffer.txt",&buffer_save_rect);
/*******************************************************************************************************
* The main problem !!!!
*
******************************************************************************************************/
// It seems that gimp_drawable_merge_shadow command doesn't do
it's job without error-message !
// if I investigate the data which I saved with gegl_buffer_save
command above than it seems that
// the pixel data is stored correctly into the buffer rgn_out.
// But it is not updated to the core !
/* The facts:
* rgn_out contains the wished result.
* After deployment of the plugin: The source image becomes
completly transparent. There are no intransparent pixel lines
* If I export it as a bmp file,the bmp file is after the header
completly empty !!!
*
*/
printf("perspective_lines: pixel count rgn_out: %i
\n",gegl_buffer_get_pixel_count(rgn_out));
g_object_unref(rgn_in);
g_object_unref(rgn_out);
if(gimp_drawable_merge_shadow (drawable_id, TRUE)== FALSE)
{
printf("perspective_lines: gimp_drawable_merge_shadow failed
\n ");
return FALSE;
}
if(gimp_drawable_update (drawable_id,
x1, y1,
x2 - x1, y2 - y1)==FALSE)
{
printf("perspective_lines: gimp_drawable_update failed \n
");
return FALSE;
}
//gimp_drawable_detach()???
gimp_displays_flush ();
gimp_drawable_detach (drawable);
printf("perspective_lines: perpespective lines finished\n");
return TRUE;
}
_______________________________________________
gimp-developer-list mailing list
List address: [email protected]
List membership: https://mail.gnome.org/mailman/listinfo/gimp-developer-list
List archives: https://mail.gnome.org/archives/gimp-developer-list