Commit 99e575d1 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer
Browse files

fixed temp_buf_copy() and temp_buf_to_[color|gray]() to (1) not crash and

2002-04-16  Michael Natterer  <mitch@gimp.org>

	* app/base/temp-buf.c: fixed temp_buf_copy() and
	temp_buf_to_[color|gray]() to (1) not crash and (2) to assume the
	correct pixelformat. Bugs were never noticed because the code was
	never used until today...

	* app/core/gimpviewable.c (gimp_viewable_get_new_preview_pixbuf):
	use temp_buf_copy() to convert GRAY* TempBufs to RGB* before
	creating the pixbuf.

	* app/app_procs.c: don't try to open command line images if the
	filename could not be converted to an URI.

	* app/file/file-open.c
	* app/file/file-save.c: use g_file_test() instead of stat().

	* app/file/file-utils.[ch]: cleanup, changed
	file_utils_filename_to_uri() to take a list of procs, not a Gimp
	pointer.

	* app/core/gimpimage.c: changed accordingly.

	* app/core/gimpimagefile.[ch]: implemented thumbnail saving
	following the thumbnail standard v0.5 (the implementation is not
	yet fully standard compliant).

	* app/gui/file-open-dialog.c: use the new thubmnail functions and
	removed all .xvpics code. Not finished yet...

	* app/core/gimpdocuments.c
	* app/widgets/gimpdocumentview.c: changed accordingly.

	* tools/pdbgen/pdb/fileops.pdb (file_save_thumbnail): set "success"
	correctly.

	* app/pdb/fileops_cmds.c: regenerated.
parent 3da95025
2002-04-16 Michael Natterer <mitch@gimp.org>
* app/base/temp-buf.c: fixed temp_buf_copy() and
temp_buf_to_[color|gray]() to (1) not crash and (2) to assume the
correct pixelformat. Bugs were never noticed because the code was
never used until today...
* app/core/gimpviewable.c (gimp_viewable_get_new_preview_pixbuf):
use temp_buf_copy() to convert GRAY* TempBufs to RGB* before
creating the pixbuf.
* app/app_procs.c: don't try to open command line images if the
filename could not be converted to an URI.
* app/file/file-open.c
* app/file/file-save.c: use g_file_test() instead of stat().
* app/file/file-utils.[ch]: cleanup, changed
file_utils_filename_to_uri() to take a list of procs, not a Gimp
pointer.
* app/core/gimpimage.c: changed accordingly.
* app/core/gimpimagefile.[ch]: implemented thumbnail saving
following the thumbnail standard v0.5 (the implementation is not
yet fully standard compliant).
* app/gui/file-open-dialog.c: use the new thubmnail functions and
removed all .xvpics code. Not finished yet...
* app/core/gimpdocuments.c
* app/widgets/gimpdocumentview.c: changed accordingly.
* tools/pdbgen/pdb/fileops.pdb (file_save_thumbnail): set "success"
correctly.
* app/pdb/fileops_cmds.c: regenerated.
2002-04-16 Sven Neumann <sven@gimp.org>
 
