static gboolean webx_pipeline_check_update (WebxPipeline *pipeline) { gint *layers; gint num_layers; gint i; g_return_val_if_fail (WEBX_IS_PIPELINE (pipeline), FALSE); if (pipeline->rgb_image != -1) { gimp_image_delete (pipeline->rgb_image); pipeline->rgb_image = -1; } if (pipeline->indexed_image != -1) { gimp_image_delete (pipeline->indexed_image); pipeline->indexed_image = -1; } if (pipeline->background) { g_object_unref (pipeline->background); pipeline->background = NULL; } pipeline->rgb_image = gimp_image_duplicate (pipeline->user_image); gimp_image_undo_disable (pipeline->rgb_image); pipeline->rgb_layer = gimp_image_merge_visible_layers (pipeline->rgb_image, GIMP_CLIP_TO_IMAGE); /* make sure there is only one layer, where all visible layers were merged */ layers = gimp_image_get_layers (pipeline->rgb_image, &num_layers); for (i = 0; i < num_layers; i++) { if (layers[i] != pipeline->rgb_layer) gimp_image_remove_layer (pipeline->rgb_image, layers[i]); } g_free (layers); /* we don't want layer to be smaller than image */ gimp_layer_resize_to_image_size (pipeline->rgb_layer); gimp_image_scale (pipeline->rgb_image, pipeline->resize_width, pipeline->resize_height); webx_pipeline_create_background (pipeline); pipeline->crop_offsx *= pipeline->crop_scale_x; pipeline->crop_offsy *= pipeline->crop_scale_y; pipeline->crop_width *= pipeline->crop_scale_x; pipeline->crop_height *= pipeline->crop_scale_y; pipeline->crop_scale_x = 1.0; pipeline->crop_scale_y = 1.0; webx_pipeline_crop_clip (pipeline); if (pipeline->crop_width != pipeline->resize_width || pipeline->crop_height != pipeline->resize_height ) { gimp_image_crop (pipeline->rgb_image, pipeline->crop_width, pipeline->crop_height, pipeline->crop_offsx, pipeline->crop_offsy); } if (gimp_drawable_is_indexed (pipeline->rgb_layer)) { pipeline->indexed_image = gimp_image_duplicate (pipeline->rgb_image); gimp_image_undo_disable (pipeline->indexed_image); pipeline->indexed_layer = gimp_image_merge_visible_layers (pipeline->indexed_image, GIMP_CLIP_TO_IMAGE); } else { pipeline->indexed_image = -1; pipeline->indexed_layer = -1; } if ( ! gimp_drawable_is_rgb (pipeline->rgb_layer)) gimp_image_convert_rgb (pipeline->rgb_image); return TRUE; }
/* ------------------------------------------------------- * gap_image_set_selection_from_selection_or_drawable * ------------------------------------------------------- * create a selection in the specified image_id. * The selection is a scaled copy of the selection in another image, * referred by ref_drawable_id, or a Grayscale copy of the specified ref_drawable_id * (in case the referred image has no selection or the flag force_from_drawable is TRUE) * * - operates on a duplicate of the image referred by ref_drawable_id. * - this duplicate is scaled to same size as specified image_id * * return TRUE in case the selection was successfully created . */ gboolean gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_drawable_id , gboolean force_from_drawable) { gint32 l_aux_channel_id; gint32 ref_image_id; gint32 work_drawable_id; /* the duplicate of the layer that is used as selction mask */ gint32 dup_image_id; gboolean has_selection; gboolean non_empty; gint x1, y1, x2, y2; if ((image_id < 0) || (ref_drawable_id < 0)) { return (FALSE); } ref_image_id = gimp_item_get_image(ref_drawable_id); if (ref_image_id < 0) { printf("ref_drawable_id does not refer to a valid image layer_id:%d\n", (int)ref_drawable_id); return (FALSE); } dup_image_id = gimp_image_duplicate(ref_image_id); if (dup_image_id < 0) { printf("duplicating of image failed, referred souce image_id:%d\n", (int)ref_image_id); return (FALSE); } /* clear undo stack */ if (gimp_image_undo_is_enabled(dup_image_id)) { gimp_image_undo_disable(dup_image_id); } if ((gimp_image_width(image_id) != gimp_image_width(dup_image_id)) || (gimp_image_height(image_id) != gimp_image_height(dup_image_id))) { if(gap_debug) { printf("scaling tmp image_id: %d\n", (int)dup_image_id); } gimp_image_scale(dup_image_id, gimp_image_width(image_id), gimp_image_height(image_id)); } has_selection = gimp_selection_bounds(ref_image_id, &non_empty, &x1, &y1, &x2, &y2); if ((has_selection) && (non_empty) && (force_from_drawable != TRUE)) { /* use scaled copy of the already exisating selection in the referred image */ work_drawable_id = gimp_image_get_selection(dup_image_id); } else { gint32 active_layer_stackposition; /* create selection as gray copy of the alt_selection layer */ active_layer_stackposition = gap_layer_get_stackposition(ref_image_id, ref_drawable_id); if(gimp_image_base_type(dup_image_id) != GIMP_GRAY) { if(gap_debug) { printf("convert to GRAYSCALE tmp image_id: %d\n", (int)dup_image_id); } gimp_image_convert_grayscale(dup_image_id); } work_drawable_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition); gimp_layer_resize_to_image_size (work_drawable_id); } gimp_selection_all(image_id); //l_sel_channel_id = gimp_image_get_selection(image_id); l_aux_channel_id = gimp_selection_save(image_id); /* copy the work drawable (layer or channel) into the selection channel * the work layer is a grayscale copy GRAY or GRAYA of the alt_selection layer * that is already scaled and resized to fit the size of the target image * the work channel is the scaled selection of the image refred by ref_drawable_id * * copying is done into an auxiliary channel from where we regulary load the selection. * this is done because subseqent queries of the selection boudaries will deliver * full channel size rectangle after a direct copy into the selection. */ gap_layer_copy_picked_channel (l_aux_channel_id /* dst_drawable_id*/ , 0 /* dst_channel_pick */ , work_drawable_id /* src_drawable_id */ , 0 /* src_channel_pick */ , FALSE /* gboolean shadow */ ); gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_aux_channel_id); gimp_image_remove_channel(image_id, l_aux_channel_id); gap_image_delete_immediate(dup_image_id); return (TRUE); } /* end gap_image_set_selection_from_selection_or_drawable */
/* Compose a roll film image from several images */ static gint32 film (void) { gint width, height; guchar *hole; gint film_height, film_width; gint picture_width, picture_height; gint picture_space, picture_x0, picture_y0; gint hole_offset, hole_width, hole_height, hole_space, hole_x; gint number_height, num_images, num_pictures; gint j, k, picture_count; gdouble f; gint num_layers; gint32 *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst; gint image_ID_tmp; gint32 *layers; GimpDrawable *drawable_dst; GimpPixelRgn pixel_rgn_dst; gint new_layer; gint floating_sel; /* initialize */ layers = NULL; num_images = filmvals.num_images; image_ID_src = filmvals.image; if (num_images <= 0) return (-1); gimp_context_push (); gimp_context_set_foreground (&filmvals.number_color); gimp_context_set_background (&filmvals.film_color); if (filmvals.keep_height) /* Search maximum picture height */ { picture_height = 0; for (j = 0; j < num_images; j++) { height = gimp_image_height (image_ID_src[j]); if (height > picture_height) picture_height = height; } film_height = (int)(picture_height / filmvals.picture_height + 0.5); filmvals.film_height = film_height; } else { film_height = filmvals.film_height; picture_height = (int)(film_height * filmvals.picture_height + 0.5); } picture_space = (int)(film_height * filmvals.picture_space + 0.5); picture_y0 = (film_height - picture_height)/2; number_height = film_height * filmvals.number_height; /* Calculate total film width */ film_width = 0; num_pictures = 0; for (j = 0; j < num_images; j++) { layers = gimp_image_get_layers (image_ID_src[j], &num_layers); /* Get scaled image size */ width = gimp_image_width (image_ID_src[j]); height = gimp_image_height (image_ID_src[j]); f = ((double)picture_height) / (double)height; picture_width = width * f; for (k = 0; k < num_layers; k++) { if (gimp_layer_is_floating_sel (layers[k])) continue; film_width += (picture_space/2); /* Leading space */ film_width += picture_width; /* Scaled image width */ film_width += (picture_space/2); /* Trailing space */ num_pictures++; } g_free (layers); } #ifdef FILM_DEBUG g_printerr ("film_height = %d, film_width = %d\n", film_height, film_width); g_printerr ("picture_height = %d, picture_space = %d, picture_y0 = %d\n", picture_height, picture_space, picture_y0); g_printerr ("Number of pictures = %d\n", num_pictures); #endif image_ID_dst = create_new_image (_("Untitled"), (guint) film_width, (guint) film_height, GIMP_RGB_IMAGE, &layer_ID_dst, &drawable_dst, &pixel_rgn_dst); /* Fill film background */ gimp_drawable_fill (layer_ID_dst, GIMP_FILL_BACKGROUND); /* Draw all the holes */ hole_offset = film_height * filmvals.hole_offset; hole_width = film_height * filmvals.hole_width; hole_height = film_height * filmvals.hole_height; hole_space = film_height * filmvals.hole_space; hole_x = hole_space / 2; #ifdef FILM_DEBUG g_printerr ("hole_x %d hole_offset %d hole_width %d hole_height %d hole_space %d\n", hole_x, hole_offset, hole_width, hole_height, hole_space ); #endif hole = create_hole_rgb (hole_width, hole_height); if (hole) { while (hole_x < film_width) { draw_hole_rgb (drawable_dst, hole_x, hole_offset, hole_width, hole_height, hole); draw_hole_rgb (drawable_dst, hole_x, film_height-hole_offset-hole_height, hole_width, hole_height, hole); hole_x += hole_width + hole_space; } g_free (hole); } gimp_drawable_detach (drawable_dst); /* Compose all images and layers */ picture_x0 = 0; picture_count = 0; for (j = 0; j < num_images; j++) { image_ID_tmp = gimp_image_duplicate (image_ID_src[j]); width = gimp_image_width (image_ID_tmp); height = gimp_image_height (image_ID_tmp); f = ((gdouble) picture_height) / (gdouble) height; picture_width = width * f; if (gimp_image_base_type (image_ID_tmp) != GIMP_RGB) gimp_image_convert_rgb (image_ID_tmp); gimp_image_scale (image_ID_tmp, picture_width, picture_height); layers = gimp_image_get_layers (image_ID_tmp, &num_layers); for (k = 0; k < num_layers; k++) { if (gimp_layer_is_floating_sel (layers[k])) continue; picture_x0 += picture_space / 2; layer_ID_src = layers[k]; gimp_layer_resize_to_image_size (layer_ID_src); new_layer = gimp_layer_new_from_drawable (layer_ID_src, image_ID_dst); gimp_image_insert_layer (image_ID_dst, new_layer, -1, -1); gimp_layer_set_offsets (new_layer, picture_x0, picture_y0); /* Draw picture numbers */ if ((number_height > 0) && (filmvals.number_pos[0] || filmvals.number_pos[1])) { if (filmvals.number_pos[0]) draw_number (layer_ID_dst, filmvals.number_start + picture_count, picture_x0 + picture_width/2, (hole_offset-number_height)/2, number_height); if (filmvals.number_pos[1]) draw_number (layer_ID_dst, filmvals.number_start + picture_count, picture_x0 + picture_width/2, film_height - (hole_offset + number_height)/2, number_height); } picture_x0 += picture_width + (picture_space/2); gimp_progress_update (((gdouble) (picture_count + 1)) / (gdouble) num_pictures); picture_count++; } g_free (layers); gimp_image_delete (image_ID_tmp); } gimp_progress_update (1.0); gimp_image_flatten (image_ID_dst); /* Drawing text/numbers leaves us with a floating selection. Stop it */ floating_sel = gimp_image_get_floating_sel (image_ID_dst); if (floating_sel != -1) gimp_floating_sel_anchor (floating_sel); gimp_context_pop (); return image_ID_dst; }
/* ------------------------------ * gap_pview_render_f_from_image * ------------------------------ * render preview widget from image. * IMPORTANT: the image is scaled to preview size * and the visible layers in the image are merged together ! * If the supplied image shall stay unchanged, * you may use gap_pview_render_f_from_image_duplicate * * hint: call gtk_widget_queue_draw(pv_ptr->da_widget); * after this procedure to make the changes appear on screen. */ void gap_pview_render_f_from_image (GapPView *pv_ptr , gint32 image_id , gint32 flip_request , gint32 flip_status ) { gint32 layer_id; guchar *frame_data; GimpPixelRgn pixel_rgn; GimpDrawable *drawable; if(image_id < 0) { if(gap_debug) { printf("gap_pview_render_f_from_image: have no image, cant render image_id:%d\n" ,(int)image_id ); } return; } p_free_desaturated_area_data(pv_ptr); if((gimp_image_width(image_id) != pv_ptr->pv_width) || ( gimp_image_height(image_id) != pv_ptr->pv_height)) { gimp_image_scale(image_id, pv_ptr->pv_width, pv_ptr->pv_height); } /* workaround: gimp_image_merge_visible_layers * needs at least 2 layers to work without complaining * therefore add 2 full transparent dummy layers */ { gint32 l_layer_id; GimpImageBaseType l_type; l_type = gimp_image_base_type(image_id); l_type = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */ l_layer_id = gimp_layer_new(image_id, "dummy_01" , 4, 4 , l_type , 0.0 /* Opacity full transparent */ , 0 /* NORMAL */ ); gimp_image_insert_layer(image_id, l_layer_id, 0, 0); l_layer_id = gimp_layer_new(image_id, "dummy_02" , 4, 4 , l_type , 0.0 /* Opacity full transparent */ , 0 /* NORMAL */ ); gimp_image_insert_layer(image_id, l_layer_id, 0, 0); gimp_layer_resize_to_image_size(l_layer_id); } layer_id = gimp_image_merge_visible_layers (image_id, GIMP_CLIP_TO_IMAGE); drawable = gimp_drawable_get (layer_id); frame_data = g_malloc(drawable->width * drawable->height * drawable->bpp); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0 , drawable->width, drawable->height , FALSE /* dirty */ , FALSE /* shadow */ ); gimp_pixel_rgn_get_rect (&pixel_rgn, frame_data , 0 , 0 , drawable->width , drawable->height); { gboolean frame_data_was_grabbed; frame_data_was_grabbed = gap_pview_render_f_from_buf (pv_ptr , frame_data , drawable->width , drawable->height , drawable->bpp , TRUE /* allow_grab_src_data */ , flip_request , flip_status ); if(!frame_data_was_grabbed) g_free(frame_data); gimp_drawable_detach (drawable); } } /* end gap_pview_render_f_from_image */