libcupsfilters_la_LIBADD = \
$(CUPS_LIBS) \
$(LIBJPEG_LIBS) \
+ $(EXIF_LIBS) \
$(LIBPNG_LIBS) \
$(TIFF_LIBS) \
-lm
libcupsfilters_la_CFLAGS = \
$(CUPS_CFLAGS) \
$(LIBJPEG_CFLAGS) \
+ $(EXIF_CFLAGS) \
$(LIBPNG_CFLAGS) \
$(TIFF_CFLAGS)
libcupsfilters_la_LDFLAGS = \
# Check for modules needed by utils/
# ==================================
+dnl including EXIF library
+EXIF_LIBS=""
+EXIF_CFLAGS=""
+
+AC_ARG_ENABLE([exif],
+ [AS_HELP_STRING([--disable-exif], [Disable exif metadata readout from images])],
+ [enable_exif="$enableval"],
+ [enable_exif=yes]
+)
+AM_CONDITIONAL([ENABLE_EXIF], [test "x$enable_exif" != "xno"])
+
+AC_ARG_WITH(exif-libs,
+ [AS_HELP_STRING([--with-exif-libs], [Set directory for exif library.])],
+ EXIF_LIBS="-L$withval $EXIF_LIBS",)
+AC_ARG_WITH(exif-includes,
+ [AS_HELP_STRING([--with-exif-includes], [Set directory for exif includes.])],
+ EXIF_CFLAGS="-I$withval $EXIF_CFLAGS",)
+
+if test "x$enable_exif" != xno; then
+ PKG_CHECK_MODULES(EXIF, libexif,
+ [AC_DEFINE(HAVE_EXIF, [], [Define if you have the libexif library])])
+fi
+
+AC_SUBST(EXIF_LIBS)
+AC_SUBST(EXIF_CFLAGS)
+
dnl Avahi for cups-browsed
AVAHI_LIBS=""
AVAHI_CFLAGS=""
ippfind-path: ${with_ippfind_path}
imagefilters: ${enable_imagefilters}
jpeg: ${with_jpeg}
+ exif: ${enable_exif}
pdftocairo-path: ${with_pdftocairo_path}
pdftops: ${with_pdftops}
pdftops-path: ${with_pdftops_path}
#ifdef HAVE_LIBJPEG
# include <jpeglib.h> /* JPEG/JFIF image definitions */
+#define JPEG_APP0 0xE0 /* APP0 marker code */
/*
* '_cupsImageReadJPEG()' - Read a JPEG image file.
img->xsize = cinfo.output_width;
img->ysize = cinfo.output_height;
+
+ int temp = -1;
- if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
+#ifdef HAVE_EXIF
+ /*
+ scan image file for exif data
+ */
+
+ temp = _cupsImageReadEXIF(img, fp);
+#endif
+ /*
+ check headers only if EXIF contains no info about ppi
+ */
+
+ if (temp != 1 && cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
{
if (cinfo.density_unit == 1)
{
img->xsize = width;
img->ysize = height;
- if ((xppm = png_get_x_pixels_per_meter(pp, info)) != 0 &&
+
+ int temp = -1;
+
+#ifdef HAVE_EXIF
+ /*
+ scan image file for exif data
+ */
+
+ temp = _cupsImageReadEXIF(img, fp);
+#endif
+ /*
+ check headers only if EXIF contains no info about ppi
+ */
+
+ if (temp != 1 && (xppm = png_get_x_pixels_per_meter(pp, info)) != 0 &&
(yppm = png_get_y_pixels_per_meter(pp, info)) != 0)
{
img->xppi = (int)((float)xppm * 0.0254);
# include <unistd.h>
# endif /* WIN32 */
# include <errno.h>
-# include <math.h>
+# include <math.h>
+#ifdef HAVE_EXIF
+# include <libexif/exif-data.h>
+#endif
/*
* Constants...
extern void _cupsRasterAddError(const char *f, ...);
extern void _cupsRasterClearError(void);
+#ifdef HAVE_EXIF
+int _cupsImageReadEXIF(cf_image_t *img, FILE *fp);
+#endif
+
#endif /* !_CUPS_IMAGE_PRIVATE_H_ */
/*
* Get the image resolution...
*/
+
+ int temp = -1;
- if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) &&
+#ifdef HAVE_EXIF
+ /*
+ scan image file for exif data
+ */
+
+ temp = _cupsImageReadEXIF(img, fp);
+#endif
+ /*
+ check headers only if EXIF contains no info about ppi
+ */
+
+ if (temp != 1 && TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) &&
TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) &&
TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit))
{
img->xppi, img->yppi);
}
+
/*
* See if the image has an alpha channel...
*/
* cupsImageSetMaxTiles() - Set the maximum number of tiles to cache.
* flush_tile() - Flush the least-recently-used tile in the cache.
* get_tile() - Get a cached tile.
+ * _cupsImageReadEXIF() - to read exif metadata of images
+ * trim_spaces() - helper function to extract results from string
+ * returned by exif library functions
+ * find_bytes() - creates character array from image file, to
+ * make use in exif library functions
*/
/*
* Include necessary headers...
*/
+
#include "image-private.h"
static int flush_tile(cups_image_t *img);
static cups_ib_t *get_tile(cups_image_t *img, int x, int y);
+static void trim_spaces(char *buf);
+static char *find_bytes(FILE *fp, int *size);
/*
free(pixels);
return temp;
}
+
+#ifdef HAVE_EXIF
+/*
+ helper function required by EXIF read function
+ */
+
+static void trim_spaces(char *buf)
+{
+ char *s = buf - 1;
+ for (; *buf; ++buf)
+ {
+ if (*buf != ' ')
+ s = buf;
+ }
+ *++s = 0; /* null terminate the string on the first of the final spaces */
+}
+
+/*
+ implementation for EXIF read function
+ */
+
+/*
+ helper function to extract bytes from image files
+ */
+
+static char *find_bytes(FILE *fp, int *size)
+{
+ char *buf;
+
+ long int originalOffset = ftell(fp);
+ fseek(fp, 0L, SEEK_END);
+
+ // calculating the size of the file
+ long int res = ftell(fp);
+
+ buf = (char *)malloc(res * sizeof(char) + 1);
+ fseek(fp, 0, SEEK_SET);
+
+ fread(buf, res, 1, fp);
+
+ fseek(fp, originalOffset, SEEK_SET);
+ *size = res + 1;
+
+ return buf;
+}
+
+int _cupsImageReadEXIF(cf_image_t *img, FILE *fp)
+{
+
+ if (fp == NULL)
+ {
+ return -1;
+ }
+
+ int bufSize = 0;
+
+ char *buf = find_bytes(fp, &bufSize);
+
+ ExifData *ed = exif_data_new_from_data(buf, bufSize);
+
+ if (ed == NULL)
+ {
+ DEBUG_printf(("DEBUG: No EXIF data found"));
+ return 2;
+ }
+
+ ExifIfd ifd = EXIF_IFD_0;
+ ExifTag tagX = EXIF_TAG_X_RESOLUTION;
+ ExifTag tagY = EXIF_TAG_Y_RESOLUTION;
+
+ ExifEntry *entryX = exif_content_get_entry(ed->ifd[ifd], tagX);
+
+ ExifEntry *entryY = exif_content_get_entry(ed->ifd[ifd], tagY);
+
+ if (entryX == NULL || entryY == NULL)
+ {
+ DEBUG_printf(("DEBUG: No EXIF data found"));
+ return 2;
+ }
+
+ if (entryX)
+ {
+ char buf1[1024];
+
+ exif_entry_get_value(entryX, buf1, sizeof(buf1));
+
+ trim_spaces(buf1);
+
+ if (*buf1)
+ {
+ int xRes;
+ sscanf(buf1, "%d", &xRes);
+ img->xppi = xRes;
+ }
+ else{
+ return 2;
+ }
+ }
+
+ if (entryY)
+ {
+ char buf2[1024];
+
+ exif_entry_get_value(entryY, buf2, sizeof(buf2));
+ trim_spaces(buf2);
+
+ if (*buf2)
+ {
+ int yRes;
+ sscanf(buf2, "%d", &yRes);
+ img->yppi = yRes;
+ }
+ else{
+ return 2;
+ }
+ }
+
+ return 1;
+}
+#endif