/* Cataract - Static web photo gallery generator * Copyright (C) 2008 Tomas Bzatek * * 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 #include #include #include #include #include #include #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; } }