* app/widgets/gimppreview.c (gimp_preview_expose_event): don't draw
......
......@@ -184,7 +184,8 @@ app_init (gint gimp_argc,
GError *error = NULL;
gchar *uri;
uri = file_utils_filename_to_uri (the_gimp, gimp_argv[i], &error);
uri = file_utils_filename_to_uri (the_gimp->load_procs,
gimp_argv[i], &error);
if (! uri)
{
......@@ -192,10 +193,12 @@ app_init (gint gimp_argc,
error->message);
g_error_free (error);
}
else
{
file_open_with_display (the_gimp, uri);
file_open_with_display (the_gimp, uri);
g_free (uri);
g_free (uri);
}
}
}
}
......
......@@ -71,46 +71,72 @@ temp_buf_to_color (TempBuf *src_buf,
{
guchar *src;
guchar *dest;
glong num_bytes;
glong num_pixels;
src = temp_buf_data (src_buf);
src = temp_buf_data (src_buf);
dest = temp_buf_data (dest_buf);
num_bytes = src_buf->width * src_buf->height;
num_pixels = src_buf->width * src_buf->height;
while (num_bytes--)
if (dest_buf->bytes == 4)
{
guchar tmpch;
*dest++ = *src++; /* alpha channel */
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
while (num_pixels--)
{
guchar tmpch;
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
*dest++ = *src++; /* alpha channel */
}
}
else
{
while (num_pixels--)
{
guchar tmpch;
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
}
}
}
static void
temp_buf_to_gray (TempBuf *src_buf,
TempBuf *dest_buf)
{
guchar *src;
guchar *dest;
glong num_bytes;
glong num_pixels;
gfloat pix;
src = temp_buf_data (src_buf);
src = temp_buf_data (src_buf);
dest = temp_buf_data (dest_buf);
num_bytes = src_buf->width * src_buf->height;
num_pixels = src_buf->width * src_buf->height;
while (num_bytes--)
if (dest_buf->bytes == 2)
{
*dest++ = src[0]; /* alpha channel */
while (num_pixels--)
{
pix = INTENSITY (src[0], src[1], src[2]);
*dest++ = (guchar) pix;
*dest++ = src[3]; /* alpha channel */
pix = INTENSITY (src[1], src[2], src[3]);
*dest++ = (guchar) pix;
src += 4;
}
}
else
{
while (num_pixels--)
{
pix = INTENSITY (src[0], src[1], src[2]);
*dest++ = (guchar) pix;
src += 4;
src += 3;
}
}
}
......@@ -268,40 +294,38 @@ TempBuf *
temp_buf_copy (TempBuf *src,
TempBuf *dest)
{
TempBuf *new;
glong length;
glong length;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (! dest || (dest->width == src->width &&
dest->height == src->height), NULL);
if (! dest)
{
dest = temp_buf_new (src->width, src->height, src->bytes, 0, 0, NULL);
}
if (!dest)
if (src->bytes != dest->bytes)
{
new = temp_buf_new (src->width, src->height, src->bytes, 0, 0, NULL);
if (src->bytes == 4 && dest->bytes == 2) /* RGBA -> GRAYA */
temp_buf_to_gray (src, dest);
else if (src->bytes == 3 && dest->bytes == 1) /* RGB -> GRAY */
temp_buf_to_gray (src, dest);
else if (src->bytes == 2 && dest->bytes == 4) /* GRAYA -> RGBA */
temp_buf_to_color (src, dest);
else if (src->bytes == 1 && dest->bytes == 3) /* GRAYA -> RGBA */
temp_buf_to_color (src, dest);
else
g_warning ("temp_buf_copy(): unimplemented color conversion");
}
else
{
new = dest;
if (dest->width != src->width || dest->height != src->height)
g_message ("In temp_buf_copy, the widths or heights don't match.");
/* The temp buf is smart, and can translate between color and gray */
/* (only necessary if not we allocated it */
if (src->bytes != new->bytes)
{
if (src->bytes == 4) /* RGB color */
temp_buf_to_gray (src, new);
else if (src->bytes == 2) /* grayscale */
temp_buf_to_color (src, new);
else
g_message ("Cannot convert from indexed color.");
return new;
}
/* make the copy */
length = src->width * src->height * src->bytes;
memcpy (temp_buf_data (dest), temp_buf_data (src), length);
}
/* make the copy */
length = src->width * src->height * src->bytes;
memcpy (temp_buf_data (new), temp_buf_data (src), length);
return new;
return dest;
}
TempBuf *
......
......@@ -111,6 +111,7 @@ gimp_documents_load (Gimp *gimp)
}
imagefile = gimp_imagefile_new (uri);
gimp_imagefile_update (imagefile);
g_free (uri);
......
......@@ -111,6 +111,7 @@ gimp_documents_load (Gimp *gimp)
}
imagefile = gimp_imagefile_new (uri);
gimp_imagefile_update (imagefile);
g_free (uri);
......
......@@ -111,6 +111,7 @@ gimp_documents_load (Gimp *gimp)
}
imagefile = gimp_imagefile_new (uri);
gimp_imagefile_update (imagefile);
g_free (uri);
......
......@@ -1036,7 +1036,8 @@ gimp_image_set_filename (GimpImage *gimage,
{
gchar *uri;
uri = file_utils_filename_to_uri (gimage->gimp, filename, NULL);
uri = file_utils_filename_to_uri (gimage->gimp->load_procs, filename,
NULL);
gimp_image_set_uri (gimage, uri);
......
......@@ -42,11 +42,25 @@
#include "base/temp-buf.h"
#include "gimp.h"
#include "gimpcontainer.h"
#include "gimpimage.h"
#include "gimpimagefile.h"
#include "gimpmarshal.h"
#include "file/file-open.h"
#include "app_procs.h"
#include "libgimp/gimpintl.h"
enum
{
INFO_CHANGED,
LAST_SIGNAL
};
typedef struct
{
const gchar *dirname;
......@@ -60,32 +74,38 @@ static const ThumbnailSize thumb_sizes[] =
};
static void gimp_imagefile_class_init (GimpImagefileClass *klass);
static void gimp_imagefile_init (GimpImagefile *imagefile);
static void gimp_imagefile_name_changed (GimpObject *object);
static void gimp_imagefile_set_info (GimpImagefile *imagefile,
gint width,
gint height,
gint size);
static TempBuf * gimp_imagefile_get_new_preview (GimpViewable *viewable,
gint width,
gint height);
static void gimp_imagefile_class_init (GimpImagefileClass *klass);
static void gimp_imagefile_init (GimpImagefile *imagefile);
static void gimp_imagefile_name_changed (GimpObject *object);
static void gimp_imagefile_set_info (GimpImagefile *imagefile,
gint width,
gint height,
gint size);
static TempBuf * gimp_imagefile_get_new_preview (GimpViewable *viewable,
gint width,
gint height);
static TempBuf * gimp_imagefile_read_png_thumb (GimpImagefile *imagefile,
gint size);
static const gchar * gimp_imagefile_png_thumb_name (const gchar *uri);
static gchar * gimp_imagefile_png_thumb_path (const gchar *uri,
gint size);
static gchar * gimp_imagefile_find_png_thumb (const gchar *uri,
time_t image_mtime,
gint size,
time_t *thumb_mtime);
static TempBuf * gimp_imagefile_read_png_thumb (GimpImagefile *imagefile,
gint size);
static gchar * gimp_imagefile_png_thumb_name (const gchar *uri,
gint mtime,
gint size);
static TempBuf * gimp_imagefile_read_xv_thumb (GimpImagefile *imagefile);
static guchar * readXVThumb (const gchar *filename,
gint *width,
gint *height,
gchar **imginfo);
static TempBuf * gimp_imagefile_read_xv_thumb (GimpImagefile *imagefile);
static guchar * readXVThumb (const gchar *filename,
gint *width,
gint *height,
gchar **imginfo);
static gboolean gimp_imagefile_test (const gchar *filename,
time_t *mtime);
static gboolean gimp_image_file_test (const gchar *filename,
gint *mtime);
static guint gimp_imagefile_signals[LAST_SIGNAL] = { 0 };
static GimpViewableClass *parent_class = NULL;
......@@ -129,6 +149,15 @@ gimp_imagefile_class_init (GimpImagefileClass *klass)
object_class = GIMP_OBJECT_CLASS (klass);
viewable_class = GIMP_VIEWABLE_CLASS (klass);
gimp_imagefile_signals[INFO_CHANGED] =
g_signal_new ("info_changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpImagefileClass, info_changed),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
object_class->name_changed = gimp_imagefile_name_changed;
viewable_class->get_new_preview = gimp_imagefile_get_new_preview;
}
......@@ -136,31 +165,215 @@ gimp_imagefile_class_init (GimpImagefileClass *klass)
static void
gimp_imagefile_init (GimpImagefile *imagefile)
{
imagefile->width = -1;
imagefile->height = -1;
imagefile->size = -1;
imagefile->width = -1;
imagefile->height = -1;
imagefile->size = -1;
imagefile->image_state = GIMP_IMAGEFILE_STATE_UNKNOWN;
imagefile->image_mtime = 0;
imagefile->thumb_state = GIMP_IMAGEFILE_STATE_UNKNOWN;
imagefile->thumb_mtime = 0;
}
GimpImagefile *
gimp_imagefile_new (const gchar *filename)
gimp_imagefile_new (const gchar *uri)
{
GimpImagefile *imagefile;
imagefile = GIMP_IMAGEFILE (g_object_new (GIMP_TYPE_IMAGEFILE, NULL));
if (filename)
gimp_object_set_name (GIMP_OBJECT (imagefile), filename);
if (uri)
gimp_object_set_name (GIMP_OBJECT (imagefile), uri);
return imagefile;
}
void
gimp_imagefile_update (GimpImagefile *imagefile)
{
const gchar *uri;
g_return_if_fail (GIMP_IS_IMAGEFILE (imagefile));
uri = gimp_object_get_name (GIMP_OBJECT (imagefile));
if (uri)
{
gchar *filename = NULL;
gchar *thumbname = NULL;
filename = g_filename_from_uri (uri, NULL, NULL);
imagefile->image_mtime = 0;
if (! filename)
{
/* no thumbnails of remote images :-( */
imagefile->image_state = GIMP_IMAGEFILE_STATE_REMOTE;
goto cleanup;
}
if (! gimp_imagefile_test (filename, &imagefile->image_mtime))
{
imagefile->image_state = GIMP_IMAGEFILE_STATE_NOT_FOUND;
goto cleanup;
}
imagefile->image_state = GIMP_IMAGEFILE_STATE_EXISTS;
/* found the image, now look for the thumbnail */
imagefile->thumb_mtime = 0;
thumbname = gimp_imagefile_find_png_thumb (uri,
imagefile->image_mtime,
128,
&imagefile->thumb_mtime);
if (! thumbname)
{
imagefile->thumb_state = GIMP_IMAGEFILE_STATE_NOT_FOUND;
goto cleanup;
}
imagefile->thumb_state = GIMP_IMAGEFILE_STATE_EXISTS;
cleanup:
g_free (filename);
g_free (thumbname);
{
GimpViewable *viewable;
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (imagefile));
viewable = (GimpViewable *)
gimp_container_get_child_by_name (the_gimp->documents,
uri);
if (GIMP_IS_VIEWABLE (viewable) &&
(viewable != GIMP_VIEWABLE (imagefile)))
gimp_viewable_invalidate_preview (viewable);
}
}
}
void
gimp_imagefile_create_thumbnail (GimpImagefile *imagefile)
{
const gchar *uri;
g_return_if_fail (GIMP_IS_IMAGEFILE (imagefile));
uri = gimp_object_get_name (GIMP_OBJECT (imagefile));
if (uri)
{
GimpImage *gimage = NULL;
GimpPDBStatusType dummy;
gchar *filename;
time_t mtime;
filename = g_filename_from_uri (uri, NULL, NULL);
/* no thumbnails of remote images :-( */
if (! filename)
return;
if (gimp_imagefile_test (filename, &mtime))
{
gimage = file_open_image (the_gimp,
uri,
uri,
NULL,
NULL,
GIMP_RUN_NONINTERACTIVE,
&dummy);
}
g_free (filename);
if (gimage)
{
gchar *temp_name;
gchar *thumb_name;
GdkPixbuf *pixbuf;
gint w, h;
gchar *w_str;
gchar *h_str;
gchar *t_str;
if (gimage->width <= 128 && gimage->height <= 128)
{
w = gimage->width;
h = gimage->height;
}
else
{
if (gimage->width < gimage->height)
{
h = 128;
w = MAX (1, (128 * gimage->width) / gimage->height);
}
else
{
w = 128;
h = MAX (1, (128 * gimage->height) / gimage->width);
}
}
pixbuf = gimp_viewable_get_new_preview_pixbuf (GIMP_VIEWABLE (gimage),
w, h);
temp_name = NULL;
thumb_name = gimp_imagefile_png_thumb_path (uri, 128);
w_str = g_strdup_printf ("%d", gimage->width);
h_str = g_strdup_printf ("%d", gimage->height);
t_str = g_strdup_printf ("%ld", mtime);
gdk_pixbuf_save (pixbuf, thumb_name, "png", NULL,
"tEXt::Thumb::Image::Width", w_str,
"tEXt::Thumb::Image::Height", h_str,
"tEXt::Thumb::URI", uri,
"tEXt::Thumb::MTime", t_str,
NULL);
g_free (w_str);
g_free (h_str);
g_object_unref (G_OBJECT (pixbuf));
g_object_unref (G_OBJECT (gimage));
g_free (temp_name);
g_free (thumb_name);
gimp_imagefile_update (imagefile);
}
}
}
static void
gimp_imagefile_name_changed (GimpObject *object)
{
GimpImagefile *imagefile;
imagefile = GIMP_IMAGEFILE (object);
if (GIMP_OBJECT_CLASS (parent_class)->name_changed)
GIMP_OBJECT_CLASS (parent_class)->name_changed (object);
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (object));
imagefile->width = -1;
imagefile->height = -1;
imagefile->size = -1;
imagefile->image_state = GIMP_IMAGEFILE_STATE_UNKNOWN;
imagefile->image_mtime = 0;
imagefile->thumb_state = GIMP_IMAGEFILE_STATE_UNKNOWN;
imagefile->thumb_mtime = 0;
g_signal_emit (G_OBJECT (imagefile), gimp_imagefile_signals[INFO_CHANGED], 0);
}
static void
......@@ -171,7 +384,7 @@ gimp_imagefile_set_info (GimpImagefile *imagefile,
{
gboolean changed;
changed = (imagefile->width != width ||
changed = (imagefile->width != width ||
imagefile->height != height ||
imagefile->size != size);
......@@ -179,9 +392,9 @@ gimp_imagefile_set_info (GimpImagefile *imagefile,
imagefile->height = height;
imagefile->size = size;
/* emit a name changed signal so the container view updates */
/* if (changed) */
/* gimp_object_name_changed (GIMP_OBJECT (imagefile)); */
if (changed)
g_signal_emit (G_OBJECT (imagefile),
gimp_imagefile_signals[INFO_CHANGED], 0);
}
static void
......@@ -239,36 +452,32 @@ gimp_imagefile_read_png_thumb (GimpImagefile *imagefile,
{
TempBuf *temp_buf = NULL;
GdkPixbuf *pixbuf = NULL;
gchar *uri = NULL;
gchar *thumbname = NULL;
const gchar *option;
gint mtime;
gint width;
gint height;
gint bytes;
gint y;
time_t y;
guchar *src;
guchar *dest;