#include #include #include #include //for ceil and sin #include 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", "/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; }