summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--README5
-rw-r--r--generators.c3
-rw-r--r--jpeg-utils.c280
-rw-r--r--jpeg-utils.cpp387
-rw-r--r--jpeg-utils.h28
6 files changed, 419 insertions, 292 deletions
diff --git a/Makefile b/Makefile
index 86707ce..2daafa4 100644
--- a/Makefile
+++ b/Makefile
@@ -13,15 +13,15 @@ OBJECTS=gallery-utils.o jpeg-utils.o xml-parser.o setup.o items.o generators.o c
.SUFFIXES: .c .cpp
.c.o:
- $(CC) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 libexif --cflags` `Wand-config --cflags` -c $<
+ $(CC) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 --cflags` `Wand-config --cflags` -c $<
.cpp.o:
- $(CC) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 libexif --cflags` `Wand-config --cppflags` -c $<
+ $(CPP) $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 exiv2 --cflags` `Wand-config --cppflags` -c $<
all cgg: check $(OBJECTS)
- $(CC) -o cgg $(OBJECTS) -lm $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 libexif --libs` `Wand-config --ldflags --libs`
+ $(CC) -o cgg $(OBJECTS) -lm $(CFLAGS) `pkg-config libxml-2.0 glib-2.0 exiv2 --libs` `Wand-config --ldflags --libs`
cgg.o: cgg.c
-jpeg-utils.o: jpeg-utils.c jpeg-utils.h
+jpeg-utils.o: jpeg-utils.cpp jpeg-utils.h
gallery-utils.o: gallery-utils.c gallery-utils.h
setup.o: setup.c setup.h
xml-parser.o: xml-parser.c xml-parser.h
diff --git a/README b/README
index 9ad1df0..f09f771 100644
--- a/README
+++ b/README
@@ -18,14 +18,13 @@ Feature highlights:
* fast, easy to cache/mirror
* XML-based description files
* modern design, valid XHTML 1.0 and CSS 2
- * EXIF support
+ * EXIF & IPTC support
* console application, allowing easy scripting
(e.g. auto-refresh after new images are uploaded via FTP)
Planned features:
* prefetch of next image (JavaScript)
* strip unnecessary blocks from images - EXIF, thumbnails
- * port to exiv2 library to get rid of that weird shutter times, IPTC support
* support adding comments and copyright notes to images
* switchable flat album view
* groups in the album - e.g. separate years, decades...
@@ -57,7 +56,7 @@ BUILDING
First make sure you have meet the following requirements:
libxml-2.0 (tested with 2.6.32)
glib-2.0 (2.12.0 recommented, tested with 2.16.3)
- libexif (tested with 0.6.16)
+ exiv2 (tested with 0.17)
ImageMagick (tested with 6.4.2.0)
To compile cgg, type 'make'
diff --git a/generators.c b/generators.c
index 3639309..a478389 100644
--- a/generators.c
+++ b/generators.c
@@ -486,8 +486,7 @@ write_html_image (TGallerySetup *setup,
/* Get EXIF data from the original image */
- exif = malloc (sizeof (TExifData));
- if (get_exif (original_img, exif))
+ if (get_exif (original_img, &exif))
fprintf (stderr, "write_html_image: error getting exif data from file \"%s\"\n", orig_dst);
/* Retrieve image sizes of preview and original image */
diff --git a/jpeg-utils.c b/jpeg-utils.c
deleted file mode 100644
index dc1c880..0000000
--- a/jpeg-utils.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/* Cataract - Static web photo gallery generator
- * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <libexif/exif-data.h>
-#include <libexif/exif-content.h>
-#include <libexif/exif-entry.h>
-
-#include <wand/magick-wand.h>
-
-#include "jpeg-utils.h"
-
-
-
-
-/*
- * get_exif: retrieve EXIF informations from a JPEG image
- */
-int
-get_exif (const char *filename, TExifData *data)
-{
- ExifData *edata;
- ExifEntry *entry;
- ExifContent *content;
- int i, j;
-
- if (data == NULL)
- data = malloc (sizeof (TExifData));
- memset (data, 0, sizeof (TExifData));
- edata = exif_data_new_from_file (filename);
- if (edata == NULL)
- return -1;
-
- for (i = 0; i < EXIF_IFD_COUNT; i++) {
- content = edata->ifd[i];
- if ((content == NULL) || (content->count == 0))
- continue;
-
- for (j = 0; j < content->count; j++) {
- entry = content->entries[j];
-
- if (! content->entries[j])
- continue;
-
- #define VALUE_LEN 1024
- char value[VALUE_LEN + 1];
-
- switch (entry->tag)
- {
- case EXIF_TAG_DATE_TIME:
- data->datetime = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_DATE_TIME_ORIGINAL:
- case EXIF_TAG_DATE_TIME_DIGITIZED:
- if (data->datetime == NULL)
- data->datetime = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_MODEL:
- if (data->camera_model == NULL)
- data->camera_model = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_MAKE:
- if (data->camera_model == NULL)
- data->camera_model = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_ISO_SPEED_RATINGS:
- data->iso = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_FOCAL_LENGTH:
- data->focal_length = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM:
- data->focal_length_35mm = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_FNUMBER:
- data->aperture = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_APERTURE_VALUE:
- if (data->aperture == NULL)
- data->aperture = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_EXPOSURE_TIME:
- data->exposure = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_FLASH:
- data->flash = strdup (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_PIXEL_X_DIMENSION:
- data->width = atol (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- case EXIF_TAG_PIXEL_Y_DIMENSION:
- data->height = atol (exif_entry_get_value (entry, value, VALUE_LEN));
- break;
-
- default:
- break;
- }
- }
- }
- exif_data_free (edata);
-
- #ifdef __DEBUG_ALL__
- printf("EXIF_TAG_DATE_TIME = %s\n", data->datetime);
- printf("EXIF_TAG_MODEL = %s\n", data->camera_model);
- printf("EXIF_TAG_ISO_SPEED_RATINGS = %s\n", data->iso);
- printf("EXIF_TAG_FOCAL_LENGTH = %s\n", data->focal_length);
- printf("EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = %s\n", data->focal_length_35mm);
- printf("EXIF_TAG_FNUMBER = %s\n", data->aperture);
- printf("EXIF_TAG_EXPOSURE_TIME = %s\n", data->exposure);
- printf("EXIF_TAG_FLASH = %s\n", data->flash);
- printf("EXIF_TAG_PIXEL_X_DIMENSION = %lu\n", data->width);
- printf("EXIF_TAG_PIXEL_Y_DIMENSION = %lu\n", data->height);
- #endif
-
- return 0;
-}
-
-/*
- * free_exif_struct: free allocated structure
- */
-void
-free_exif_data (TExifData *data)
-{
- if (data) {
- if (data->aperture)
- free (data->aperture);
- if (data->camera_model)
- free (data->camera_model);
- if (data->datetime)
- free (data->datetime);
- if (data->exposure)
- free (data->exposure);
- if (data->flash)
- free (data->flash);
- if (data->focal_length)
- free (data->focal_length);
- if (data->focal_length_35mm)
- free (data->focal_length_35mm);
- if (data->iso)
- free (data->iso);
- free (data);
- data = NULL;
- }
-}
-
-
-/*
- * resize_image: resize image pointed by src and save result to dst
- */
-gboolean
-resize_image (const char *src, const char *dst,
- int size_x, int size_y,
- int quality)
-{
- #define ThrowWandException(wand) \
- { \
- char *description; \
- ExceptionType severity; \
- \
- description = MagickGetException (wand, &severity); \
- (void) fprintf (stderr, "Error converting image: %s %s %ld %s\n", GetMagickModule(), description); \
- description = (char*) MagickRelinquishMemory (description); \
- return FALSE; \
- }
-
- MagickBooleanType status;
- MagickWand *magick_wand;
-
- /* Read an image. */
- MagickWandGenesis();
- magick_wand = NewMagickWand();
- status = MagickReadImage (magick_wand, src);
- if (status == MagickFalse)
- ThrowWandException (magick_wand);
- MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0);
- MagickSetImageCompressionQuality (magick_wand, quality);
-
- /* Write the image and destroy it. */
- status = MagickWriteImage (magick_wand, dst);
- if (status == MagickFalse)
- ThrowWandException (magick_wand);
- magick_wand = DestroyMagickWand (magick_wand);
- MagickWandTerminus();
-
- return TRUE;
-}
-
-
-/*
- * get_image_sizes: retrieve image dimensions
- */
-void
-get_image_sizes (const char *img,
- unsigned long *width, unsigned long *height)
-{
- #define xThrowWandException(wand) \
- { \
- char *description; \
- ExceptionType severity; \
- \
- description = MagickGetException (wand, &severity); \
- (void) fprintf (stderr, "Error reading image info: %s %s %ld %s\n", GetMagickModule(), description); \
- description = (char*) MagickRelinquishMemory(description); \
- return; \
- }
-
- MagickBooleanType status;
- MagickWand *magick_wand;
-
- *width = -1;
- *height = -1;
-
- /* Read an image. */
- MagickWandGenesis();
- magick_wand = NewMagickWand();
- status = MagickPingImage (magick_wand, img);
- if (status == MagickFalse)
- xThrowWandException (magick_wand);
- *width = MagickGetImageWidth (magick_wand);
- *height = MagickGetImageHeight (magick_wand);
-
- magick_wand = DestroyMagickWand (magick_wand);
- MagickWandTerminus();
-}
-
-
-/*
- * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio
- */
-void
-calculate_sizes (const unsigned long max_width, const unsigned long max_height,
- unsigned long *width, unsigned long *height)
-{
- if ((max_width > *width) && (max_height > *height))
- return;
-
- double max_ratio = (double) max_width / (double) max_height;
- double real_ratio = (double) *width / (double) *height;
-
- if ((*width > *height) && (max_ratio <= real_ratio))
- {
- *height = max_width / real_ratio;
- *width = max_width;
- }
- else
- {
- *width = max_height * real_ratio;
- *height = max_height;
- }
-}
-
diff --git a/jpeg-utils.cpp b/jpeg-utils.cpp
new file mode 100644
index 0000000..973b448
--- /dev/null
+++ b/jpeg-utils.cpp
@@ -0,0 +1,387 @@
+/* Cataract - Static web photo gallery generator
+ * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <exiv2/image.hpp>
+#include <exiv2/exif.hpp>
+
+#include <wand/magick-wand.h>
+
+#include "jpeg-utils.h"
+
+
+
+/*
+ * get_exif: retrieve EXIF informations from a JPEG image
+ */
+int
+get_exif (const char *filename, TExifData **exif_data)
+{
+ TExifData *data;
+
+ data = (TExifData*) malloc (sizeof (TExifData));
+ memset (data, 0, sizeof (TExifData));
+ *exif_data = data;
+
+ try
+ {
+ Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename);
+ g_assert (image.get() != 0);
+ image->readMetadata();
+
+ Exiv2::ExifData &exifData = image->exifData();
+ if (! exifData.empty()) {
+ /* EXIF::Aperture */
+ try {
+ float val = exifData["Exif.Photo.FNumber"].toFloat();
+ if (val >= 0)
+ data->aperture = g_strdup_printf ("f/%.1f", val);
+ } catch (...) { }
+
+ /* EXIF::Camera model */
+ try {
+ const char *val = exifData["Exif.Image.Model"].toString().c_str();
+ if (val && strlen(val) > 0)
+ data->camera_model = strdup (val);
+ } catch (...) { }
+
+ /* EXIF::DateTime */
+ try {
+ const char *val = NULL;
+ try {
+ val = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str();
+ } catch (...) { }
+ if ((! val) || (strlen(val) == 0))
+ try {
+ val = exifData["Exif.Image.DateTime"].toString().c_str();
+ } catch (...) { }
+
+ if (val && strlen(val) > 0) {
+ static struct tm tt;
+ static char conv[1024];
+
+ if (sscanf (val, "%d:%d:%d %d:%d:%d", &tt.tm_year, &tt.tm_mon, &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec) == 6)
+ {
+ tt.tm_year -= 1900;
+ tt.tm_mon--;
+ if (strftime (&conv[0], sizeof(conv), "%c", &tt))
+ data->datetime = strdup (&conv[0]);
+ }
+ }
+ } catch (...) { }
+
+ /* EXIF::Shutter speed */
+ try {
+ float val = exifData["Exif.Photo.ExposureTime"].toFloat();
+ if (val > 0) {
+ if (val < 0.5)
+ data->exposure = g_strdup_printf ("1/%.0f s", 1/val);
+ else
+ data->exposure = g_strdup_printf ("%.1f s", val);
+ }
+ } catch (...) { }
+
+ /* EXIF::Flash */
+ try {
+ long int val = exifData["Exif.Photo.Flash"].toLong();
+ if ((val > 0) && ((val & 1) == 1))
+ data->flash = strdup ((char *) "Flash fired");
+ else
+ data->flash = strdup ((char *) "--");
+ } catch (...) { }
+
+ /* EXIF::Focal length */
+ try {
+ float val = exifData["Exif.Photo.FocalLength"].toFloat();
+ if (val >= 0)
+ data->focal_length = g_strdup_printf ("%.0f mm", val);
+ } catch (...) { }
+
+ /* EXIF::ISO */
+ try {
+ long int val = exifData["Exif.Photo.ISOSpeedRatings"].toLong();
+ if (val > 0)
+ data->iso = g_strdup_printf ("%ld", val);
+ } catch (...) { }
+
+ /* EXIF::Software */
+ try {
+ data->exif_software = strdup (exifData["Exif.Image.Software"].toString().c_str());
+ } catch (...) { }
+
+ /* EXIF::Image description */
+ try {
+ data->exif_imgdesc = strdup (exifData["Exif.Image.ImageDescription"].toString().c_str());
+ } catch (...) { }
+
+ /* EXIF::Artist */
+ try {
+ data->exif_artist = strdup (exifData["Exif.Image.Artist"].toString().c_str());
+ } catch (...) { }
+
+ /* EXIF::Copyright */
+ try {
+ data->exif_copyright = strdup (exifData["Exif.Image.Copyright"].toString().c_str());
+ } catch (...) { }
+
+ /* EXIF::User comment */
+ try {
+ data->exif_usercomment = strdup (exifData["Exif.Photo.UserComment"].toString().c_str());
+ } catch (...) { }
+ }
+
+ Exiv2::IptcData &iptcData = image->iptcData();
+ if (! iptcData.empty()) {
+ /* IPTC::Object name */
+ try {
+ data->iptc_objectname = strdup (iptcData["Iptc.Application2.ObjectName"].toString().c_str());
+ } catch (...) { }
+
+ /* IPTC::Copyright */
+ try {
+ data->iptc_copyright = strdup (iptcData["Iptc.Application2.Copyright"].toString().c_str());
+ } catch (...) { }
+
+ /* IPTC::Credit */
+ try {
+ data->iptc_credit = strdup (iptcData["Iptc.Application2.Credit"].toString().c_str());
+ } catch (...) { }
+
+ /* IPTC::Caption */
+ try {
+ data->iptc_caption = strdup (iptcData["Iptc.Application2.Caption"].toString().c_str());
+ } catch (...) { }
+
+ /* IPTC::Author */
+ try {
+ data->iptc_author = strdup (iptcData["Iptc.Application2.Byline"].toString().c_str());
+ } catch (...) { }
+ }
+
+ }
+ catch (Exiv2::AnyError& e)
+ {
+ fprintf (stderr, "get_exif: Caught Exiv2 exception: '%s'\n", e.what());
+ return -1;
+ }
+
+ /* Read the JPEG comment */
+ MagickBooleanType status;
+ MagickWand *magick_wand;
+ char *comment;
+
+ MagickWandGenesis();
+ magick_wand = NewMagickWand();
+ status = MagickPingImage (magick_wand, filename);
+ if (status == MagickTrue) {
+ comment = MagickGetImageProperty(magick_wand, "comment");
+ if (comment)
+ data->jpeg_comment = strdup (comment);
+ MagickRelinquishMemory (comment);
+ }
+ magick_wand = DestroyMagickWand (magick_wand);
+ MagickWandTerminus();
+
+
+#ifdef __DEBUG_ALL__
+ printf("EXIF_TAG_DATE_TIME = '%s'\n", data->datetime);
+ printf("EXIF_TAG_MODEL = '%s'\n", data->camera_model);
+ printf("EXIF_TAG_ISO_SPEED_RATINGS = '%s'\n", data->iso);
+ printf("EXIF_TAG_FOCAL_LENGTH = '%s'\n", data->focal_length);
+ printf("EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM = '%s'\n", data->focal_length_35mm);
+ printf("EXIF_TAG_FNUMBER = '%s'\n", data->aperture);
+ printf("EXIF_TAG_EXPOSURE_TIME = '%s'\n", data->exposure);
+ printf("EXIF_TAG_FLASH = '%s'\n", data->flash);
+ printf("Exif.Image.Software = '%s'\n", data->exif_software);
+ printf("Exif.Image.ImageDescription = '%s'\n", data->exif_imgdesc);
+ printf("Exif.Image.Artist = '%s'\n", data->exif_artist);
+ printf("Exif.Image.Copyright = '%s'\n", data->exif_copyright);
+ printf("Exif.Photo.UserComment = '%s'\n", data->exif_usercomment);
+ printf("Iptc.Application2.ObjectName = '%s'\n", data->iptc_objectname);
+ printf("Iptc.Application2.Copyright = '%s'\n", data->iptc_copyright);
+ printf("Iptc.Application2.Credit = '%s'\n", data->iptc_credit);
+ printf("Iptc.Application2.Caption = '%s'\n", data->iptc_caption);
+ printf("Iptc.Application2.Byline = '%s'\n", data->iptc_author);
+ printf("JPEG comment = '%s'\n", data->jpeg_comment);
+#endif
+
+ return 0;
+}
+
+/*
+ * free_exif_struct: free allocated structure
+ */
+void
+free_exif_data (TExifData *data)
+{
+ if (data) {
+ if (data->aperture)
+ free (data->aperture);
+ if (data->camera_model)
+ free (data->camera_model);
+ if (data->datetime)
+ free (data->datetime);
+ if (data->exposure)
+ free (data->exposure);
+ if (data->flash)
+ free (data->flash);
+ if (data->focal_length)
+ free (data->focal_length);
+ if (data->focal_length_35mm)
+ free (data->focal_length_35mm);
+ if (data->iso)
+ free (data->iso);
+
+ if (data->exif_software)
+ free (data->exif_software);
+ if (data->exif_imgdesc)
+ free (data->exif_imgdesc);
+ if (data->exif_artist)
+ free (data->exif_artist);
+ if (data->exif_copyright)
+ free (data->exif_copyright);
+ if (data->exif_usercomment)
+ free (data->exif_usercomment);
+
+ if (data->iptc_objectname)
+ free (data->iptc_objectname);
+ if (data->iptc_copyright)
+ free (data->iptc_copyright);
+ if (data->iptc_credit)
+ free (data->iptc_credit);
+ if (data->iptc_caption)
+ free (data->iptc_caption);
+ if (data->iptc_author)
+ free (data->iptc_author);
+
+ if (data->jpeg_comment)
+ free (data->jpeg_comment);
+
+ free (data);
+ data = NULL;
+ }
+}
+
+
+/*
+ * resize_image: resize image pointed by src and save result to dst
+ */
+gboolean
+resize_image (const char *src, const char *dst,
+ int size_x, int size_y,
+ int quality)
+{
+ #define ThrowWandException(wand) \
+ { \
+ char *description; \
+ ExceptionType severity; \
+ \
+ description = MagickGetException (wand, &severity); \
+ (void) fprintf (stderr, "Error converting image: %s %s %ld %s\n", GetMagickModule(), description); \
+ description = (char*) MagickRelinquishMemory (description); \
+ return FALSE; \
+ }
+
+ MagickBooleanType status;
+ MagickWand *magick_wand;
+
+ /* Read an image. */
+ MagickWandGenesis();
+ magick_wand = NewMagickWand();
+ status = MagickReadImage (magick_wand, src);
+ if (status == MagickFalse)
+ ThrowWandException (magick_wand);
+ MagickResizeImage (magick_wand, size_x, size_y, LanczosFilter, 1.0);
+ MagickSetImageCompressionQuality (magick_wand, quality);
+
+ /* Write the image and destroy it. */
+ status = MagickWriteImage (magick_wand, dst);
+ if (status == MagickFalse)
+ ThrowWandException (magick_wand);
+ magick_wand = DestroyMagickWand (magick_wand);
+ MagickWandTerminus();
+
+ return TRUE;
+}
+
+
+/*
+ * get_image_sizes: retrieve image dimensions
+ */
+void
+get_image_sizes (const char *img,
+ unsigned long *width, unsigned long *height)
+{
+ #define xThrowWandException(wand) \
+ { \
+ char *description; \
+ ExceptionType severity; \
+ \
+ description = MagickGetException (wand, &severity); \
+ (void) fprintf (stderr, "Error reading image info: %s %s %ld %s\n", GetMagickModule(), description); \
+ description = (char*) MagickRelinquishMemory(description); \
+ return; \
+ }
+
+ MagickBooleanType status;
+ MagickWand *magick_wand;
+
+ *width = -1;
+ *height = -1;
+
+ /* Read an image. */
+ MagickWandGenesis();
+ magick_wand = NewMagickWand();
+ status = MagickPingImage (magick_wand, img);
+ if (status == MagickFalse)
+ xThrowWandException (magick_wand);
+ *width = MagickGetImageWidth (magick_wand);
+ *height = MagickGetImageHeight (magick_wand);
+
+ magick_wand = DestroyMagickWand (magick_wand);
+ MagickWandTerminus();
+}
+
+
+/*
+ * calculate_sizes: calculate maximal image sizes within specified limits keeping aspect ratio
+ */
+void
+calculate_sizes (const unsigned long max_width, const unsigned long max_height,
+ unsigned long *width, unsigned long *height)
+{
+ if ((max_width > *width) && (max_height > *height))
+ return;
+
+ double max_ratio = (double) max_width / (double) max_height;
+ double real_ratio = (double) *width / (double) *height;
+
+ if ((*width > *height) && (max_ratio <= real_ratio))
+ {
+ *height = max_width / real_ratio;
+ *width = max_width;
+ }
+ else
+ {
+ *width = max_height * real_ratio;
+ *height = max_height;
+ }
+}
+
diff --git a/jpeg-utils.h b/jpeg-utils.h
index 56bb51d..4c47d3c 100644
--- a/jpeg-utils.h
+++ b/jpeg-utils.h
@@ -15,9 +15,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
#include <glib.h>
+/* TODO: we want to have numerical values here at some point in the future */
typedef struct {
char *datetime;
char *camera_model;
@@ -27,15 +33,27 @@ typedef struct {
char *aperture;
char *exposure;
char *flash;
- unsigned long width;
- unsigned long height;
+
+ char *exif_software;
+ char *exif_imgdesc;
+ char *exif_artist;
+ char *exif_copyright;
+ char *exif_usercomment;
+
+ char *iptc_objectname;
+ char *iptc_copyright;
+ char *iptc_credit;
+ char *iptc_caption;
+ char *iptc_author;
+
+ char *jpeg_comment;
} TExifData;
/*
* get_exif: retrieve EXIF info from a JPEG image
*/
-int get_exif (const char *filename, TExifData *data);
+int get_exif (const char *filename, TExifData **exif_data);
/*
* free_exif_struct: free allocated structure
@@ -63,3 +81,7 @@ void get_image_sizes (const char *img,
void calculate_sizes (const unsigned long max_width, const unsigned long max_height,
unsigned long *width, unsigned long *height);
+
+#ifdef __cplusplus
+ }
+#endif \ No newline at end of file