diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | README | 9 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/itdb.h | 30 | ||||
-rw-r--r-- | src/itdb_artwork.c | 37 | ||||
-rw-r--r-- | src/itdb_photoalbum.c | 35 | ||||
-rw-r--r-- | src/itdb_track.c | 22 | ||||
-rw-r--r-- | src/ithumb-writer.c | 39 | ||||
-rw-r--r-- | tests/test-photos.c | 3 |
9 files changed, 165 insertions, 45 deletions
@@ -1,3 +1,36 @@ +2006-11-23 Jorg Schuler <jcsjcs at users.sourceforge.net> + + * When adding photos to the iPod the user may or may not want to + rotate the picture shown on the iPod screen, for example + deending on EXIF rotation value. This can now be achieved by + passing a new parameter 'rotation' to itdb_photodb_add_photo() + or itdb_photodb_add_photo_from_data(). (Valid values: 0, 90, 180, + 270, rotation is counter-clockwise). These two functions now + also accept a GError pointer. As a consequence Itdb_Thumb had to + be extended with a field for the rotation value and + itdb_artwork_add_thumbnail have been extended to accept + @rotation and @error as well. + + The actual rotation is carried out in + ithumb-writer.c/ithumb_writer_write_thumbnail() using + gdk_pixbuf_rotate_simple() and require gdk-pixbuf V2.6 or + higher. + + In contrast, itdb_track_set_thumbnails() and + itdb_track_set_thumbnails_from_data have been left unchanged, + even though they could be extended to accept @rotation and + @error easily. Please let me know if this is wanted. + + * configure.ac + src/itdb.h + src/itdb_artwork.c + src/itdb_photoalbum.c + src/itdb_track.c + src/ithumb-writer.c: implemented changes outlined above. + + * tests/test-photos.c: added @rotation and @error to the + itdb_photodb_add_photo() call. + 2006-11-12 Jorg Schuler <jcsjcs at users.sourceforge.net> * ithumb-writer.c (itdb_write_ithumb_files): @@ -124,12 +124,7 @@ other songs is not something that is tranparently handled, ie you'll need to add code either to libgpod or to gtkpod to make that work properly. -As for Photo Database handling (which is not dealt with currently), I -agree it doesn't make sense to associate its parsing with an -Itdb_ItunesDB object, and that a 'parallel' api mimicking somewhat the -Track/Playlist stuff with Photo/Album entities would need to be -designed, but I didn't work on that since, and I probably won't short -term. +... People wanting more info can find lots of details on http://ipodlinux.org/ITunesDB#Artwork_Database @@ -137,3 +132,5 @@ http://ipodlinux.org/ITunesDB#Artwork_Database I hope that's helpful, Christophe + +---------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index b1b5851..c010c58 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,7 @@ AC_ARG_ENABLE(gdk-pixbuf, [AC_HELP_STRING([--disable-gdk-pixbuf],[ArtworkDB will esac], have_gdkpixbuf=yes) AH_TEMPLATE([HAVE_GDKPIXBUF], [Whether gdk-pixbuf is installed, ArtworkDB writing support will be disabled if it can't be found]) if test x$have_gdkpixbuf = xyes; then - PKG_CHECK_MODULES(GDKPIXBUF, gdk-pixbuf-2.0, have_gdkpixbuf=yes, have_gdkpixbuf=no) + PKG_CHECK_MODULES(GDKPIXBUF, gdk-pixbuf-2.0 >= 2.6.0, have_gdkpixbuf=yes, have_gdkpixbuf=no) if test x"$have_gdkpixbuf" = xyes; then AC_DEFINE_UNQUOTED(HAVE_GDKPIXBUF, 1) fi @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-11-11 16:29:02 jcs> +/* Time-stamp: <2006-11-23 23:27:35 jcs> | | Copyright (C) 2002-2006 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -431,17 +431,18 @@ typedef enum { */ struct _Itdb_Thumb { ItdbThumbType type; - gchar *filename; - guchar *image_data; /* holds the thumbnail data of - non-transfered thumbnails when - filename == NULL */ - gsize image_data_len; /* length of data */ + gchar *filename; + guchar *image_data; /* holds the thumbnail data of + non-transfered thumbnails when + filename == NULL */ + gsize image_data_len; /* length of data */ + gint rotation; /* angle (0, 90, 180, 270) to rotate the image */ guint32 offset; guint32 size; - gint16 width; - gint16 height; - gint16 horizontal_padding; - gint16 vertical_padding; + gint16 width; + gint16 height; + gint16 horizontal_padding; + gint16 vertical_padding; }; struct _Itdb_Artwork { @@ -1004,10 +1005,11 @@ void itdb_track_remove_thumbnails (Itdb_Track *track); * how to use. */ Itdb_PhotoDB *itdb_photodb_parse (const gchar *mp, GError **error); Itdb_Artwork *itdb_photodb_add_photo (Itdb_PhotoDB *db, const gchar *filename, - GError **error); + gint rotation, GError **error); Itdb_Artwork *itdb_photodb_add_photo_from_data (Itdb_PhotoDB *db, const guchar *image_data, gsize image_data_len, + gint rotation, GError **error); void itdb_photodb_photoalbum_add_photo (Itdb_PhotoDB *db, Itdb_PhotoAlbum *album, @@ -1039,11 +1041,13 @@ Itdb_Thumb *itdb_artwork_get_thumb_by_type (Itdb_Artwork *artwork, ItdbThumbType type); gboolean itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, ItdbThumbType type, - const gchar *filename); + const gchar *filename, + gint rotation, GError **error); gboolean itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, ItdbThumbType type, const guchar *image_data, - gsize image_data_len); + gsize image_data_len, + gint rotation, GError **error); void itdb_artwork_remove_thumbnail (Itdb_Artwork *artwork, Itdb_Thumb *thumb); void itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork); diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c index d1b312e..4435a82 100644 --- a/src/itdb_artwork.c +++ b/src/itdb_artwork.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-11-12 23:17:20 jcs> +/* Time-stamp: <2006-11-23 23:27:35 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -163,18 +163,27 @@ itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork) * @artwork: an #Itdb_Thumbnail * @type: thumbnail size * @filename: image file to use to create the thumbnail + * @rotation: angle by which the image should be rotated + * counterclockwise. Valid values are 0, 90, 180 and 270. + * @error: return location for a #GError or NULL * * Appends a thumbnail of type @type to existing thumbnails in @artwork. No * data is read from @filename yet, the file will be when @artwork is saved to * disk. @filename must still exist when that happens. * + * For the rotation angle you can also use the gdk constants + * GDK_PIXBUF_ROTATE_NONE, ..._COUNTERCLOCKWISE, ..._UPSIDEDOWN AND + * ..._CLOCKWISE. + * * Return value: TRUE if the thumbnail could be successfully added, FALSE - * otherwise + * otherwise. @error is set appropriately. **/ gboolean itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, ItdbThumbType type, - const gchar *filename) + const gchar *filename, + gint rotation, + GError **error) { #ifdef HAVE_GDKPIXBUF /* This operation doesn't make sense when we can't save thumbnail files */ @@ -185,6 +194,9 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, g_return_val_if_fail (filename, FALSE); if (g_stat (filename, &statbuf) != 0) { + g_set_error (error, 0, -1, + _("Could not access file '%s'."), + filename); return FALSE; } @@ -194,10 +206,13 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, thumb = itdb_thumb_new (); thumb->filename = g_strdup (filename); thumb->type = type; + thumb->rotation = rotation; artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); return TRUE; #else + g_set_error (error, 0, -1, + _("Artwork support not compiled into libgpod.")); return FALSE; #endif } @@ -210,19 +225,28 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork, * @image_data: data used to create the thumbnail (the raw contents of * an image file) * @image_data_len: length of above data block + * @rotation: angle by which the image should be rotated + * counterclockwise. Valid values are 0, 90, 180 and 270. + * @error: return location for a #GError or NULL * * Appends a thumbnail of type @type to existing thumbnails in * @artwork. No data is processed yet. This will be done when @artwork * is saved to disk. * + * For the rotation angle you can also use the gdk constants + * GDK_PIXBUF_ROTATE_NONE, ..._COUNTERCLOCKWISE, ..._UPSIDEDOWN AND + * ..._CLOCKWISE. + * * Return value: TRUE if the thumbnail could be successfully added, FALSE - * otherwise + * otherwise. @error is set appropriately. **/ gboolean itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, ItdbThumbType type, const guchar *image_data, - gsize image_data_len) + gsize image_data_len, + gint rotation, + GError **error) { #ifdef HAVE_GDKPIXBUF /* This operation doesn't make sense when we can't save thumbnail files */ @@ -243,10 +267,13 @@ itdb_artwork_add_thumbnail_from_data (Itdb_Artwork *artwork, memcpy (thumb->image_data, image_data, image_data_len); thumb->type = type; + thumb->rotation = rotation; artwork->thumbnails = g_list_append (artwork->thumbnails, thumb); return TRUE; #else + g_set_error (error, 0, -1, + _("Artwork support not compiled into libgpod.")); return FALSE; #endif } diff --git a/src/itdb_photoalbum.c b/src/itdb_photoalbum.c index edc1004..df36a1b 100644 --- a/src/itdb_photoalbum.c +++ b/src/itdb_photoalbum.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-10-31 21:49:36 jcs> +/* Time-stamp: <2006-11-23 23:29:44 jcs> | | Copyright (C) 2002-2006 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -333,6 +333,7 @@ static Itdb_Artwork *itdb_photodb_add_photo_internal (Itdb_PhotoDB *db, const gchar *filename, const guchar *image_data, gsize image_data_len, + gint rotation, GError **error) { #ifdef HAVE_GDKPIXBUF @@ -408,14 +409,18 @@ static Itdb_Artwork *itdb_photodb_add_photo_internal (Itdb_PhotoDB *db, { result = itdb_artwork_add_thumbnail (artwork, format->type, - filename); + filename, + rotation, + error); } if (image_data) { result = itdb_artwork_add_thumbnail_from_data (artwork, format->type, image_data, - image_data_len); + image_data_len, + rotation, + error); } } @@ -453,45 +458,63 @@ static Itdb_Artwork *itdb_photodb_add_photo_internal (Itdb_PhotoDB *db, * itdb_photodb_add_photo: * @db: the #Itdb_PhotoDB to add the photo to. * @filename: file with the photo to add. + * @rotation: angle by which the image should be rotated + * counterclockwise. Valid values are 0, 90, 180 and 270. * @error: return location for a #GError or NULL * * Add a photo to the PhotoDB. The photo is automatically added to the * first Photoalbum, which by default contains a list of all photos in * the database. If no Photoalbums exist one is created automatically. * + * For the rotation angle you can also use the gdk constants + * GDK_PIXBUF_ROTATE_NONE, ..._COUNTERCLOCKWISE, ..._UPSIDEDOWN AND + * ..._CLOCKWISE. + * * Return value: a pointer to the added photo. **/ Itdb_Artwork *itdb_photodb_add_photo (Itdb_PhotoDB *db, const gchar *filename, + gint rotation, GError **error) { g_return_val_if_fail (db, FALSE); g_return_val_if_fail (filename, FALSE); - return itdb_photodb_add_photo_internal (db, filename, NULL, 0, error); + return itdb_photodb_add_photo_internal (db, filename, NULL, 0, rotation, error); } /** * itdb_photodb_add_photo_from_data: * @db: the #Itdb_PhotoDB to add the photo to. - * @filename: file with the photo to add. + * @image_data: chunk of memory containing the image data (for example + * a jpg file) + * @image_data_len: length of above chunk of memory + * @rotation: angle by which the image should be rotated + * counterclockwise. Valid values are 0, 90, 180 and 270. * @error: return location for a #GError or NULL * * Add a photo to the PhotoDB. The photo is automatically added to the * first Photoalbum, which by default contains a list of all photos in * the database. If no Photoalbums exist one is created automatically. + * + * For the rotation angle you can also use the gdk constants + * GDK_PIXBUF_ROTATE_NONE, ..._COUNTERCLOCKWISE, ..._UPSIDEDOWN AND + * ..._CLOCKWISE. + * + * Return value: a pointer to the added photo. **/ Itdb_Artwork *itdb_photodb_add_photo_from_data (Itdb_PhotoDB *db, const guchar *image_data, gsize image_data_len, + gint rotation, GError **error) { g_return_val_if_fail (db, FALSE); g_return_val_if_fail (image_data, FALSE); return itdb_photodb_add_photo_internal (db, NULL, image_data, image_data_len, - error); + rotation, error); } diff --git a/src/itdb_track.c b/src/itdb_track.c index fc66f75..3b8b9c0 100644 --- a/src/itdb_track.c +++ b/src/itdb_track.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-11-07 20:54:45 jcs> +/* Time-stamp: <2006-11-23 23:32:16 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -370,7 +370,9 @@ Itdb_Track *itdb_track_duplicate (Itdb_Track *tr) static gboolean itdb_track_set_thumbnails_internal (Itdb_Track *track, const gchar *filename, const guchar *image_data, - gsize image_data_len) + gsize image_data_len, + gint rotation, + GError **error) { gboolean result = FALSE; @@ -382,23 +384,25 @@ static gboolean itdb_track_set_thumbnails_internal (Itdb_Track *track, { result = itdb_artwork_add_thumbnail (track->artwork, ITDB_THUMB_COVER_SMALL, - filename); + filename, rotation, error); if (result == TRUE) result = itdb_artwork_add_thumbnail (track->artwork, ITDB_THUMB_COVER_LARGE, - filename); + filename, rotation, error); } if (image_data) { result = itdb_artwork_add_thumbnail_from_data (track->artwork, ITDB_THUMB_COVER_SMALL, image_data, - image_data_len); + image_data_len, + rotation, error); if (result == TRUE) result = itdb_artwork_add_thumbnail_from_data (track->artwork, ITDB_THUMB_COVER_LARGE, image_data, - image_data_len); + image_data_len, + rotation, error); } if (result == TRUE) @@ -443,7 +447,8 @@ gboolean itdb_track_set_thumbnails (Itdb_Track *track, g_return_val_if_fail (track, FALSE); g_return_val_if_fail (filename, FALSE); - return itdb_track_set_thumbnails_internal (track, filename, NULL, 0); + return itdb_track_set_thumbnails_internal (track, filename, NULL, 0, + 0, NULL); } @@ -471,7 +476,8 @@ gboolean itdb_track_set_thumbnails_from_data (Itdb_Track *track, g_return_val_if_fail (image_data, FALSE); return itdb_track_set_thumbnails_internal (track, NULL, - image_data, image_data_len); + image_data, image_data_len, + 0, NULL); } diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index 060ff2a..f20546f 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-11-13 00:03:30 jcs> +/* Time-stamp: <2006-11-23 23:45:01 jcs> * * Copyright (C) 2005 Christophe Fergeau * @@ -304,13 +304,32 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, gint width, height; /* must be gint -- see comment below */ g_return_val_if_fail (writer, FALSE); + g_return_val_if_fail (writer->img_info, FALSE); g_return_val_if_fail (thumb, FALSE); + /* Make sure @rotation is valid (0, 90, 180, 270) */ + thumb->rotation = thumb->rotation % 360; + thumb->rotation /= 90; + thumb->rotation *= 90; + + /* If we rotate by 90 or 270 degrees interchange the width and + * height */ + + if ((thumb->rotation == 0) || (thumb->rotation == 180)) + { + width = writer->img_info->width; + height = writer->img_info->height; + } + else + { + width = writer->img_info->height; + height = writer->img_info->width; + } + if (thumb->filename) { /* read image from filename */ pixbuf = gdk_pixbuf_new_from_file_at_size (thumb->filename, - writer->img_info->width, - writer->img_info->height, + width, height, NULL); g_free (thumb->filename); @@ -321,8 +340,7 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); g_return_val_if_fail (loader, FALSE); gdk_pixbuf_loader_set_size (loader, - writer->img_info->width, - writer->img_info->height); + width, height); gdk_pixbuf_loader_write (loader, thumb->image_data, thumb->image_data_len, @@ -342,6 +360,17 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, return FALSE; } + /* Rotate if necessary */ + if (thumb->rotation != 0) + { + GdkPixbuf *new_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, thumb->rotation); + g_object_unref (pixbuf); + pixbuf = new_pixbuf; + } + + /* Clean up */ + thumb->rotation = 0; + /* !! cannot write directly to &thumb->width/height because g_object_get() returns a gint, but thumb->width/height are gint16 !! */ diff --git a/tests/test-photos.c b/tests/test-photos.c index 18d364e..fd89aa4 100644 --- a/tests/test-photos.c +++ b/tests/test-photos.c @@ -265,7 +265,8 @@ static int do_add (int argc, char **argv) { Itdb_Artwork *photo; - photo = itdb_photodb_add_photo (db, argv[i], &error); + photo = itdb_photodb_add_photo (db, argv[i], GDK_PIXBUF_ROTATE_NONE, + &error); if (photo == NULL) { if (error) |