void image_flatten_image_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; return_if_no_image (image, data); gimp_image_flatten (image, action_data_get_context (data)); gimp_image_flush (image); }
static void export_flatten (gint32 image_ID, gint32 *drawable_ID) { gint32 flattened; flattened = gimp_image_flatten (image_ID); if (flattened != -1) *drawable_ID = flattened; }
/* ============================================================================ * p_movtar_encode * The main "productive" routine * movtar encoding of anim frames, based on the buz_tools' encoding routines. * (flattens the images if nedded) * Optional you can provide audio, too * (wav_audiofile must be provided in that case) * * returns value >= 0 if all went ok * (or -1 on error) * ============================================================================ */ static int p_movtar_encode(t_anim_info *ainfo_ptr, long range_from, long range_to, char *vidname, gint32 dont_recode_frames, char *wavname, gint32 auto_videoparam, char *videonorm, gint32 jpeg_interlaced, char *text_author, char *text_software, char *text_device, char *text_input, char *text_contdescription, char *text_contclassification, gint32 jpeg_quality ) { gint32 l_tmp_image_id = -1; gint32 l_layer_id = -1; GDrawable *l_drawable; long l_cur_frame_nr; long l_step, l_begin, l_end; int l_width, l_height; gint l_nlayers; gint32 *l_layers_list; gdouble l_percentage, l_percentage_step; int l_rc; FILE *movtar, *inwav = NULL; gint32 JPEG_size, datasize; gint32 audio_x100; char *buffer; static struct tarinfotype frameinfo; // static struct tarinfotype frcopyinfo; static struct tarinfotype audioinfo; gint32 wavsize; /* Data size of the wav file */ long audio_margin = 8192; long audio_filled_100 = 0; gchar databuffer[300000]; gchar *name_examine; l_rc = 0; l_layer_id = -1; l_width = 0; l_height = 0; movtar_init(FALSE); tarblock_makedefault(&frameinfo, "tja.jpeg", 1024); tarblock_makedefault(&audioinfo, "tja.raw", 1024); /* create file */ if (movtar_debug) printf("Creating movtar file.\n"); movtar = movtar_create(vidname); if (movtar == NULL) { perror("Creation of movtar file failed."); exit(1); } l_percentage = 0.0; if(ainfo_ptr->run_mode == RUN_INTERACTIVE) gimp_progress_init("Encoding movtar..."); l_begin = range_from; l_end = range_to; /* special setup (makes it possible to code sequences backwards) */ if(range_from > range_to) { l_step = -1; /* operate in descending (reverse) order */ l_percentage_step = 1.0 / ((1.0 + range_from) - range_to); if(range_to < ainfo_ptr->first_frame_nr) l_begin = ainfo_ptr->first_frame_nr; if(range_from > ainfo_ptr->last_frame_nr) l_end = ainfo_ptr->last_frame_nr; } else { l_step = 1; /* operate in ascending order */ l_percentage_step = 1.0 / ((1.0 + range_to) - range_from); if(range_from < ainfo_ptr->first_frame_nr) l_begin = ainfo_ptr->first_frame_nr; if(range_to > ainfo_ptr->last_frame_nr) l_end = ainfo_ptr->last_frame_nr; } /* start with the first frame to encode */ l_cur_frame_nr = l_begin; while(l_rc >= 0) { /* build the frame name */ if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename); /* Use the gap functions to generate the frame filename */ ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename, l_cur_frame_nr, ainfo_ptr->extension); /* can't find the frame ? */ if(ainfo_ptr->new_filename == NULL) return -1; if(l_cur_frame_nr == l_begin) /* setup things first if this is the first frame */ { /* load current frame ... */ l_tmp_image_id = p_load_image(ainfo_ptr->new_filename); if(l_tmp_image_id < 0) return -1; /* to determine these parameters */ l_width = (int) gimp_image_width(l_tmp_image_id); l_height = (int) gimp_image_height(l_tmp_image_id); /* create the MOVTAR Info file, based on the information stored in the first JPEG */ inwav = p_make_movtar_info(movtar, wavname, l_width, l_height, auto_videoparam, videonorm, jpeg_interlaced, text_author, text_software, text_device, text_input, text_contdescription, text_contclassification, &audio_x100, &wavsize); /* destroy the tmp image, dont_recode doesn't need it */ if (dont_recode_frames) gimp_image_delete(l_tmp_image_id); } if (dont_recode_frames) { JPEG_size = p_get_filesize(ainfo_ptr->new_filename); buffer = p_load_file(ainfo_ptr->new_filename); if (buffer == NULL) { printf("gap_movtar: Failed opening encoded input frame %s.", ainfo_ptr->new_filename); return -1; } /* generate the file name for the frame to be stored */ /* store the compressed video frame */ /* A quick hack to replace the extension with raw */ strcpy(frameinfo.name, g_basename(ainfo_ptr->new_filename)); name_examine = frameinfo.name + strlen(frameinfo.name); while (frameinfo.name != name_examine && *name_examine != '.') { *name_examine = '\0'; name_examine--; } strcpy(name_examine, ".jpeg"); sprintf(frameinfo.size, "%o", JPEG_size); tarblock_create_checksum(&frameinfo); if (movtar_debug) printf("gap_movtar: Writing frame nr. %ld, size %d\n", l_cur_frame_nr, JPEG_size); if (movtar_write(movtar, buffer, JPEG_size, &frameinfo) != TRUE) { printf("gap_movtar: Failed in writing a frame."); return -1; } } else { if(l_cur_frame_nr != l_begin) /* frame has already been loaded if l_begin */ { /* load current frame */ l_tmp_image_id = p_load_image(ainfo_ptr->new_filename); if (l_tmp_image_id < 0) return -1; } /* Examine the layers of the picture */ l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers); if(l_layers_list != NULL) { l_layer_id = l_layers_list[0]; g_free (l_layers_list); } if(l_nlayers > 1 ) { if (movtar_debug) fprintf(stderr, "DEBUG: p_movtar_encode flatten tmp image'\n"); /* flatten current frame image (reduce to single layer) */ l_layer_id = gimp_image_flatten (l_tmp_image_id); } l_drawable = gimp_drawable_get (l_layer_id); if (movtar_debug) fprintf(stderr, "DEBUG: JPEG encoding frame %s\n", ainfo_ptr->new_filename); /* Compress the picture into a JPEG */ buffer = p_drawable_encode_jpeg(l_drawable, jpeg_interlaced, &JPEG_size, jpeg_quality, 0, FALSE, NULL, 0); if (movtar_debug) fprintf(stderr, "DEBUG: Ready with encoding, now saving %s\n", ainfo_ptr->new_filename); /* store the compressed video frame */ /* A quick hack to replace the extension with raw */ strcpy(frameinfo.name, g_basename(ainfo_ptr->new_filename)); name_examine = frameinfo.name + strlen(frameinfo.name); while (frameinfo.name != name_examine && *name_examine != '.') { *name_examine = '\0'; name_examine--; } strcpy(name_examine, ".jpeg"); sprintf(frameinfo.size, "%o", JPEG_size); tarblock_create_checksum(&frameinfo); if (movtar_debug) printf("gap_movtar: Writing frame nr. %ld, size %d\n", l_cur_frame_nr, JPEG_size); if (movtar_write(movtar, buffer, JPEG_size, &frameinfo) != TRUE) { printf("Failed in writing a frame."); return -1; } /* free the compressed JPEG data */ g_free(buffer); /* destroy the tmp image */ gimp_image_delete(l_tmp_image_id); } /* As long as there is a video frame, "fill" the fake audio buffer */ if (inwav) audio_filled_100 += audio_x100; /* Now "empty" the fake audio buffer, until it goes under the margin again */ while ((audio_filled_100 >= (audio_margin * 100)) && (wavsize > 0)) { if (wavsize >= audio_margin) { datasize = fread(databuffer, 1, audio_margin, inwav); if (datasize != audio_margin) { perror("Warning: Read from wav file failed. (non-critical)\n"); } wavsize -= audio_margin; } else { datasize = fread(databuffer, 1, wavsize, inwav); if (datasize != wavsize) { perror("Warning: Read from wav file failed. (non-critical)\n"); } wavsize = 0; } /* create a filename, with the sequence number and the timestamp info in brackets. Checksum the new tarheader. */ /* A quick hack to replace the extension with raw */ name_examine = frameinfo.name + strlen(frameinfo.name); while (frameinfo.name != name_examine && *name_examine != '.') { *name_examine = '\0'; name_examine--; } strcpy(name_examine, ".raw"); sprintf(frameinfo.size, "%o", datasize); tarblock_create_checksum(&frameinfo); if (movtar_debug) printf("Now saving audio frame %s\n", frameinfo.name); movtar_write(movtar, databuffer, datasize, &frameinfo); audio_filled_100 -= audio_margin * 100; } if(ainfo_ptr->run_mode == RUN_INTERACTIVE) { l_percentage += l_percentage_step; gimp_progress_update (l_percentage); } /* advance to next frame */ if((l_cur_frame_nr == l_end) || (l_rc < 0)) break; l_cur_frame_nr += l_step; } movtar_finish_close(movtar); return l_rc; }
/* 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; }
static gboolean webx_jpeg_target_save_image (WebxTarget *widget, WebxTargetInput *input, const gchar *file_name) { WebxJpegTarget *jpeg; GimpParam *return_vals; gint n_return_vals; gint32 image; gint32 layer; gint32 save_image; gint32 save_layer; gboolean save_res; jpeg = WEBX_JPEG_TARGET (widget); image = input->rgb_image; layer = input->rgb_layer; if (gimp_drawable_has_alpha (layer) || jpeg->strip_exif) { /* jpeg doesn't support alpha */ save_image = gimp_image_duplicate (image); gimp_image_undo_disable (image); save_layer = gimp_image_flatten (save_image); if (jpeg->strip_exif) { gimp_image_parasite_detach (save_image, "exif-data"); gimp_image_parasite_detach (save_image, "gimp-metadata"); } } else { save_image = image; save_layer = layer; } return_vals = gimp_run_procedure ("file-jpeg-save", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, save_image, GIMP_PDB_DRAWABLE, save_layer, GIMP_PDB_STRING, file_name, GIMP_PDB_STRING, file_name, GIMP_PDB_FLOAT, jpeg->quality, GIMP_PDB_FLOAT, jpeg->smoothing, GIMP_PDB_INT32, (gint)jpeg->optimize, GIMP_PDB_INT32, (gint)jpeg->progressive, GIMP_PDB_STRING, "", GIMP_PDB_INT32, jpeg->subsmp, GIMP_PDB_INT32, (gint)jpeg->baseline, GIMP_PDB_INT32, jpeg->restart, GIMP_PDB_INT32, jpeg->dct, GIMP_PDB_END); if (return_vals[0].data.d_int32 == GIMP_PDB_SUCCESS) save_res = TRUE; else save_res = FALSE; gimp_destroy_params (return_vals, n_return_vals); if (gimp_drawable_has_alpha (layer)) { gimp_image_delete (save_image); } return save_res; }