static void webx_pipeline_destroy (GtkObject *object) { WebxPipeline *pipeline; pipeline = WEBX_PIPELINE (object); 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; } if (GTK_OBJECT_CLASS (parent_class)->destroy) GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (pipeline)); }
/* ============================================================================ * gap_image_delete_immediate * delete image (with workaround to ensure that most of the * allocatd memory is freed) * ============================================================================ * The workaround disables undo and scales the image down to miniumum size * before calling the gimp_image_delete procedure. * this way memory resources for big layers will be freed up immediate. */ void gap_image_delete_immediate (gint32 image_id) { gboolean imageDeleteWorkaroundDefault = TRUE; if(gap_base_get_gimprc_gboolean_value("gap-image-delete-workaround" , imageDeleteWorkaroundDefault)) { if(gap_debug) { printf("gap_image_delete_immediate: SCALED down to 2x2 id = %d (workaround for gimp_image-delete problem)\n" , (int)image_id ); } gimp_image_undo_disable(image_id); //gimp_image_scale_full(image_id, 2, 2, 0 /*INTERPOLATION_NONE*/); gimp_context_push(); gimp_context_set_interpolation(0); gimp_image_scale(image_id, 2, 2); gimp_context_pop(); gimp_image_undo_enable(image_id); /* clear undo stack */ } gimp_image_delete(image_id); } /* end gap_image_delete_immediate */
static void do_texture_press () { gimp_image_delete (preview_image); preview_image = gimp_image_duplicate(image_ID); border (preview_image); preview_update (preview); }
static void preview_update_preview (GimpPreview *preview, GimpDrawable *drawable) { gint x1, y1; gint width, height; gint bpp; guchar *buffer; GimpPixelRgn src_rgn; GimpPixelRgn preview_rgn; gint32 image_id, src_image_id; gint32 preview_id; GimpDrawable *preview_drawable; bpp = gimp_drawable_bpp (drawable->drawable_id); gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); buffer = g_new (guchar, width * height * bpp); gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE); gimp_pixel_rgn_get_rect (&src_rgn, buffer, x1, y1, width, height); /* set up gimp drawable for rendering preview into */ src_image_id = gimp_drawable_get_image (drawable->drawable_id); image_id = gimp_image_new (width, height, gimp_image_base_type (src_image_id)); preview_id = gimp_layer_new (image_id, "preview", width, height, gimp_drawable_type (drawable->drawable_id), 100, GIMP_NORMAL_MODE); preview_drawable = gimp_drawable_get (preview_id); gimp_image_add_layer (image_id, preview_id, 0); gimp_layer_set_offsets (preview_id, 0, 0); gimp_pixel_rgn_init (&preview_rgn, preview_drawable, 0, 0, width, height, TRUE, TRUE); gimp_pixel_rgn_set_rect (&preview_rgn, buffer, 0, 0, width, height); gimp_drawable_flush (preview_drawable); gimp_drawable_merge_shadow (preview_id, TRUE); gimp_drawable_update (preview_id, 0, 0, width, height); dog (image_id, preview_drawable, dogvals.inner, dogvals.outer, FALSE); gimp_pixel_rgn_get_rect (&preview_rgn, buffer, 0, 0, width, height); gimp_preview_draw_buffer (preview, buffer, width * bpp); gimp_image_delete (image_id); g_free (buffer); }
void webx_indexed_target_free_image (WebxIndexedTarget *indexed, WebxTargetInput *input, gint image) { if (indexed->image == image) { gimp_image_delete (image); indexed->image = -1; } }
gint webx_indexed_target_get_image (WebxIndexedTarget *indexed, WebxTargetInput *input, gint *layer) { gint tmp_image; gint tmp_layer; gint *layers; gint num_layers; gchar *custom_palette; gint num_colors; gboolean converted; g_return_val_if_fail (WEBX_IS_INDEXED_TARGET (indexed), -1); if (indexed->palette_type == GIMP_REUSE_PALETTE) { *layer = input->indexed_layer; return input->indexed_image; } custom_palette = indexed->custom_palette; if (! custom_palette) custom_palette = ""; tmp_image = input->rgb_image; tmp_layer = input->rgb_layer; num_colors = indexed->num_colors; if (num_colors == 256 && gimp_drawable_has_alpha (tmp_layer)) num_colors = 255; tmp_image = gimp_image_duplicate (tmp_image); converted = gimp_image_convert_indexed (tmp_image, indexed->dither_type, indexed->palette_type, num_colors, indexed->alpha_dither, indexed->remove_unused, custom_palette); if (! converted) { gimp_image_delete (tmp_image); *layer = -1; return -1; } layers = gimp_image_get_layers (tmp_image, &num_layers); g_assert (num_layers == 1); tmp_layer = layers[0]; indexed->image = tmp_image; indexed->layer = tmp_layer; *layer= tmp_layer; return tmp_image; }
static int p_convert_frames(gint32 frame_from, gint32 frame_to, char *basename, char *ext, char *ext2) { GimpParam *return_vals; int nreturn_vals; gint32 l_tmp_image_id; char l_first_xa_frame[200]; /* load 1st one of those frames generated by xanim */ p_build_xanim_framename(l_first_xa_frame, frame_from, ext); l_tmp_image_id = p_load_image(l_first_xa_frame); /* convert the xanim frames (from ppm) to xcf fileformat * (the gap module for range convert is not linked to the frontends * main program, therefore i call the convert procedure by PDB-interface) */ return_vals = gimp_run_procedure ("plug_in_gap_range_convert2", &nreturn_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, /* runmode */ GIMP_PDB_IMAGE, l_tmp_image_id, GIMP_PDB_DRAWABLE, 0, /* (unused) */ GIMP_PDB_INT32, frame_from, GIMP_PDB_INT32, frame_to, GIMP_PDB_INT32, 0, /* dont flatten */ GIMP_PDB_INT32, 4444, /* dest type (keep type) */ GIMP_PDB_INT32, 256, /* colors (unused) */ GIMP_PDB_INT32, 0, /* no dither (unused) */ GIMP_PDB_STRING, ext2, /* extension for dest. filetype */ GIMP_PDB_STRING, basename, /* basename for dest. filetype */ GIMP_PDB_INT32, 0, /* (unused) */ GIMP_PDB_INT32, 0, /* (unused) */ GIMP_PDB_INT32, 0, /* (unused) */ GIMP_PDB_STRING, "none", /* (unused) palettename */ GIMP_PDB_END); /* destroy the tmp image */ gimp_image_delete(l_tmp_image_id); if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS) { return(-1); } return(0); /* OK */ }
static void webx_pipeline_create_background (WebxPipeline *pipeline) { g_return_if_fail (WEBX_IS_PIPELINE (pipeline)); if (gimp_drawable_is_rgb (pipeline->rgb_layer)) { pipeline->background = webx_drawable_to_pixbuf (pipeline->rgb_layer); } else { /* pipeline->rgb_image is still original image, which can be non rgb (as we create background early in pipeline). */ gint duplicate = gimp_image_duplicate (pipeline->rgb_image); gimp_image_undo_disable (duplicate); pipeline->background = webx_image_to_pixbuf (duplicate); gimp_image_delete (duplicate); } }
/* --------------------------------------- * gap_pview_render_f_from_image_duplicate * --------------------------------------- * render preview widget from image. * This procedure creates a temorary copy of the image * for rendering of the preview. * NOTE: if the caller wants to render a temporary image * that is not needed anymore after the rendering, * the procedure gap_pview_render_f_from_image should be used * to avoid duplicating of the image. * * 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_duplicate (GapPView *pv_ptr , gint32 image_id , gint32 flip_request , gint32 flip_status ) { gint32 dup_image_id; dup_image_id = gimp_image_duplicate(image_id); gimp_image_undo_disable (dup_image_id); gap_pview_render_f_from_image(pv_ptr , dup_image_id , flip_request , flip_status ); gimp_image_delete(dup_image_id); } /* end gap_pview_render_f_from_image_duplicate */
gint32 file_vtf_load_image (const gchar *fname, GError **error) { gimp_progress_init_printf ("Opening '%s'", gimp_filename_to_utf8 (fname)); gint32 image = -1; std::auto_ptr<Vtf::File> vtf (new Vtf::File); try { vtf->load(fname); Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*) vtf->findResource (Vtf::Resource::TypeHires); if (!vres) throw Vtf::Exception ("Cound not find high-resolution image"); image = gimp_image_new (vres->width (), vres->height (), GIMP_RGB); gimp_image_set_filename (image, fname); guint16 i, frame_count = vres->frameCount (); for (i = 0; i < frame_count; i++) { if (!file_vtf_load_layer (vres, image, i)) { g_set_error (error, 0, 0, "Unsupported format %s", Vtf::formatToString (vres->format())); gimp_image_delete (image); image = -1; break; } } gimp_progress_update (1.0); } catch (std::exception& e) { g_set_error (error, 0, 0, e.what ()); } return image; }
gint32 file_vtf_load_thumbnail_image (const gchar *fname, gint *width, gint *height, GError **error) { gint32 image = -1; gimp_progress_init_printf ("Opening thumbnail for '%s'", gimp_filename_to_utf8 (fname)); Vtf::File *vtf = new Vtf::File; try { vtf->load(fname); Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*) vtf->findResource(Vtf::Resource::TypeHires); if (!vres) throw Vtf::Exception ("Cound not find high-resolution image"); *width = static_cast<gint> (vres->width ()); *height = static_cast<gint> (vres->height ()); image = gimp_image_new (*width, *height, GIMP_RGB); if (!file_vtf_load_layer (vres, image, 0)) { g_set_error (error, 0, 0, "Unsupported format %s", Vtf::formatToString(vres->format())); gimp_image_delete (image); image = -1; } gimp_progress_update (1.0); } catch (std::exception& e) { g_set_error (error, 0, 0, e.what()); } delete vtf; return image; }
/* Main file load function */ gint32 load_thumbnail_image (const gchar *filename, gint *width, gint *height, GError **load_error) { FILE *f; struct stat st; PSDimage img_a; gint32 image_id = -1; GError *error = NULL; /* ----- Open PSD file ----- */ if (g_stat (filename, &st) == -1) return -1; IFDBG(1) g_debug ("Open file %s", gimp_filename_to_utf8 (filename)); f = g_fopen (filename, "rb"); if (f == NULL) { g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); return -1; } gimp_progress_init_printf (_("Opening thumbnail for '%s'"), gimp_filename_to_utf8 (filename)); /* ----- Read the PSD file Header block ----- */ IFDBG(2) g_debug ("Read header block"); if (read_header_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.2); /* ----- Read the PSD file Colour Mode block ----- */ IFDBG(2) g_debug ("Read colour mode block"); if (read_color_mode_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.4); /* ----- Read the PSD file Image Resource block ----- */ IFDBG(2) g_debug ("Read image resource block"); if (read_image_resource_block (&img_a, f, &error) < 0) goto load_error; gimp_progress_update (0.6); /* ----- Create GIMP image ----- */ IFDBG(2) g_debug ("Create GIMP image"); image_id = create_gimp_image (&img_a, filename); if (image_id < 0) goto load_error; /* ----- Add image resources ----- */ IFDBG(2) g_debug ("Add image resources"); if (add_image_resources (image_id, &img_a, f, &error) < 1) goto load_error; gimp_progress_update (1.0); gimp_image_clean_all (image_id); gimp_image_undo_enable (image_id); fclose (f); *width = img_a.columns; *height = img_a.rows; return image_id; /* ----- Process load errors ----- */ load_error: if (error) { g_set_error (load_error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error loading PSD file: %s"), error->message); g_error_free (error); } /* Delete partially loaded image */ if (image_id > 0) gimp_image_delete (image_id); /* Close file if Open */ if (! (f == NULL)) fclose (f); return -1; }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[2]; gint32 image_ID; gint32 drawable_ID; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpExportReturn export = GIMP_EXPORT_CANCEL; run_mode = param[0].data.d_int32; *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (strcmp (name, "file_icns_load") == 0) { switch (run_mode) { case GIMP_RUN_INTERACTIVE: interactive_ico = TRUE; break; case GIMP_RUN_NONINTERACTIVE: interactive_ico = FALSE; if (nparams != 3) status = GIMP_PDB_CALLING_ERROR; break; default: break; } if (status == GIMP_PDB_SUCCESS) { image_ID = LoadICNS (param[1].data.d_string); if (image_ID != -1) { *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; } else { status = GIMP_PDB_EXECUTION_ERROR; } } } else if (strcmp (name, "file_icns_save") == 0) { gchar *file_name; image_ID = param[1].data.d_int32; drawable_ID = param[2].data.d_int32; file_name = param[3].data.d_string; switch (run_mode) { case GIMP_RUN_INTERACTIVE: interactive_ico = TRUE; break; case GIMP_RUN_NONINTERACTIVE: interactive_ico = FALSE; /* Make sure all the arguments are there! */ if (nparams < 5) status = GIMP_PDB_CALLING_ERROR; break; case GIMP_RUN_WITH_LAST_VALS: interactive_ico = FALSE; break; default: break; } if (status == GIMP_PDB_SUCCESS) { status = SaveICNS (file_name, image_ID); } if (export == GIMP_EXPORT_EXPORT) gimp_image_delete (image_ID); }
gint32 load_image (const gchar *filename, GimpRunMode runmode, gboolean preview, gboolean *resolution_loaded, GError **error) { gint32 volatile image_ID; gint32 layer_ID; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; jpeg_saved_marker_ptr marker; FILE *infile; guchar *buf; guchar **rowbuf; GimpImageBaseType image_type; GimpImageType layer_type; GeglBuffer *buffer = NULL; const Babl *format; gint tile_height; gint scanlines; gint i, start, end; cmsHTRANSFORM cmyk_transform = NULL; /* We set up the normal JPEG error routines. */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; if (!preview) { jerr.pub.output_message = my_output_message; gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); } if ((infile = g_fopen (filename, "rb")) == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); return -1; } image_ID = -1; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); if (image_ID != -1 && !preview) gimp_image_delete (image_ID); if (preview) destroy_preview (); if (buffer) g_object_unref (buffer); return -1; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src (&cinfo, infile); if (! preview) { /* - step 2.1: tell the lib to save the comments */ jpeg_save_markers (&cinfo, JPEG_COM, 0xffff); /* - step 2.2: tell the lib to save APP1 data (Exif or XMP) */ jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xffff); /* - step 2.3: tell the lib to save APP2 data (ICC profiles) */ jpeg_save_markers (&cinfo, JPEG_APP0 + 2, 0xffff); } /* Step 3: read file parameters with jpeg_read_header() */ jpeg_read_header (&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ jpeg_start_decompress (&cinfo); /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. */ /* temporary buffer */ tile_height = gimp_tile_height (); buf = g_new (guchar, tile_height * cinfo.output_width * cinfo.output_components); rowbuf = g_new (guchar *, tile_height); for (i = 0; i < tile_height; i++) rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i; switch (cinfo.output_components) { case 1: image_type = GIMP_GRAY; layer_type = GIMP_GRAY_IMAGE; break; case 3: image_type = GIMP_RGB; layer_type = GIMP_RGB_IMAGE; break; case 4: if (cinfo.out_color_space == JCS_CMYK) { image_type = GIMP_RGB; layer_type = GIMP_RGB_IMAGE; break; } /*fallthrough*/ default: g_message ("Don't know how to load JPEG images " "with %d color channels, using colorspace %d (%d).", cinfo.output_components, cinfo.out_color_space, cinfo.jpeg_color_space); return -1; break; } if (preview) { image_ID = preview_image_ID; } else { image_ID = gimp_image_new_with_precision (cinfo.output_width, cinfo.output_height, image_type, GIMP_PRECISION_U8_GAMMA); gimp_image_undo_disable (image_ID); gimp_image_set_filename (image_ID, filename); } if (preview) { preview_layer_ID = gimp_layer_new (preview_image_ID, _("JPEG preview"), cinfo.output_width, cinfo.output_height, layer_type, 100, GIMP_NORMAL_MODE); layer_ID = preview_layer_ID; } else { layer_ID = gimp_layer_new (image_ID, _("Background"), cinfo.output_width, cinfo.output_height, layer_type, 100, GIMP_NORMAL_MODE); } if (! preview) { GString *comment_buffer = NULL; guint8 *profile = NULL; guint profile_size = 0; /* Step 5.0: save the original JPEG settings in a parasite */ jpeg_detect_original_settings (&cinfo, image_ID); /* Step 5.1: check for comments, or Exif metadata in APP1 markers */ for (marker = cinfo.marker_list; marker; marker = marker->next) { const gchar *data = (const gchar *) marker->data; gsize len = marker->data_length; if (marker->marker == JPEG_COM) { #ifdef GIMP_UNSTABLE g_print ("jpeg-load: found image comment (%d bytes)\n", marker->data_length); #endif if (! comment_buffer) { comment_buffer = g_string_new_len (data, len); } else { /* concatenate multiple comments, separate them with LF */ g_string_append_c (comment_buffer, '\n'); g_string_append_len (comment_buffer, data, len); } } else if ((marker->marker == JPEG_APP0 + 1) && (len > sizeof (JPEG_APP_HEADER_EXIF) + 8) && ! strcmp (JPEG_APP_HEADER_EXIF, data)) { #ifdef GIMP_UNSTABLE g_print ("jpeg-load: found Exif block (%d bytes)\n", (gint) (len - sizeof (JPEG_APP_HEADER_EXIF))); #endif } } if (jpeg_load_resolution (image_ID, &cinfo)) { if (resolution_loaded) *resolution_loaded = TRUE; } /* if we found any comments, then make a parasite for them */ if (comment_buffer && comment_buffer->len) { GimpParasite *parasite; jpeg_load_sanitize_comment (comment_buffer->str); parasite = gimp_parasite_new ("gimp-comment", GIMP_PARASITE_PERSISTENT, strlen (comment_buffer->str) + 1, comment_buffer->str); gimp_image_attach_parasite (image_ID, parasite); gimp_parasite_free (parasite); g_string_free (comment_buffer, TRUE); } /* Step 5.3: check for an embedded ICC profile in APP2 markers */ jpeg_icc_read_profile (&cinfo, &profile, &profile_size); if (cinfo.out_color_space == JCS_CMYK) { cmyk_transform = jpeg_load_cmyk_transform (profile, profile_size); } else if (profile) /* don't attach the profile if we are transforming */ { GimpParasite *parasite; parasite = gimp_parasite_new ("icc-profile", GIMP_PARASITE_PERSISTENT | GIMP_PARASITE_UNDOABLE, profile_size, profile); gimp_image_attach_parasite (image_ID, parasite); gimp_parasite_free (parasite); } g_free (profile); /* Do not attach the "jpeg-save-options" parasite to the image * because this conflicts with the global defaults (bug #75398). */ } /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ buffer = gimp_drawable_get_buffer (layer_ID); format = babl_format (image_type == GIMP_RGB ? "R'G'B' u8" : "Y' u8"); while (cinfo.output_scanline < cinfo.output_height) { start = cinfo.output_scanline; end = cinfo.output_scanline + tile_height; end = MIN (end, cinfo.output_height); scanlines = end - start; for (i = 0; i < scanlines; i++) jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1); if (cinfo.out_color_space == JCS_CMYK) jpeg_load_cmyk_to_rgb (buf, cinfo.output_width * scanlines, cmyk_transform); gegl_buffer_set (buffer, GEGL_RECTANGLE (0, start, cinfo.output_width, scanlines), 0, format, buf, GEGL_AUTO_ROWSTRIDE); if (! preview && (cinfo.output_scanline % 32) == 0) gimp_progress_update ((gdouble) cinfo.output_scanline / (gdouble) cinfo.output_height); } /* Step 7: Finish decompression */ jpeg_finish_decompress (&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ if (cmyk_transform) cmsDeleteTransform (cmyk_transform); /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress (&cinfo); g_object_unref (buffer); /* free up the temporary buffers */ g_free (rowbuf); g_free (buf); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose (infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.num_warnings is nonzero). */ /* Detach from the drawable and add it to the image. */ if (! preview) { gimp_progress_update (1.0); } gimp_image_insert_layer (image_ID, layer_ID, -1, 0); return image_ID; }
gint32 load_thumbnail_image (GFile *file, gint *width, gint *height, GimpImageType *type, GError **error) { gint32 volatile image_ID = -1; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile = NULL; gimp_progress_init_printf (_("Opening thumbnail for '%s'"), g_file_get_parse_name (file)); image_ID = gimp_image_metadata_load_thumbnail (file, error); if (image_ID < 1) return -1; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; jerr.pub.output_message = my_output_message; if ((infile = g_fopen (g_file_get_path (file), "rb")) == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), g_file_get_parse_name (file), g_strerror (errno)); if (image_ID != -1) gimp_image_delete (image_ID); return -1; } /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. We * need to clean up the JPEG object, close the input file, * and return. */ jpeg_destroy_decompress (&cinfo); if (image_ID != -1) gimp_image_delete (image_ID); return -1; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src (&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); *width = cinfo.output_width; *height = cinfo.output_height; switch (cinfo.output_components) { case 1: *type = GIMP_GRAY_IMAGE; break; case 3: *type = GIMP_RGB_IMAGE; break; case 4: if (cinfo.out_color_space == JCS_CMYK) { *type = GIMP_RGB_IMAGE; break; } /*fallthrough*/ default: g_message ("Don't know how to load JPEG images " "with %d color channels, using colorspace %d (%d).", cinfo.output_components, cinfo.out_color_space, cinfo.jpeg_color_space); gimp_image_delete (image_ID); image_ID = -1; break; } /* Step 4: Release JPEG decompression object */ /* This is an important step since it will release a good deal * of memory. */ jpeg_destroy_decompress (&cinfo); fclose (infile); return image_ID; }
/* ============================================================================ * 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; }
static void ico_dialog_update_icon_preview (GtkWidget *dialog, gint32 layer, gint bpp) { GtkWidget *preview = ico_dialog_get_layer_preview (dialog, layer); GdkPixbuf *pixbuf; gint w = gimp_drawable_width (layer); gint h = gimp_drawable_height (layer); if (! preview) return; if (bpp <= 8) { GimpDrawable *drawable; GimpDrawable *tmp; GimpPixelRgn src_pixel_rgn, dst_pixel_rgn; gint32 image; gint32 tmp_image; gint32 tmp_layer; guchar *buffer; guchar *cmap; gint num_colors; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); drawable = gimp_drawable_get (layer); tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); buffer = g_malloc (w * h * 4); gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); gimp_drawable_detach (tmp); gimp_drawable_detach (drawable); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 1 <<bpp, TRUE, FALSE, "dummy"); cmap = gimp_image_get_colormap (tmp_image, &num_colors); if ( num_colors == (1 << bpp) && !ico_cmap_contains_black (cmap, num_colors)) { /* Windows icons with color maps need the color black. * We need to eliminate one more color to make room for black. */ if (gimp_drawable_is_indexed (layer)) { g_free (cmap); cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); } else if (gimp_drawable_is_gray (layer)) { gimp_image_convert_grayscale (tmp_image); } else { gimp_image_convert_rgb (tmp_image); } tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); gimp_drawable_detach (tmp); if (!gimp_drawable_is_rgb (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, (1<<bpp) - 1, TRUE, FALSE, "dummy"); } g_free (cmap); g_free (buffer); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else if (bpp == 24) { GimpDrawable *drawable; GimpDrawable *tmp; GimpPixelRgn src_pixel_rgn, dst_pixel_rgn; gint32 image; gint32 tmp_image; gint32 tmp_layer; guchar *buffer; GimpParam *return_vals; gint n_return_vals; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); drawable = gimp_drawable_get (layer); tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); buffer = g_malloc (w * h * 4); gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); g_free (buffer); gimp_drawable_detach (tmp); gimp_drawable_detach (drawable); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); return_vals = gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, tmp_image, GIMP_PDB_DRAWABLE, tmp_layer, GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD, GIMP_PDB_END); gimp_destroy_params (return_vals, n_return_vals); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else { pixbuf = gimp_drawable_get_thumbnail (layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); } gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf); g_object_unref (pixbuf); }
gint32 load_thumbnail_image (const gchar *filename, gint *width, gint *height, GError **error) { gint32 volatile image_ID; ExifData *exif_data; GimpPixelRgn pixel_rgn; GimpDrawable *drawable; gint32 layer_ID; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; guchar *buf; guchar **rowbuf; gint image_type; gint layer_type; gint tile_height; gint scanlines; gint i, start, end; gint orientation; my_src_ptr src; FILE *infile; image_ID = -1; exif_data = jpeg_exif_data_new_from_file (filename, NULL); if (! ((exif_data) && (exif_data->data) && (exif_data->size > 0))) return -1; orientation = jpeg_exif_get_orientation (exif_data); cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; jerr.pub.output_message = my_output_message; gimp_progress_init_printf (_("Opening thumbnail for '%s'"), gimp_filename_to_utf8 (filename)); /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. We * need to clean up the JPEG object, close the input file, * and return. */ jpeg_destroy_decompress (&cinfo); if (image_ID != -1) gimp_image_delete (image_ID); if (exif_data) { exif_data_unref (exif_data); exif_data = NULL; } return -1; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ if (cinfo.src == NULL) cinfo.src = (struct jpeg_source_mgr *)(*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); src = (my_src_ptr) cinfo.src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; src->pub.term_source = term_source; src->pub.bytes_in_buffer = exif_data->size; src->pub.next_input_byte = exif_data->data; src->buffer = exif_data->data; src->size = exif_data->size; /* Step 3: read file parameters with jpeg_read_header() */ jpeg_read_header (&cinfo, TRUE); /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ jpeg_start_decompress (&cinfo); /* We may need to do some setup of our own at this point before * reading the data. After jpeg_start_decompress() we have the * correct scaled output image dimensions available, as well as * the output colormap if we asked for color quantization. In * this example, we need to make an output work buffer of the * right size. */ /* temporary buffer */ tile_height = gimp_tile_height (); buf = g_new (guchar, tile_height * cinfo.output_width * cinfo.output_components); rowbuf = g_new (guchar *, tile_height); for (i = 0; i < tile_height; i++) rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i; /* Create a new image of the proper size and associate the * filename with it. */ switch (cinfo.output_components) { case 1: image_type = GIMP_GRAY; layer_type = GIMP_GRAY_IMAGE; break; case 3: image_type = GIMP_RGB; layer_type = GIMP_RGB_IMAGE; break; case 4: if (cinfo.out_color_space == JCS_CMYK) { image_type = GIMP_RGB; layer_type = GIMP_RGB_IMAGE; break; } /*fallthrough*/ default: g_message ("Don't know how to load JPEG images " "with %d color channels, using colorspace %d (%d).", cinfo.output_components, cinfo.out_color_space, cinfo.jpeg_color_space); if (exif_data) { exif_data_unref (exif_data); exif_data = NULL; } return -1; break; } image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height, image_type); gimp_image_undo_disable (image_ID); gimp_image_set_filename (image_ID, filename); jpeg_load_resolution (image_ID, &cinfo); layer_ID = gimp_layer_new (image_ID, _("Background"), cinfo.output_width, cinfo.output_height, layer_type, 100, GIMP_NORMAL_MODE); drawable_global = drawable = gimp_drawable_get (layer_ID); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { start = cinfo.output_scanline; end = cinfo.output_scanline + tile_height; end = MIN (end, cinfo.output_height); scanlines = end - start; for (i = 0; i < scanlines; i++) jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1); if (cinfo.out_color_space == JCS_CMYK) jpeg_load_cmyk_to_rgb (buf, drawable->width * scanlines, NULL); gimp_pixel_rgn_set_rect (&pixel_rgn, buf, 0, start, drawable->width, scanlines); gimp_progress_update ((gdouble) cinfo.output_scanline / (gdouble) cinfo.output_height); } /* Step 7: Finish decompression */ jpeg_finish_decompress (&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal * of memory. */ jpeg_destroy_decompress (&cinfo); /* free up the temporary buffers */ g_free (rowbuf); g_free (buf); /* At this point you may want to check to see whether any * corrupt-data warnings occurred (test whether * jerr.num_warnings is nonzero). */ gimp_image_insert_layer (image_ID, layer_ID, -1, 0); /* NOW to get the dimensions of the actual image to return the * calling app */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; jerr.pub.output_message = my_output_message; if ((infile = g_fopen (filename, "rb")) == NULL) { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), g_strerror (errno)); if (exif_data) { exif_data_unref (exif_data); exif_data = NULL; } return -1; } /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. We * need to clean up the JPEG object, close the input file, * and return. */ jpeg_destroy_decompress (&cinfo); if (image_ID != -1) gimp_image_delete (image_ID); if (exif_data) { exif_data_unref (exif_data); exif_data = NULL; } return -1; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src (&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); *width = cinfo.output_width; *height = cinfo.output_height; /* Step 4: Release JPEG decompression object */ /* This is an important step since it will release a good deal * of memory. */ jpeg_destroy_decompress (&cinfo); fclose (infile); if (exif_data) { exif_data_unref (exif_data); exif_data = NULL; } jpeg_exif_rotate (image_ID, orientation); return image_ID; }
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; /* Plug-in variables */ gboolean single_image; gboolean defaults_proc; /* Plug-In variables */ cairo_surface_t *pdf_file; cairo_t *cr; GimpExportCapabilities capabilities; guint32 i = 0; gint32 j = 0; gdouble x_res, y_res; gdouble x_scale, y_scale; gint32 image_id; gboolean exported; GimpImageBaseType type; gint32 temp; gint *layers; gint32 num_of_layers; GimpDrawable *layer; cairo_surface_t *layer_image; gdouble opacity; gint x, y; GimpRGB layer_color; gboolean single_color; gint32 mask_id = -1; GimpDrawable *mask = NULL; cairo_surface_t *mask_image = NULL; FILE *fp; INIT_I18N (); /* Setting mandatory output values */ *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; /* Initializing all the settings */ multi_page.image_count = 0; if (! init_vals (name, nparams, param, &single_image, &defaults_proc, &run_mode)) { values[0].data.d_status = GIMP_PDB_CALLING_ERROR; return; } /* Starting the executions */ if (run_mode == GIMP_RUN_INTERACTIVE) { if (single_image) { if (! gui_single ()) { values[0].data.d_status = GIMP_PDB_CANCEL; return; } } else if (! gui_multi ()) { values[0].data.d_status = GIMP_PDB_CANCEL; return; } if (file_name == NULL) { values[0].data.d_status = GIMP_PDB_CALLING_ERROR; gimp_message (_("You must select a file to save!")); return; } } fp = g_fopen (file_name, "wb"); pdf_file = cairo_pdf_surface_create_for_stream (write_func, fp, 1, 1); if (cairo_surface_status (pdf_file) != CAIRO_STATUS_SUCCESS) { char *str = g_strdup_printf (_("An error occured while creating the PDF file:\n" "%s\n" "Make sure you entered a valid filename and that the selected location isn't read only!"), cairo_status_to_string (cairo_surface_status (pdf_file))); gimp_message (str); g_free (str); values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; return; } cr = cairo_create (pdf_file); capabilities = GIMP_EXPORT_CAN_HANDLE_RGB | GIMP_EXPORT_CAN_HANDLE_ALPHA | GIMP_EXPORT_CAN_HANDLE_GRAY | GIMP_EXPORT_CAN_HANDLE_LAYERS | GIMP_EXPORT_CAN_HANDLE_INDEXED; if (optimize.apply_masks) capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS; for (i = 0; i < multi_page.image_count; i++) { /* Save the state of the surface before any changes, so that settings * from one page won't affect all the others */ cairo_save (cr); image_id = multi_page.images[i]; /* We need the active layer in order to use gimp_image_export */ temp = gimp_image_get_active_drawable (image_id); if (temp == -1) exported = gimp_export_image (&image_id, &temp, NULL, capabilities) == GIMP_EXPORT_EXPORT; else exported = FALSE; type = gimp_image_base_type (image_id); gimp_image_get_resolution (image_id, &x_res, &y_res); x_scale = 72.0 / x_res; y_scale = 72.0 / y_res; cairo_pdf_surface_set_size (pdf_file, gimp_image_width (image_id) * x_scale, gimp_image_height (image_id) * y_scale); /* This way we set how many pixels are there in every inch. * It's very important for PangoCairo */ cairo_surface_set_fallback_resolution (pdf_file, x_res, y_res); /* PDF is usually 72 points per inch. If we have a different resolution, * we will need this to fit our drawings */ cairo_scale (cr, x_scale, y_scale); /* Now, we should loop over the layers of each image */ layers = gimp_image_get_layers (image_id, &num_of_layers); for (j = 0; j < num_of_layers; j++) { layer = gimp_drawable_get (layers [num_of_layers-j-1]); opacity = gimp_layer_get_opacity (layer->drawable_id)/100.0; /* Gimp doesn't display indexed layers with opacity below 50% * And if it's above 50%, it will be rounded to 100% */ if (type == GIMP_INDEXED) { if (opacity <= 0.5) opacity = 0.0; else opacity = 1.0; } if (gimp_item_get_visible (layer->drawable_id) && (! optimize.ignore_hidden || (optimize.ignore_hidden && opacity > 0.0))) { mask_id = gimp_layer_get_mask (layer->drawable_id); if (mask_id != -1) { mask = gimp_drawable_get (mask_id); mask_image = get_drawable_image (mask); } gimp_drawable_offsets (layer->drawable_id, &x, &y); /* For raster layers */ if (!gimp_item_is_text_layer (layer->drawable_id)) { layer_color = get_layer_color (layer, &single_color); cairo_rectangle (cr, x, y, layer->width, layer->height); if (optimize.vectorize && single_color) { cairo_set_source_rgba (cr, layer_color.r, layer_color.g, layer_color.b, layer_color.a * opacity); if (mask_id != -1) cairo_mask_surface (cr, mask_image, x, y); else cairo_fill (cr); } else { cairo_clip (cr); layer_image = get_drawable_image (layer); cairo_set_source_surface (cr, layer_image, x, y); cairo_push_group (cr); cairo_paint_with_alpha (cr, opacity); cairo_pop_group_to_source (cr); if (mask_id != -1) cairo_mask_surface (cr, mask_image, x, y); else cairo_paint (cr); cairo_reset_clip (cr); cairo_surface_destroy (layer_image); } } /* For text layers */ else { drawText (layer, opacity, cr, x_res, y_res); } } /* We are done with the layer - time to free some resources */ gimp_drawable_detach (layer); if (mask_id != -1) { gimp_drawable_detach (mask); cairo_surface_destroy (mask_image); } } /* We are done with this image - Show it! */ cairo_show_page (cr); cairo_restore (cr); if (exported) gimp_image_delete (image_id); } /* We are done with all the images - time to free the resources */ cairo_surface_destroy (pdf_file); cairo_destroy (cr); fclose (fp); /* Finally done, let's save the parameters */ gimp_set_data (DATA_OPTIMIZE, &optimize, sizeof (optimize)); if (!single_image) { g_strlcpy (multi_page.file_name, file_name, MAX_FILE_NAME_LENGTH); gimp_set_data (DATA_IMAGE_LIST, &multi_page, sizeof (multi_page)); } }
static void ico_dialog_update_icon_preview (GtkWidget *dialog, gint32 layer, gint bpp) { GtkWidget *preview = ico_dialog_get_layer_preview (dialog, layer); GdkPixbuf *pixbuf; const Babl *format; gint w = gimp_drawable_width (layer); gint h = gimp_drawable_height (layer); if (! preview) return; switch (gimp_drawable_type (layer)) { case GIMP_RGB_IMAGE: format = babl_format ("R'G'B' u8"); break; case GIMP_RGBA_IMAGE: format = babl_format ("R'G'B'A u8"); break; case GIMP_GRAY_IMAGE: format = babl_format ("Y' u8"); break; case GIMP_GRAYA_IMAGE: format = babl_format ("Y'A u8"); break; case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: format = gimp_drawable_get_format (layer); default: g_return_if_reached (); } if (bpp <= 8) { GeglBuffer *buffer; GeglBuffer *tmp; gint32 image; gint32 tmp_image; gint32 tmp_layer; guchar *buf; guchar *cmap; gint num_colors; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); buffer = gimp_drawable_get_buffer (layer); tmp = gimp_drawable_get_buffer (tmp_layer); buf = g_malloc (w * h * 4); gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gegl_buffer_copy (buffer, NULL, tmp, NULL); g_object_unref (tmp); g_object_unref (buffer); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 1 << bpp, TRUE, FALSE, "dummy"); cmap = gimp_image_get_colormap (tmp_image, &num_colors); if (num_colors == (1 << bpp) && ! ico_cmap_contains_black (cmap, num_colors)) { /* Windows icons with color maps need the color black. * We need to eliminate one more color to make room for black. */ if (gimp_drawable_is_indexed (layer)) { g_free (cmap); cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); } else if (gimp_drawable_is_gray (layer)) { gimp_image_convert_grayscale (tmp_image); } else { gimp_image_convert_rgb (tmp_image); } tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0, format, buf, GEGL_AUTO_ROWSTRIDE); g_object_unref (tmp); if (!gimp_drawable_is_rgb (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, (1 << bpp) - 1, TRUE, FALSE, "dummy"); } g_free (cmap); g_free (buf); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else if (bpp == 24) { GeglBuffer *buffer; GeglBuffer *tmp; gint32 image; gint32 tmp_image; gint32 tmp_layer; GimpParam *return_vals; gint n_return_vals; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); buffer = gimp_drawable_get_buffer (layer); tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_copy (buffer, NULL, tmp, NULL); g_object_unref (tmp); g_object_unref (buffer); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); return_vals = gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, tmp_image, GIMP_PDB_DRAWABLE, tmp_layer, GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD, GIMP_PDB_END); gimp_destroy_params (return_vals, n_return_vals); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else { pixbuf = gimp_drawable_get_thumbnail (layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); } gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf); g_object_unref (pixbuf); }
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; }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[2]; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; gint32 image_ID; gint32 drawable_ID; GimpExportReturn export = GIMP_EXPORT_CANCEL; GError *error = NULL; run_mode = param[0].data.d_int32; INIT_I18N (); *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (strcmp (name, LOAD_PROC) == 0) { image_ID = load_image (param[1].data.d_string, &error); if (image_ID != -1) { *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; } else { status = GIMP_PDB_EXECUTION_ERROR; } } else if (strcmp (name, SAVE_PROC) == 0) { gimp_ui_init (PLUG_IN_BINARY, FALSE); image_ID = param[1].data.d_int32; drawable_ID = param[2].data.d_int32; /* eventually export the image */ switch (run_mode) { case GIMP_RUN_INTERACTIVE: case GIMP_RUN_WITH_LAST_VALS: export = gimp_export_image (&image_ID, &drawable_ID, NULL, (GIMP_EXPORT_CAN_HANDLE_RGB | GIMP_EXPORT_CAN_HANDLE_GRAY | GIMP_EXPORT_CAN_HANDLE_INDEXED | GIMP_EXPORT_CAN_HANDLE_ALPHA )); if (export == GIMP_EXPORT_CANCEL) { values[0].data.d_status = GIMP_PDB_CANCEL; return; } break; default: break; } switch (run_mode) { case GIMP_RUN_INTERACTIVE: /* Possibly retrieve data */ gimp_get_data ("file_xpm_save", &xpmvals); /* First acquire information with a dialog */ if (gimp_drawable_has_alpha (drawable_ID)) if (! save_dialog ()) status = GIMP_PDB_CANCEL; break; case GIMP_RUN_NONINTERACTIVE: /* Make sure all the arguments are there! */ if (nparams != 6) { status = GIMP_PDB_CALLING_ERROR; } else { xpmvals.threshold = param[5].data.d_int32; if (xpmvals.threshold < 0 || xpmvals.threshold > 255) status = GIMP_PDB_CALLING_ERROR; } break; case GIMP_RUN_WITH_LAST_VALS: /* Possibly retrieve data */ gimp_get_data ("file_xpm_save", &xpmvals); break; default: break; } if (status == GIMP_PDB_SUCCESS) { if (save_image (param[3].data.d_string, image_ID, drawable_ID, &error)) { gimp_set_data ("file_xpm_save", &xpmvals, sizeof (XpmSaveVals)); } else { status = GIMP_PDB_EXECUTION_ERROR; } } if (export == GIMP_EXPORT_EXPORT) gimp_image_delete (image_ID); }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[4]; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpExportReturn ret = GIMP_EXPORT_CANCEL; GError *error = NULL; run_mode = (GimpRunMode) param[0].data.d_int32; *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; if (strcmp (name, LOAD_PROC) == 0) { switch (run_mode) { case GIMP_RUN_INTERACTIVE: break; case GIMP_RUN_NONINTERACTIVE: if (nparams != 3) status = GIMP_PDB_CALLING_ERROR; break; default: break; } if (status == GIMP_PDB_SUCCESS) { gint32 image_ID; image_ID = file_vtf_load_image (param[1].data.d_string, &error); if (image_ID != -1) { *nreturn_vals = 2; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; } else { status = GIMP_PDB_EXECUTION_ERROR; } } } else if (strcmp (name, LOAD_THUMB_PROC) == 0) { if (nparams < 2) { status = GIMP_PDB_CALLING_ERROR; } else { const gchar *filename = param[0].data.d_string; gint width = param[1].data.d_int32; gint height = param[1].data.d_int32; gint32 image_ID; image_ID = file_vtf_load_thumbnail_image (filename, &width, &height, &error); if (image_ID != -1) { *nreturn_vals = 4; values[1].type = GIMP_PDB_IMAGE; values[1].data.d_image = image_ID; values[2].type = GIMP_PDB_INT32; values[2].data.d_int32 = width; values[3].type = GIMP_PDB_INT32; values[3].data.d_int32 = height; } else { status = GIMP_PDB_EXECUTION_ERROR; } } } else if (strcmp (name, SAVE_PROC) == 0) { gchar *file_name; gint32 image_ID; image_ID = param[1].data.d_int32; file_name = param[3].data.d_string; switch (run_mode) { case GIMP_RUN_INTERACTIVE: break; case GIMP_RUN_NONINTERACTIVE: if (nparams < 5) status = GIMP_PDB_CALLING_ERROR; break; case GIMP_RUN_WITH_LAST_VALS: break; default: break; } if (status == GIMP_PDB_SUCCESS) { status = file_vtf_save_image (file_name, image_ID, run_mode, &error); } if (ret == GIMP_EXPORT_EXPORT) gimp_image_delete (image_ID); } else { status = GIMP_PDB_CALLING_ERROR; } if (status != GIMP_PDB_SUCCESS && error) { *nreturn_vals = 2; values[1].type = GIMP_PDB_STRING; values[1].data.d_string = error->message; } values[0].data.d_status = status; }
static GimpPDBStatusType plt_load(gchar *filename, gint32 *image_id) { FILE *stream = 0; unsigned int i; // Using uint for guaranteed sizes across all systems // guint may or may not work (?) uint8_t plt_version[8]; uint32_t plt_width = 0; uint32_t plt_height = 0; uint8_t *buffer; uint8_t px_value = 0; uint8_t px_layer = 0; uint32_t num_px = 0; gint32 newImgID = -1; gint32 newLayerID = -1; gint32 plt_layer_ids[PLT_NUM_LAYERS]; guint8 pixel[2] = {0, 255}; // GRAYA image = 2 Channels: Value + Alpha stream = fopen(filename, "rb"); if(stream == 0) { g_message("Error opening file.\n"); return (GIMP_PDB_EXECUTION_ERROR); } gimp_progress_init_printf("Opening %s", filename); gimp_progress_update(0.0); // Read header: Version, should be 8x1 bytes = "PLT V1 " if (fread(plt_version, 1, 8, stream) < 8) { g_message("Invalid plt file: Unable to read version information.\n"); fclose(stream); return (GIMP_PDB_EXECUTION_ERROR); } if (g_ascii_strncasecmp(plt_version, PLT_HEADER_VERSION, 8) != 0) { g_message("Invalid plt file: Version mismatch.\n"); fclose(stream); return (GIMP_PDB_EXECUTION_ERROR); } // Read header: Next 8 bytes don't matter fseek(stream, 8, SEEK_CUR); // Read header: Width if (fread(&plt_width, 4, 1, stream) < 1) { g_message("Invalid plt file: Unable to read width.\n"); fclose(stream); return (GIMP_PDB_EXECUTION_ERROR); } // Read header: Height if (fread(&plt_height, 4, 1, stream) < 1) { g_message("Invalid plt file: Unable to read height.\n"); fclose(stream); return (GIMP_PDB_EXECUTION_ERROR); } // Create a new image newImgID = gimp_image_new(plt_width, plt_height, GIMP_GRAY); if(newImgID == -1) { g_message("Unable to allocate new image.\n"); fclose(stream); return (GIMP_PDB_EXECUTION_ERROR); } gimp_image_set_filename(newImgID, filename); // Create the 10 plt layers, add them to the new image and save their ID's for (i = 0; i < PLT_NUM_LAYERS; i++) { newLayerID = gimp_layer_new(newImgID, plt_layernames[i], plt_width, plt_height, GIMP_GRAYA_IMAGE, 100.0, GIMP_NORMAL_MODE); gimp_image_insert_layer(newImgID, newLayerID, 0, 0); plt_layer_ids[i] = newLayerID; } // Read image data // Expecting width*height (value, layer) tuples = 2*width*height bytes num_px = plt_width * plt_height; buffer = (uint8_t*) g_malloc(sizeof(uint8_t)*2*num_px); if (fread(buffer, 1, 2*num_px, stream) < (2*num_px)) { g_message("Image size mismatch.\n"); fclose(stream); g_free(buffer); gimp_image_delete(newImgID); return (GIMP_PDB_EXECUTION_ERROR); } for (i = 0; i < num_px; i++) { pixel[0] = buffer[2*i]; px_layer = buffer[2*i+1]; gimp_drawable_set_pixel(plt_layer_ids[px_layer], i % plt_width, plt_height - (int)(floor(i / plt_width)) - 1, 2, pixel); gimp_progress_update((float) i/ (float) num_px); } gimp_progress_update(1.0); gimp_image_set_active_layer(newImgID, plt_layer_ids[0]); fclose(stream); g_free(buffer); *image_id = newImgID; return (GIMP_PDB_SUCCESS); }
static gint32 load_image (const gchar *filename, gboolean interactive, GError **error) { gint32 status = -1; EXRLoader *loader; int width; int height; gboolean has_alpha; GimpImageBaseType image_type; GimpPrecision image_precision; gint32 image = -1; GimpImageType layer_type; int layer; const Babl *format; GeglBuffer *buffer = NULL; int bpp; int tile_height; gchar *pixels = NULL; int begin; int end; int num; loader = exr_loader_new (filename); if (!loader) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error opening file '%s' for reading"), gimp_filename_to_utf8 (filename)); goto out; } width = exr_loader_get_width (loader); height = exr_loader_get_height (loader); if ((width < 1) || (height < 1)) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error querying image dimensions from '%s'"), gimp_filename_to_utf8 (filename)); goto out; } has_alpha = exr_loader_has_alpha (loader) ? TRUE : FALSE; switch (exr_loader_get_precision (loader)) { case PREC_UINT: image_precision = GIMP_PRECISION_U32; break; case PREC_HALF: image_precision = GIMP_PRECISION_HALF; break; case PREC_FLOAT: image_precision = GIMP_PRECISION_FLOAT; break; default: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error querying image precision from '%s'"), gimp_filename_to_utf8 (filename)); goto out; } switch (exr_loader_get_image_type (loader)) { case IMAGE_TYPE_RGB: image_type = GIMP_RGB; layer_type = has_alpha ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE; break; case IMAGE_TYPE_GRAY: image_type = GIMP_GRAY; layer_type = has_alpha ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE; break; default: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error querying image type from '%s'"), gimp_filename_to_utf8 (filename)); goto out; } gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); image = gimp_image_new_with_precision (width, height, image_type, image_precision); if (image == -1) { g_set_error (error, 0, 0, _("Could not create new image for '%s': %s"), gimp_filename_to_utf8 (filename), gimp_get_pdb_error ()); goto out; } gimp_image_set_filename (image, filename); layer = gimp_layer_new (image, _("Background"), width, height, layer_type, 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (image, layer, -1, 0); buffer = gimp_drawable_get_buffer (layer); format = gimp_drawable_get_format (layer); bpp = babl_format_get_bytes_per_pixel (format); tile_height = gimp_tile_height (); pixels = g_new0 (gchar, tile_height * width * bpp); for (begin = 0; begin < height; begin += tile_height) { int retval; int i; end = MIN (begin + tile_height, height); num = end - begin; for (i = 0; i < num; i++) { retval = exr_loader_read_pixel_row (loader, pixels + (i * width * bpp), bpp, begin + i); if (retval < 0) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Error reading pixel data from '%s'"), gimp_filename_to_utf8 (filename)); goto out; } } gegl_buffer_set (buffer, GEGL_RECTANGLE (0, begin, width, num), 0, NULL, pixels, GEGL_AUTO_ROWSTRIDE); gimp_progress_update ((gdouble) begin / (gdouble) height); } gimp_progress_update (1.0); status = image; out: if (buffer) g_object_unref (buffer); if ((status != image) && (image != -1)) { /* This should clean up any associated layers too. */ gimp_image_delete (image); } if (pixels) g_free (pixels); if (loader) exr_loader_unref (loader); return status; }
/* 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 process_image(gpointer parent) { gboolean success = TRUE; image_output imageout = (image_output)g_malloc(sizeof(struct imageout_str)); char* orig_filename = NULL; char* orig_basename = NULL; char* orig_file_ext = NULL; char* output_file_comp = NULL; // store original file path and name orig_filename = g_slist_nth (bimp_input_filenames, processed_count)->data; orig_basename = g_strdup(comp_get_filename(orig_filename)); // store original extension and check error cases orig_file_ext = g_strdup(strrchr(orig_basename, '.')); if (orig_file_ext == NULL) { /* under Linux, GtkFileChooser lets to pick an image file without extension, but GIMP cannot * save it back if its format remains unchanged. Operation can continue only if a MANIP_CHANGEFORMAT * is present */ if (list_contains_changeformat) { orig_file_ext = g_malloc0(sizeof(char)); } else { bimp_show_error_dialog(g_strdup_printf(_("Can't save image \"%s\": input file has no extension.\nYou can solve this error by adding a \"Change format or compression\" step"), orig_basename), bimp_window_main); success = FALSE; goto process_end; } } else if (g_ascii_strcasecmp(orig_file_ext, ".svg") == 0 && !list_contains_changeformat) { bimp_show_error_dialog(g_strdup_printf(_("GIMP can't save %s back to its original SVG format.\nYou can solve this error by adding a \"Change format or compression\" step"), orig_basename), bimp_window_main); success = FALSE; goto process_end; } g_print("\nWorking on file %d of %d (%s)\n", processed_count + 1, total_images, orig_filename); bimp_progress_bar_set(((double)processed_count)/total_images, g_strdup_printf(_("Working on file \"%s\"..."), orig_basename)); // rename and save process... orig_basename[strlen(orig_basename) - strlen(orig_file_ext)] = '\0'; // remove extension from basename // check if a rename pattern is defined if(list_contains_rename) { g_print("Applying RENAME...\n"); apply_rename((rename_settings)(bimp_list_get_manip(MANIP_RENAME))->settings, imageout, orig_basename); } else { imageout->filename = orig_basename; } // To keep the folder hierarchy if (common_folder_path == NULL) { // Not selected or required, everything goes into the same destination folder output_file_comp = g_malloc0(sizeof(char)); } else { // keep folders to add to output path output_file_comp = g_strndup(&orig_filename[strlen(common_folder_path)+1], strlen(orig_filename)-(strlen(common_folder_path)+1) -strlen(orig_basename)-strlen(orig_file_ext)); } if (strlen(output_file_comp) > 0) { #ifdef _WIN32 // Clean output_file_comp // Should only be concerned for ':' in Drive letter int i; for (i = 0; i < strlen(output_file_comp); ++i) if ( output_file_comp[i] == ':' ) output_file_comp[i] = '_'; #endif // Create path if needed g_mkdir_with_parents( g_strconcat(bimp_output_folder, FILE_SEPARATOR_STR, output_file_comp, NULL), 0777 ); } // save the final image in output dir with proper format and params format_type final_format = -1; format_params params = NULL; if(list_contains_changeformat) { changeformat_settings settings = (changeformat_settings)(bimp_list_get_manip(MANIP_CHANGEFORMAT))->settings; final_format = settings->format; params = settings->params; g_print("Changing FORMAT to %s\n", format_type_string[final_format][0]); imageout->filename = g_strconcat(imageout->filename, ".", format_type_string[final_format][0], NULL); // append new file extension imageout->filepath = g_strconcat(bimp_output_folder, FILE_SEPARATOR_STR, output_file_comp, imageout->filename, NULL); // build new path } // TO CHECK what apply_userdef does once coded else if (list_contains_savingplugin) { // leave filename without extension and proceed calling each saving plugin imageout->filename = g_strconcat(imageout->filename, ".dds", NULL); imageout->filepath = g_strconcat(bimp_output_folder, FILE_SEPARATOR_STR, output_file_comp, imageout->filename, NULL); // build new path GSList *iterator = NULL; manipulation man; for (iterator = bimp_selected_manipulations; iterator; iterator = iterator->next) { man = (manipulation)(iterator->data); if (man->type == MANIP_USERDEF && strstr(((userdef_settings)(man->settings))->procedure, "-save") != NULL) { /* found a saving plugin, execute it // TODO!!!! This won't work yet, we need a way to extract the file extension managed by the selected saving plugin * e.g. "file-dds-save" -> "dds" (don't do it with regexp on plugin's name... too easy...) */ apply_userdef((userdef_settings)(man->settings), imageout); } } } else { // if not specified, save in original format imageout->filename = g_strconcat(imageout->filename, orig_file_ext, NULL); // append old file extension imageout->filepath = g_strconcat(bimp_output_folder, FILE_SEPARATOR_STR, output_file_comp, imageout->filename, NULL); // build new path final_format = -1; } // check if writing possible gboolean will_overwrite = FALSE; if (bimp_opt_alertoverwrite != BIMP_OVERWRITE_SKIP_ASK) { // file already exists ? will_overwrite = g_file_test(imageout->filepath, G_FILE_TEST_IS_REGULAR); if (will_overwrite) { // "Don't overwrite" without confirmation if (bimp_opt_alertoverwrite == BIMP_DONT_OVERWRITE_SKIP_ASK) { g_print("Destination file already exists and won't be overwritten\n"); goto process_end; } else { // Ask what to do int ow_res = overwrite_result(imageout->filepath, parent); if (ow_res == 0) { g_print("Destination file already exists and user select to don't overwrite\n"); goto process_end; } } } } // apply all the main manipulations bimp_apply_drawable_manipulations(imageout, (gchar*)orig_filename, (gchar*)orig_basename); time_t mod_time = -1; if (will_overwrite && bimp_opt_keepdates) { // I must keep the dates even if the file has been overwritten mod_time = get_modification_time(imageout->filepath); if (mod_time == -1) g_print("An error occurred when retrieving the modification date of file.\n"); } // Save g_print("Saving file %s in %s\n", imageout->filename, imageout->filepath); image_save(final_format, imageout, params); if (will_overwrite && bimp_opt_keepdates && mod_time > -1) { // replace with the old dates int res = set_modification_time(imageout->filepath, mod_time); if (res == -1) g_print("An error occurred when replacing the modification date of file.\n"); } gimp_image_delete(imageout->image_id); // is it useful? process_end: g_free(orig_basename); g_free(orig_file_ext); g_free(output_file_comp); g_free(imageout->filename); g_free(imageout->filepath); g_free(imageout); processed_count++; if (success) success_count++; // TODO: errors check here if (!bimp_is_busy) { bimp_progress_bar_set(0.0, _("Operations stopped")); g_print("\nStopped, %d files processed.\n", processed_count); return FALSE; } else { if (processed_count == total_images) { int errors_count = processed_count - success_count; bimp_progress_bar_set(1.0, g_strdup_printf(_("End, all files have been processed with %d errors"), errors_count)); g_print("\nEnd, %d files have been processed with %d errors.\n", processed_count, errors_count); bimp_set_busy(FALSE); return FALSE; } else { return TRUE; } } }
static void ico_image_get_reduced_buf (guint32 layer, gint bpp, gint *num_colors, guchar **cmap_out, guchar **buf_out) { gint32 tmp_image; gint32 tmp_layer; gint w, h; guchar *buf; guchar *cmap = NULL; GeglBuffer *buffer = gimp_drawable_get_buffer (layer); const Babl *format; w = gegl_buffer_get_width (buffer); h = gegl_buffer_get_height (buffer); switch (gimp_drawable_type (layer)) { case GIMP_RGB_IMAGE: format = babl_format ("R'G'B' u8"); break; case GIMP_RGBA_IMAGE: format = babl_format ("R'G'B'A u8"); break; case GIMP_GRAY_IMAGE: format = babl_format ("Y' u8"); break; case GIMP_GRAYA_IMAGE: format = babl_format ("Y'A u8"); break; case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: format = gegl_buffer_get_format (buffer); default: g_return_if_reached (); } *num_colors = 0; buf = g_new (guchar, w * h * 4); if (bpp <= 8 || bpp == 24 || babl_format_get_bytes_per_pixel (format) != 4) { gint32 image = gimp_item_get_image (layer); GeglBuffer *tmp; tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "tmp", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, tmp, NULL); g_object_unref (tmp); if (! gimp_drawable_is_rgb (tmp_layer)) gimp_image_convert_rgb (tmp_image); if (bpp <= 8) { gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 1 << bpp, TRUE, FALSE, "dummy"); cmap = gimp_image_get_colormap (tmp_image, num_colors); if (*num_colors == (1 << bpp) && ! ico_cmap_contains_black (cmap, *num_colors)) { /* Windows icons with color maps need the color black. * We need to eliminate one more color to make room for black. */ if (gimp_drawable_is_indexed (layer)) { g_free (cmap); cmap = gimp_image_get_colormap (image, num_colors); gimp_image_set_colormap (tmp_image, cmap, *num_colors); } else if (gimp_drawable_is_gray (layer)) { gimp_image_convert_grayscale (tmp_image); } else { gimp_image_convert_rgb (tmp_image); } tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0, format, buf, GEGL_AUTO_ROWSTRIDE); g_object_unref (tmp); if (! gimp_drawable_is_rgb (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, (1<<bpp) - 1, TRUE, FALSE, "dummy"); g_free (cmap); cmap = gimp_image_get_colormap (tmp_image, num_colors); } gimp_image_convert_rgb (tmp_image); } else if (bpp == 24) { GimpParam *return_vals; gint n_return_vals; return_vals = gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, tmp_image, GIMP_PDB_DRAWABLE, tmp_layer, GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD, GIMP_PDB_END); gimp_destroy_params (return_vals, n_return_vals); } gimp_layer_add_alpha (tmp_layer); tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_get (tmp, GEGL_RECTANGLE (0, 0, w, h), 1.0, NULL, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); g_object_unref (tmp); gimp_image_delete (tmp_image); } else { gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); } g_object_unref (buffer); *cmap_out = cmap; *buf_out = buf; }
static gint32 load_image (char *filename) { GPixelRgn pixel_rgn; TileDrawable *drawable; gint32 image_ID; gint32 layer_ID; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; guchar *buf; guchar **rowbuf; char *name; int image_type; int layer_type; int tile_height; int scanlines; int i, start, end; int m; int depth = 8; /* We set up the normal JPEG error routines. */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; if ((infile = fopen (filename, "rb")) == NULL) { g_warning ("can't open \"%s\"\n", filename); gimp_quit (); } if( strrchr(filename,'.') && strcmp( strrchr(filename, '.'), ".jp4") == 0 ) depth = 16; name = malloc (strlen (filename) + 12); sprintf (name, "%s %s:", _("Loading"), filename); gimp_progress_init (name); free (name); image_ID = -1; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); if (image_ID != -1) gimp_image_delete (image_ID); gimp_quit (); } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src (&cinfo, infile); setup_read_icc_profile(&cinfo); for (m = 0; m < 16; m++) jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header (&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ prepareColour( &cinfo ); /* Step 5: Start decompressor */ jpeg_start_decompress (&cinfo); /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* temporary buffer */ tile_height = gimp_tile_height (); buf = g_new (guchar, tile_height * cinfo.output_width * cinfo.output_components); rowbuf = g_new (guchar*, tile_height); for (i = 0; i < tile_height; i++) rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i; /* Create a new image of the proper size and associate the filename with it. */ if(depth == 8) { switch (cinfo.output_components) { case 1: image_type = GRAY; layer_type = GRAY_IMAGE; break; case 3: image_type = RGB; layer_type = RGB_IMAGE; break; case 4: image_type = RGB; layer_type = RGBA_IMAGE; break; default: gimp_quit (); } } else { switch (cinfo.output_components) { case 1: image_type = U16_GRAY; layer_type = U16_GRAY_IMAGE; break; case 3: image_type = U16_RGB; layer_type = U16_RGB_IMAGE; break; case 4: image_type = U16_RGB; layer_type = U16_RGBA_IMAGE; break; default: gimp_quit (); } } image_ID = gimp_image_new (cinfo.output_width / (depth/8), cinfo.output_height, image_type); gimp_image_set_filename (image_ID, filename); layer_ID = gimp_layer_new (image_ID, _("Background"), cinfo.output_width / (depth/8), cinfo.output_height, layer_type, 100, NORMAL_MODE); gimp_image_add_layer (image_ID, layer_ID, 0); drawable = gimp_drawable_get (layer_ID); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { start = cinfo.output_scanline; end = cinfo.output_scanline + tile_height; end = MIN (end,CAST(int) cinfo.output_height); scanlines = end - start; for (i = 0; i < scanlines; i++) jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1); /* for (i = start; i < end; i++) gimp_pixel_rgn_set_row (&pixel_rgn, tilerow[i - start], 0, i, drawable->width); */ if(cinfo.out_color_space == JCS_CMYK) for(i = 0; i < scanlines*drawable->width*cinfo.output_components; ++i) buf[i] = 255 - buf[i]; if(depth == 16 && 0) for(i = 0; i < scanlines*drawable->width*cinfo.output_components; ++i) { unsigned char c = buf[2*i]; buf[2*i] = buf[2*i+1]; buf[2*i+1] = c; } gimp_pixel_rgn_set_rect (&pixel_rgn, buf, 0, start, drawable->width, scanlines); gimp_progress_update ((double) cinfo.output_scanline / (double) cinfo.output_height); } // Step 6a: read icc profile { LPBYTE Buffer = NULL; size_t Len = 0; cmsHPROFILE hProfile=NULL; if (read_icc_profile(&cinfo, &Buffer, &Len)) { printf ("%s:%d %s() embedded profile found\n",__FILE__,__LINE__,__func__); } else if (read_icc_profile2(&cinfo, &Buffer, &Len)) { printf ("%s:%d %s() default profile selected\n",__FILE__,__LINE__,__func__); } if(Buffer && Len) { hProfile = cmsOpenProfileFromMem(Buffer, Len); if (hProfile) { gimp_image_set_icc_profile_by_mem (image_ID, Len, Buffer, ICC_IMAGE_PROFILE); cmsCloseProfile (hProfile); free(Buffer); printf ("%s:%d %s() set profile\n",__FILE__,__LINE__,__func__); } } } /* Step 7: Finish decompression */ jpeg_finish_decompress (&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress (&cinfo); /* free up the temporary buffers */ g_free (rowbuf); g_free (buf); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose (infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.num_warnings is nonzero). */ /* Tell the GIMP to display the image. */ gimp_drawable_flush (drawable); return image_ID; }
/* -------------------------- * p_process_layer * -------------------------- */ static gint32 p_process_layer(gint32 image_id, gint32 drawable_id, TransValues *val_ptr) { gboolean has_selection; gboolean non_empty; gboolean alt_selection_success; gint x1, y1, x2, y2; gint32 trans_drawable_id; if(gap_debug) { printf("corpus_border_radius: %d\n", (int)val_ptr->corpus_border_radius); printf("alt_selection: %d\n", (int)val_ptr->alt_selection); printf("seed: %d\n", (int)val_ptr->seed); } gimp_image_undo_group_start(image_id); trans_drawable_id = -1; alt_selection_success = FALSE; if(val_ptr->alt_selection >= 0) { if(gap_debug) { printf("p_process_layer creating alt_selection: %d\n", (int)val_ptr->alt_selection); } alt_selection_success = p_set_alt_selection(image_id, drawable_id, val_ptr); } has_selection = gimp_selection_bounds(image_id, &non_empty, &x1, &y1, &x2, &y2); if(gap_debug) { printf("p_process_layer has_selection: %d\n", (int)has_selection); } /* here the action starts, we create the corpus_layer_id that builds the reference pattern * (the corpus is created in a spearate image and has an expanded selection * that excludes the unwanted parts) * then start the resynthesizer plug-in to replace selected (i.e. unwanted parts) of the * processed layer (i.e. drawable_id) */ if (non_empty) { gint32 corpus_layer_id; gint32 corpus_image_id; trans_drawable_id = drawable_id; corpus_layer_id = p_create_corpus_layer(image_id, drawable_id, val_ptr); p_pdb_call_resynthesizer(image_id, drawable_id, corpus_layer_id, val_ptr->seed); /* delete the temporary working duplicate */ corpus_image_id = gimp_item_get_image(corpus_layer_id); gimp_image_delete(corpus_image_id); } else { g_message("Please make a selection (cant operate on empty selection)"); } if(alt_selection_success) { gimp_selection_none(image_id); } gimp_image_undo_group_end(image_id); return (trans_drawable_id); } /* end p_process_layer */