static gint32 load_image (const gchar *uri, GimpRunMode run_mode, GError **error) { gchar *tmpname = NULL; gint32 image_ID = -1; gboolean name_image = FALSE; tmpname = get_temp_name (uri, &name_image); if (uri_backend_load_image (uri, tmpname, run_mode, error)) { image_ID = gimp_file_load (run_mode, tmpname, tmpname); if (image_ID != -1) { if (name_image) gimp_image_set_filename (image_ID, uri); else gimp_image_set_filename (image_ID, ""); } else { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "%s", gimp_get_pdb_error ()); } } g_unlink (tmpname); g_free (tmpname); return image_ID; }
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */ static gint32 create_new_image (const gchar *filename, const gchar *layername, guint width, guint height, GimpImageBaseType type, gdouble xres, gdouble yres, gint32 *layer_ID, GimpDrawable **drawable, GimpPixelRgn *pixel_rgn) { gint32 image_ID; image_ID = gimp_image_new (width, height, type); gimp_image_undo_disable (image_ID); gimp_image_set_filename (image_ID, filename); gimp_image_set_resolution (image_ID, xres, yres); *layer_ID = create_new_layer (image_ID, 0, layername, width, height, type, drawable, pixel_rgn); return image_ID; }
static gint32 load_image (const gchar *uri, GimpRunMode run_mode, GError **error) { gint32 image_ID = -1; gboolean name_image = FALSE; gchar *tmpname; gboolean mapped = FALSE; tmpname = uri_backend_map_image (uri, run_mode); if (tmpname) { mapped = TRUE; } else { tmpname = get_temp_name (uri, &name_image); if (! uri_backend_load_image (uri, tmpname, run_mode, error)) return -1; } image_ID = gimp_file_load (run_mode, tmpname, tmpname); if (image_ID != -1) { if (mapped || name_image) gimp_image_set_filename (image_ID, uri); else gimp_image_set_filename (image_ID, ""); } else { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "%s", gimp_get_pdb_error ()); } if (! mapped) g_unlink (tmpname); g_free (tmpname); return image_ID; }
GimpPDBStatusType screenshot_osx_shoot (ScreenshotValues *shootvals, GdkScreen *screen, gint32 *image_ID) { gchar *mode = " "; gchar *delay = NULL; gchar *cursor = " "; gchar *command = NULL; switch (shootvals->shoot_type) { case SHOOT_REGION: mode = "-is"; break; case SHOOT_WINDOW: mode = "-iwo"; if (shootvals->decorate) mode = "-iw"; break; case SHOOT_ROOT: mode = " "; break; default: break; } delay = g_strdup_printf ("-T %i", shootvals->select_delay); if (shootvals->show_cursor) cursor = "-C"; command = g_strjoin (" ", "/usr/sbin/screencapture", mode, cursor, delay, "/tmp/screenshot.png", NULL); system ((const char *) command); g_free (command); g_free (delay); *image_ID = gimp_file_load (GIMP_RUN_NONINTERACTIVE, "/tmp/screenshot.png", "/tmp/screenshot.png"); gimp_image_set_filename (*image_ID, "screenshot.png"); return GIMP_PDB_SUCCESS; }
static gint32 load_image (const gchar *filename, GError **load_error) { gint32 image; gint32 layer; GdkPixbuf *pixbuf; gint width; gint height; GError *error = NULL; pixbuf = load_rsvg_pixbuf (filename, &load_vals, &error); if (! pixbuf) { /* Do not rely on librsvg setting GError on failure! */ g_set_error (load_error, error ? error->domain : 0, error ? error->code : 0, _("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), error ? error->message : _("Unknown reason")); g_clear_error (&error); return -1; } gimp_progress_init (_("Rendering SVG")); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); image = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (image); gimp_image_set_filename (image, filename); gimp_image_set_resolution (image, load_vals.resolution, load_vals.resolution); layer = gimp_layer_new_from_pixbuf (image, _("Rendered SVG"), pixbuf, 100, GIMP_NORMAL_MODE, 0.0, 1.0); gimp_image_insert_layer (image, layer, -1, 0); gimp_image_undo_enable (image); return image; }
static gint32 create_gimp_image (PSDimage *img_a, const gchar *filename) { gint32 image_id = -1; img_a->base_type = GIMP_RGB; /* Create gimp image */ IFDBG(2) g_debug ("Create image"); image_id = gimp_image_new (img_a->columns, img_a->rows, img_a->base_type); gimp_image_set_filename (image_id, filename); gimp_image_undo_disable (image_id); return image_id; }
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */ static gint32 create_new_image (const gchar *filename, guint width, guint height, GimpImageType gdtype, gint32 *layer_ID, GimpDrawable **drawable, GimpPixelRgn *pixel_rgn) { gint32 image_ID; GimpImageBaseType gitype; if ((gdtype == GIMP_GRAY_IMAGE) || (gdtype == GIMP_GRAYA_IMAGE)) gitype = GIMP_GRAY; else if ((gdtype == GIMP_INDEXED_IMAGE) || (gdtype == GIMP_INDEXEDA_IMAGE)) gitype = GIMP_INDEXED; else gitype = GIMP_RGB; image_ID = gimp_image_new (width, height, gitype); gimp_image_set_filename (image_ID, filename); gimp_image_undo_disable (image_ID); *layer_ID = gimp_layer_new (image_ID, _("Background"), width, height, gdtype, 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (image_ID, *layer_ID, -1, 0); if (drawable) { *drawable = gimp_drawable_get (*layer_ID); if (pixel_rgn != NULL) gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width, (*drawable)->height, TRUE, FALSE); } return image_ID; }
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; }
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */ static gint32 create_new_image (const gchar *filename, const gchar *layername, guint width, guint height, GimpImageBaseType type, GimpPrecision precision, gdouble xres, gdouble yres, gint32 *layer_ID) { gint32 image_ID; image_ID = gimp_image_new_with_precision (width, height, type, precision); gimp_image_undo_disable (image_ID); gimp_image_set_filename (image_ID, filename); gimp_image_set_resolution (image_ID, xres, yres); *layer_ID = create_new_layer (image_ID, 0, layername, width, height, type); return image_ID; }
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; }
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 (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; }
gboolean load_image(const gchar *filename, gint32 *image_ID, GError **error) { gboolean status = FALSE; gchar *indata = NULL; gsize indatalen; gint width; gint height; WebPMux *mux = NULL; WebPData wp_data; uint32_t flags; uint8_t *outdata = NULL; #ifdef GIMP_2_9 /* Initialize GEGL */ gegl_init(NULL, NULL); #endif do { /* Attempt to read the file contents from disk */ if (g_file_get_contents(filename, &indata, &indatalen, error) == FALSE) { break; } /* Validate WebP data, grabbing the width and height */ if (!WebPGetInfo(indata, indatalen, &width, &height)) { break; } /* Create a WebPMux from the contents of the file */ wp_data.bytes = (uint8_t*)indata; wp_data.size = indatalen; mux = WebPMuxCreate(&wp_data, 1); if (mux == NULL) { break; } /* Retrieve the features present */ if (WebPMuxGetFeatures(mux, &flags) != WEBP_MUX_OK) { break; } /* TODO: decode the image in "chunks" or "tiles" */ /* TODO: check if an alpha channel is present */ /* Create the new image and associated layer */ *image_ID = gimp_image_new(width, height, GIMP_RGB); #ifdef WEBP_0_5 if (flags & ANIMATION_FLAG) { int frames, i; /* Retrieve the number of frames */ WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &frames); /* Loop over each of the frames */ for (i = 0; i < frames; ++i) { WebPMuxFrameInfo frame = {0}; /* Retrieve the data for the frame */ if (WebPMuxGetFrame(mux, i, &frame) != WEBP_MUX_OK) { goto error; } /* Decode the frame */ outdata = WebPDecodeRGBA(frame.bitstream.bytes, frame.bitstream.size, &width, &height); /* Free the compressed data */ WebPDataClear(&frame.bitstream); if (!outdata) { goto error; } /* Create a layer for the frame */ char name[255]; snprintf(name, 255, "Frame %d", (i + 1)); if (create_layer(*image_ID, outdata, 0, (gchar*)name, width, height, frame.x_offset, frame.y_offset) == FALSE) { goto error; } } /* If all is well, jump *over* the error label - otherwise leave the loop and begin cleaning things up */ goto success; error: break; success: ; } else { #endif /* Attempt to decode the data as a WebP image */ outdata = WebPDecodeRGBA(indata, indatalen, &width, &height); if (!outdata) { break; } /* Create a single layer */ status = create_layer(*image_ID, outdata, 0, "Background", width, height, 0, 0); #ifdef WEBP_0_5 } #ifdef GIMP_2_9 /* Load a color profile if one was provided */ if (flags & ICCP_FLAG) { WebPData icc_profile; GimpColorProfile *profile; /* Load the ICC profile from the file */ WebPMuxGetChunk(mux, "ICCP", &icc_profile); /* Have Gimp load the color profile */ profile = gimp_color_profile_new_from_icc_profile( icc_profile.bytes, icc_profile.size, NULL); if (profile) { gimp_image_set_color_profile(image_ID, profile); g_object_unref(profile); } } #endif #endif /* Set the filename for the image */ gimp_image_set_filename(*image_ID, filename); } while(0); /* Delete the mux object */ if (mux) { WebPMuxDelete(mux); } /* Free the data read from disk */ if (indata) { g_free(indata); } return status; }
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; gint32 image_ID; gint32 drawable_ID; gint32 orig_image_ID; GimpParasite *parasite; 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; preview_image_ID = -1; preview_layer_ID = -1; has_metadata = FALSE; orig_quality = 0; orig_subsmp = JPEG_SUPSAMPLING_2x2_1x1_1x1; num_quant_tables = 0; if (strcmp (name, LOAD_PROC) == 0) { switch (run_mode) { case GIMP_RUN_INTERACTIVE: case GIMP_RUN_WITH_LAST_VALS: gimp_ui_init (PLUG_IN_BINARY, FALSE); load_interactive = TRUE; break; default: load_interactive = FALSE; break; } image_ID = load_image (param[1].data.d_string, run_mode, FALSE, &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; } } #ifdef HAVE_EXIF 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 = 0; gint height = 0; image_ID = 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; } } } #endif /* HAVE_EXIF */ else if (strcmp (name, SAVE_PROC) == 0) { image_ID = orig_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: gimp_ui_init (PLUG_IN_BINARY, FALSE); export = gimp_export_image (&image_ID, &drawable_ID, NULL, (GIMP_EXPORT_CAN_HANDLE_RGB | GIMP_EXPORT_CAN_HANDLE_GRAY)); switch (export) { case GIMP_EXPORT_EXPORT: { gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1, NULL, NULL, NULL); if (tmp) { gimp_image_set_filename (image_ID, tmp); g_free (tmp); } display_ID = -1; } break; case GIMP_EXPORT_IGNORE: break; case GIMP_EXPORT_CANCEL: values[0].data.d_status = GIMP_PDB_CANCEL; return; break; } break; default: break; }
static gint32 load_image (PopplerDocument *doc, const gchar *filename, GimpRunMode run_mode, GimpPageSelectorTarget target, guint32 resolution, PdfSelectedPages *pages) { gint32 image_ID = 0; gint32 *images = NULL; gint i; gdouble scale; gdouble doc_progress = 0; if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) images = g_new0 (gint32, pages->n_pages); gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); scale = resolution / gimp_unit_get_factor (GIMP_UNIT_POINT); /* read the file */ for (i = 0; i < pages->n_pages; i++) { PopplerPage *page; gchar *page_label; gdouble page_width; gdouble page_height; GdkPixbuf *buf; gint width; gint height; page = poppler_document_get_page (doc, pages->pages[i]); poppler_page_get_size (page, &page_width, &page_height); width = page_width * scale; height = page_height * scale; g_object_get (G_OBJECT (page), "label", &page_label, NULL); if (! image_ID) { gchar *name; image_ID = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (image_ID); if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) name = g_strdup_printf (_("%s-%s"), filename, page_label); else name = g_strdup_printf (_("%s-pages"), filename); gimp_image_set_filename (image_ID, name); g_free (name); gimp_image_set_resolution (image_ID, resolution, resolution); } buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf); layer_from_pixbuf (image_ID, page_label, i, buf, doc_progress, 1.0 / pages->n_pages); g_free (page_label); g_object_unref (buf); doc_progress = (double) (i + 1) / pages->n_pages; gimp_progress_update (doc_progress); if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) { images[i] = image_ID; gimp_image_undo_enable (image_ID); gimp_image_clean_all (image_ID); image_ID = 0; } } if (image_ID) { gimp_image_undo_enable (image_ID); gimp_image_clean_all (image_ID); } if (target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) { if (run_mode != GIMP_RUN_NONINTERACTIVE) { /* Display images in reverse order. The last will be * displayed by GIMP itself */ for (i = pages->n_pages - 1; i > 0; i--) gimp_display_new (images[i]); } image_ID = images[0]; g_free (images); } return image_ID; }
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); }
/* * 'load_image()' - Load a WMF image into a new image window. */ static gint32 load_image (const gchar *filename, GError **error) { gint32 image; gint32 layer; GimpDrawable *drawable; guchar *pixels; GimpPixelRgn pixel_rgn; guint width, height; guint rowstride; guint count = 0; guint done = 0; gpointer pr; pixels = wmf_load_file (filename, &width, &height, error); if (! pixels) return -1; rowstride = width * 4; gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); image = gimp_image_new (width, height, GIMP_RGB); gimp_image_set_filename (image, filename); gimp_image_set_resolution (image, load_vals.resolution, load_vals.resolution); layer = gimp_layer_new (image, _("Rendered WMF"), width, height, GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE); drawable = gimp_drawable_get (layer); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, TRUE, FALSE); for (pr = gimp_pixel_rgns_register (1, &pixel_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { const guchar *src = pixels + pixel_rgn.y * rowstride + pixel_rgn.x * 4; guchar *dest = pixel_rgn.data; gint y; for (y = 0; y < pixel_rgn.h; y++) { memcpy (dest, src, pixel_rgn.w * pixel_rgn.bpp); src += rowstride; dest += pixel_rgn.rowstride; } done += pixel_rgn.h * pixel_rgn.w; if (count++ % 16 == 0) gimp_progress_update ((gdouble) done / (width * height)); } g_free (pixels); gimp_drawable_detach (drawable); gimp_progress_update (1.0); /* Tell GIMP to display the image. */ gimp_image_insert_layer (image, layer, -1, 0); gimp_drawable_flush (drawable); return image; }
static gint32 load_image (char *filename) { FILE *fp; gint32 image_ID = -1; gint32 layer_ID; GPixelRgn pixel_rgn; GDrawable *drawable; guchar *data; GDrawableType dtype; GImageType itype; struct stat st; int width, height, bpp=0; int i, j, k; int pelbytes, tileheight, wbytes, bsize, npels, pels, ncols, npals; int badread; gushort tmpval; if (stat (filename,&st) == -1) return -1; fp = fopen (filename, "rb"); if (!fp) return -1; bs = (bs_header_t *) g_malloc (st.st_size); fread (bs,st.st_size,1,fp); fclose (fp); if (bs->magic != BS_MAGIC) { printf("not a .bs file\n"); return -1; } gimp_get_data ("bs_width",&width); gimp_get_data ("bs_height",&height); printf("%d x %d\n",width,height); itype = RGB; dtype = RGB_IMAGE; image_ID = gimp_image_new (width, height, itype); gimp_image_set_filename (image_ID, filename); layer_ID = gimp_layer_new (image_ID, "Background", width, height, dtype, 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, width, height, TRUE, FALSE); data = (guchar *) g_malloc (width * height * 3); bs_init(); bs_decode_rgb24 (data,bs,width,height,0); printf ("image decoded!\n"); gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, 0, width, height); g_free (data); gimp_drawable_flush (drawable); gimp_drawable_detach (drawable); return image_ID; }
gint32 load_djvu (const gchar * filename, GimpRunMode runmode, gboolean preview) { GimpPixelRgn rgn_in; GimpDrawable *drawable; gint32 volatile image_ID; gint32 layer_ID; int x1, y1, x2, y2, width, height; unsigned char *src = NULL; int file_length; ctx = ddjvu_context_create("gimp"); // doc = ddjvu_document_create_by_filename(ctx,filename, TRUE); while (! ddjvu_document_decoding_done(doc)) handle(TRUE); i = ddjvu_document_get_pagenum(doc); dialog( &pageno ,i); //processing the page page = ddjvu_page_create_by_pageno(doc, pageno-1); while (! ddjvu_page_decoding_done(page)) handle(TRUE); if (ddjvu_page_decoding_error(page)) { fprintf(stderr,"unexpected error "); exit(10); } // ddjvu variables ddjvu_rect_t prect; ddjvu_rect_t rrect; ddjvu_format_style_t style; ddjvu_render_mode_t mode; ddjvu_format_t *fmt; int iw = ddjvu_page_get_width(page); int ih = ddjvu_page_get_height(page); int dpi = ddjvu_page_get_resolution(page); ddjvu_page_type_t type = ddjvu_page_get_type(page); char *image = 0; int rowsize; //end of ddjvu variables style= DDJVU_FORMAT_RGB24; mode=DDJVU_RENDER_COLOR; fmt = ddjvu_format_create(style, 0, 0); ddjvu_format_set_row_order(fmt, 1); prect.w = iw; prect.h = ih; prect.x = 0; prect.y = 0; flag_scale=150; prect.w = (unsigned int) (iw * flag_scale) / dpi; prect.h = (unsigned int) (ih * flag_scale) / dpi; rrect = prect; rowsize = (rrect.w *3); image = (char*)malloc(rowsize * rrect.h); //generating page ddjvu_page_render(page, mode, &prect, &rrect, fmt, rowsize, image); ddjvu_page_release(page); char *s =image; /* create output image */ width = prect.w; height = prect.h; x1 = 0; y1 = 0; x2 = prect.w; y2 = prect.h; image_ID = gimp_image_new (width, height, GIMP_RGB); layer_ID = gimp_layer_new (image_ID, _("Background"), width, height, GIMP_RGB, 100, GIMP_NORMAL_MODE); gimp_image_add_layer (image_ID, layer_ID, 0); drawable = gimp_drawable_get (layer_ID); // initializes the drawable gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, x2 - x1, y2 - y1, TRUE, TRUE); gimp_pixel_rgn_set_rect (&rgn_in, image, 0, 0, width, height); //g_free (buf); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1); gimp_image_set_filename (image_ID, filename); return image_ID; image =NULL; //not handling any error if (doc) ddjvu_document_release(doc); if (ctx) ddjvu_context_release(ctx); }
GimpPDBStatusType screenshot_osx_shoot (ScreenshotValues *shootvals, GdkScreen *screen, gint32 *image_ID, GError **error) { const gchar *mode = " "; const gchar *cursor = " "; gchar *delay = NULL; gchar *filename; gchar *quoted; gchar *command = NULL; switch (shootvals->shoot_type) { case SHOOT_REGION: mode = "-is"; break; case SHOOT_WINDOW: if (shootvals->decorate) mode = "-iwo"; else mode = "-iw"; break; case SHOOT_ROOT: mode = " "; if (shootvals->show_cursor) cursor = "-C"; break; default: g_return_val_if_reached (GIMP_PDB_CALLING_ERROR); break; } delay = g_strdup_printf ("-T %i", shootvals->select_delay); filename = gimp_temp_name ("png"); quoted = g_shell_quote (filename); command = g_strjoin (" ", "/usr/sbin/screencapture", mode, cursor, delay, quoted, NULL); g_free (quoted); g_free (delay); if (system ((const char *) command) == EXIT_SUCCESS) { *image_ID = gimp_file_load (GIMP_RUN_NONINTERACTIVE, filename, filename); gimp_image_set_filename (*image_ID, "screenshot.png"); g_unlink (filename); g_free (filename); g_free (command); return GIMP_PDB_SUCCESS; } g_free (command); g_free (filename); return GIMP_PDB_EXECUTION_ERROR; }
static gint32 ReadImage (FILE *fd, const gchar *filename, gint len, gint height, CMap cmap, gint ncols, gint format, gint interlace, gint number, guint leftpos, guint toppos, guint screenwidth, guint screenheight) { static gint32 image_ID = -1; static gint frame_number = 1; gint32 layer_ID; GimpPixelRgn pixel_rgn; GimpDrawable *drawable; guchar *dest, *temp; guchar c; gint xpos = 0, ypos = 0, pass = 0; gint cur_progress, max_progress; gint v; gint i, j; gchar *framename; gchar *framename_ptr; gboolean alpha_frame = FALSE; static gint previous_disposal; /* Guard against bogus frame size */ if (len < 1 || height < 1) { g_message ("Bogus frame dimensions"); return -1; } /* ** Initialize the Compression routines */ if (! ReadOK (fd, &c, 1)) { g_message ("EOF / read error on image data"); return -1; } if (LZWReadByte (fd, TRUE, c) < 0) { g_message ("Error while reading"); return -1; } if (frame_number == 1) { /* Guard against bogus logical screen size values */ if (screenwidth == 0) screenwidth = len; if (screenheight == 0) screenheight = height; image_ID = gimp_image_new (screenwidth, screenheight, GIMP_INDEXED); gimp_image_set_filename (image_ID, filename); for (i = 0, j = 0; i < ncols; i++) { used_cmap[0][i] = gimp_cmap[j++] = cmap[0][i]; used_cmap[1][i] = gimp_cmap[j++] = cmap[1][i]; used_cmap[2][i] = gimp_cmap[j++] = cmap[2][i]; } gimp_image_set_colormap (image_ID, gimp_cmap, ncols); if (Gif89.delayTime < 0) framename = g_strdup (_("Background")); else framename = g_strdup_printf (_("Background (%d%s)"), 10 * Gif89.delayTime, "ms"); previous_disposal = Gif89.disposal; if (Gif89.transparent == -1) { layer_ID = gimp_layer_new (image_ID, framename, len, height, GIMP_INDEXED_IMAGE, 100, GIMP_NORMAL_MODE); } else { layer_ID = gimp_layer_new (image_ID, framename, len, height, GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE); alpha_frame=TRUE; } g_free (framename); } else /* NOT FIRST FRAME */ { gimp_progress_set_text_printf (_("Opening '%s' (frame %d)"), gimp_filename_to_utf8 (filename), frame_number); gimp_progress_pulse (); /* If the colourmap is now different, we have to promote to RGB! */ if (! promote_to_rgb) { for (i = 0; i < ncols; i++) { if ((used_cmap[0][i] != cmap[0][i]) || (used_cmap[1][i] != cmap[1][i]) || (used_cmap[2][i] != cmap[2][i])) { /* Everything is RGB(A) from now on... sigh. */ promote_to_rgb = TRUE; /* Promote everything we have so far into RGB(A) */ #ifdef GIFDEBUG g_print ("GIF: Promoting image to RGB...\n"); #endif gimp_image_convert_rgb (image_ID); break; } } } if (Gif89.delayTime < 0) framename = g_strdup_printf (_("Frame %d"), frame_number); else framename = g_strdup_printf (_("Frame %d (%d%s)"), frame_number, 10 * Gif89.delayTime, "ms"); switch (previous_disposal) { case 0x00: break; /* 'don't care' */ case 0x01: framename_ptr = framename; framename = g_strconcat (framename, " (combine)", NULL); g_free (framename_ptr); break; case 0x02: framename_ptr = framename; framename = g_strconcat (framename, " (replace)", NULL); g_free (framename_ptr); break; case 0x03: /* Rarely-used, and unhandled by many loaders/players (including GIMP: we treat as 'combine' mode). */ framename_ptr = framename; framename = g_strconcat (framename, " (combine) (!)", NULL); g_free (framename_ptr); break; case 0x04: /* I've seen a composite of this type. stvo_online_banner2.gif */ case 0x05: case 0x06: /* I've seen a composite of this type. bn31.Gif */ case 0x07: framename_ptr = framename; framename = g_strconcat (framename, " (unknown disposal)", NULL); g_free (framename_ptr); g_message (_("GIF: Undocumented GIF composite type %d is " "not handled. Animation might not play or " "re-save perfectly."), previous_disposal); break; default: g_message ("Disposal word got corrupted. Bug."); break; } previous_disposal = Gif89.disposal; layer_ID = gimp_layer_new (image_ID, framename, len, height, promote_to_rgb ? GIMP_RGBA_IMAGE : GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE); alpha_frame = TRUE; g_free (framename); } frame_number++; gimp_image_insert_layer (image_ID, layer_ID, -1, 0); gimp_layer_translate (layer_ID, (gint) leftpos, (gint) toppos); drawable = gimp_drawable_get (layer_ID); cur_progress = 0; max_progress = height; if (alpha_frame) dest = (guchar *) g_malloc (len * height * (promote_to_rgb ? 4 : 2)); else dest = (guchar *) g_malloc (len * height); #ifdef GIFDEBUG g_print ("GIF: reading %d by %d%s GIF image, ncols=%d\n", len, height, interlace ? " interlaced" : "", ncols); #endif if (! alpha_frame && promote_to_rgb) { /* I don't see how one would easily construct a GIF in which this could happen, but it's a mad mad world. */ g_message ("Ouch! Can't handle non-alpha RGB frames.\n" "Please file a bug report in GIMP's bugzilla."); gimp_quit (); } while ((v = LZWReadByte (fd, FALSE, c)) >= 0) { if (alpha_frame) { if (((guchar) v > highest_used_index) && !(v == Gif89.transparent)) highest_used_index = (guchar) v; if (promote_to_rgb) { temp = dest + ( (ypos * len) + xpos ) * 4; *(temp ) = (guchar) cmap[0][v]; *(temp+1) = (guchar) cmap[1][v]; *(temp+2) = (guchar) cmap[2][v]; *(temp+3) = (guchar) ((v == Gif89.transparent) ? 0 : 255); } else { temp = dest + ( (ypos * len) + xpos ) * 2; *temp = (guchar) v; *(temp+1) = (guchar) ((v == Gif89.transparent) ? 0 : 255); } } else { if ((guchar) v > highest_used_index) highest_used_index = (guchar) v; temp = dest + (ypos * len) + xpos; *temp = (guchar) v; } xpos++; if (xpos == len) { xpos = 0; if (interlace) { switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { pass++; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; default: goto fini; } } } else { ypos++; } if (frame_number == 1) { cur_progress++; if ((cur_progress % 16) == 0) gimp_progress_update ((gdouble) cur_progress / (gdouble) max_progress); } } if (ypos >= height) break; } fini: if (LZWReadByte (fd, FALSE, c) >= 0) g_print ("GIF: too much input data, ignoring extra...\n"); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, 0, drawable->width, drawable->height); g_free (dest); gimp_drawable_flush (drawable); gimp_drawable_detach (drawable); return image_ID; }
static void guillotine (gint32 image_ID) { gint guide; gint image_width; gint image_height; gboolean guides_found = FALSE; GList *hguides, *hg; GList *vguides, *vg; image_width = gimp_image_width (image_ID); image_height = gimp_image_height (image_ID); hguides = g_list_append (NULL, GINT_TO_POINTER (0)); hguides = g_list_append (hguides, GINT_TO_POINTER (image_height)); vguides = g_list_append (NULL, GINT_TO_POINTER (0)); vguides = g_list_append (vguides, GINT_TO_POINTER (image_width)); for (guide = gimp_image_find_next_guide (image_ID, 0); guide > 0; guide = gimp_image_find_next_guide (image_ID, guide)) { gint position = gimp_image_get_guide_position (image_ID, guide); switch (gimp_image_get_guide_orientation (image_ID, guide)) { case GIMP_ORIENTATION_HORIZONTAL: if (! g_list_find (hguides, GINT_TO_POINTER (position))) { hguides = g_list_insert_sorted (hguides, GINT_TO_POINTER (position), guide_sort_func); guides_found = TRUE; } break; case GIMP_ORIENTATION_VERTICAL: if (! g_list_find (vguides, GINT_TO_POINTER (position))) { vguides = g_list_insert_sorted (vguides, GINT_TO_POINTER (position), guide_sort_func); guides_found = TRUE; } break; case GIMP_ORIENTATION_UNKNOWN: g_assert_not_reached (); break; } } if (guides_found) { gchar *filename; gint h, v, hpad, vpad; gint x, y; gchar *hformat; gchar *format; filename = gimp_image_get_filename (image_ID); if (!filename) filename = g_strdup (_("Untitled")); /* get the number horizontal and vertical slices */ h = g_list_length (hguides); v = g_list_length (vguides); /* need the number of digits of h and v for the padding */ hpad = log10(h) + 1; vpad = log10(v) + 1; /* format for the x-y coordinates in the filename */ hformat = g_strdup_printf ("%%0%i", MAX (hpad, vpad)); format = g_strdup_printf ("-%si-%si", hformat, hformat); /* Do the actual dup'ing and cropping... this isn't a too naive a * way to do this since we got copy-on-write tiles, either. */ for (y = 0, hg = hguides; hg && hg->next; y++, hg = hg->next) { for (x = 0, vg = vguides; vg && vg->next; x++, vg = vg->next) { gint32 new_image = gimp_image_duplicate (image_ID); GString *new_filename; gchar *fileextension; gchar *fileindex; gint pos; if (new_image == -1) { g_warning ("Couldn't create new image."); return; } gimp_image_undo_disable (new_image); gimp_image_crop (new_image, GPOINTER_TO_INT (vg->next->data) - GPOINTER_TO_INT (vg->data), GPOINTER_TO_INT (hg->next->data) - GPOINTER_TO_INT (hg->data), GPOINTER_TO_INT (vg->data), GPOINTER_TO_INT (hg->data)); new_filename = g_string_new (filename); /* show the rough coordinates of the image in the title */ fileindex = g_strdup_printf (format, x, y); /* get the position of the file extension - last . in filename */ fileextension = strrchr (new_filename->str, '.'); pos = fileextension - new_filename->str; /* insert the coordinates before the extension */ g_string_insert (new_filename, pos, fileindex); g_free (fileindex); gimp_image_set_filename (new_image, new_filename->str); g_string_free (new_filename, TRUE); while ((guide = gimp_image_find_next_guide (new_image, 0))) gimp_image_delete_guide (new_image, guide); gimp_image_undo_enable (new_image); gimp_display_new (new_image); } } g_free (filename); g_free (hformat); g_free (format); } g_list_free (hguides); g_list_free (vguides); }
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; }