/* Functions for image support on window system.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
-This file is part of GNU Emacs.
+ This file is part of GNU Emacs.
-GNU Emacs 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 3 of the License, or
-(at your option) any later version.
+ GNU Emacs 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 3 of the License, or
+ (at your option) any later version.
-GNU Emacs 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.
+ GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU General Public License
+ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
#define PIX_MASK_DRAW 1
#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
-#define x_defined_color(f, name, color_def, alloc) \
+#define x_defined_color(f, name, color_def, alloc) \
ns_defined_color (f, name, color_def, alloc, 0)
#define FRAME_X_SCREEN(f) 0
#define DefaultDepthOfScreen(screen) x_display_list->n_planes
#ifdef HAVE_NS
void *bitmap = ns_image_from_XBM (bits, width, height);
if (!bitmap)
- return -1;
+ return -1;
#endif
id = x_allocate_bitmap_record (f);
void *bitmap = ns_image_from_file (file);
if (!bitmap)
- return -1;
+ return -1;
id = x_allocate_bitmap_record (f);
/***********************************************************************
Image types
- ***********************************************************************/
+***********************************************************************/
/* Value is the number of elements of vector VECTOR. */
Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data;
Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation;
/* Other symbols. */
static int x_build_heuristic_mask (struct frame *, struct image *,
Lisp_Object);
-#define CACHE_IMAGE_TYPE(type, status) \
+#define CACHE_IMAGE_TYPE(type, status) \
do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
-#define ADD_IMAGE_TYPE(type) \
+#define ADD_IMAGE_TYPE(type) \
do { Vimage_types = Fcons (type, Vimage_types); } while (0)
/* Define a new image type from TYPE. This adds a copy of TYPE to
\f
/***********************************************************************
Image specifications
- ***********************************************************************/
+***********************************************************************/
enum image_value_type
-{
- IMAGE_DONT_CHECK_VALUE_TYPE,
- IMAGE_STRING_VALUE,
- IMAGE_STRING_OR_NIL_VALUE,
- IMAGE_SYMBOL_VALUE,
- IMAGE_POSITIVE_INTEGER_VALUE,
- IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
- IMAGE_NON_NEGATIVE_INTEGER_VALUE,
- IMAGE_ASCENT_VALUE,
- IMAGE_INTEGER_VALUE,
- IMAGE_FUNCTION_VALUE,
- IMAGE_NUMBER_VALUE,
- IMAGE_BOOL_VALUE
-};
+ {
+ IMAGE_DONT_CHECK_VALUE_TYPE,
+ IMAGE_STRING_VALUE,
+ IMAGE_STRING_OR_NIL_VALUE,
+ IMAGE_SYMBOL_VALUE,
+ IMAGE_POSITIVE_INTEGER_VALUE,
+ IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
+ IMAGE_NON_NEGATIVE_INTEGER_VALUE,
+ IMAGE_ASCENT_VALUE,
+ IMAGE_INTEGER_VALUE,
+ IMAGE_FUNCTION_VALUE,
+ IMAGE_NUMBER_VALUE,
+ IMAGE_BOOL_VALUE
+ };
/* Structure used when parsing image specifications. */
\f
/***********************************************************************
Image type independent image structures
- ***********************************************************************/
+***********************************************************************/
static struct image *make_image (Lisp_Object spec, unsigned hash);
static void free_image (struct frame *f, struct image *img);
#ifdef HAVE_NTGUI
-#define Destroy_Image(img_dc, prev) \
+#define Destroy_Image(img_dc, prev) \
do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
-#define Free_Pixmap(display, pixmap) \
+#define Free_Pixmap(display, pixmap) \
DeleteObject (pixmap)
#elif defined (HAVE_NS)
#else
-#define Destroy_Image(ximg, dummy) \
+#define Destroy_Image(ximg, dummy) \
XDestroyImage (ximg)
-#define Free_Pixmap(display, pixmap) \
+#define Free_Pixmap(display, pixmap) \
XFreePixmap (display, pixmap)
#endif /* !HAVE_NTGUI && !HAVE_NS */
\f
/***********************************************************************
Helper functions for X image types
- ***********************************************************************/
+***********************************************************************/
static void x_clear_image_1 (struct frame *, struct image *, int,
int, int);
\f
/***********************************************************************
Image Cache
- ***********************************************************************/
+***********************************************************************/
static struct image *search_image_cache (struct frame *, Lisp_Object, unsigned);
static void cache_image (struct frame *f, struct image *img);
DEFUN ("image-flush", Fimage_flush, Simage_flush,
1, 2, 0,
doc: /* Fush the image with specification SPEC on frame FRAME.
-This removes the image from the Emacs image cache. If SPEC specifies
-an image file, the next redisplay of this image will read from the
-current contents of that file.
+ This removes the image from the Emacs image cache. If SPEC specifies
+ an image file, the next redisplay of this image will read from the
+ current contents of that file.
FRAME nil or omitted means use the selected frame.
FRAME t means refresh the image on all frames. */)
\f
/***********************************************************************
X / NS / W32 support code
- ***********************************************************************/
+***********************************************************************/
#ifdef HAVE_NTGUI
#define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
/* Macro for loading those image functions from the library. */
-#define LOAD_IMGLIB_FN(lib,func) { \
- fn_##func = (void *) GetProcAddress (lib, #func); \
- if (!fn_##func) return 0; \
+#define LOAD_IMGLIB_FN(lib,func) { \
+ fn_##func = (void *) GetProcAddress (lib, #func); \
+ if (!fn_##func) return 0; \
}
/* Load a DLL implementing an image type.
\f
/***********************************************************************
File Handling
- ***********************************************************************/
+***********************************************************************/
static unsigned char *slurp_file (char *, int *);
\f
/***********************************************************************
XBM images
- ***********************************************************************/
+***********************************************************************/
static int xbm_scan (unsigned char **, unsigned char *, char *, int *);
static int xbm_load (struct frame *f, struct image *img);
/* Indices of image specification fields in xbm_format, below. */
enum xbm_keyword_index
-{
- XBM_TYPE,
- XBM_FILE,
- XBM_WIDTH,
- XBM_HEIGHT,
- XBM_DATA,
- XBM_FOREGROUND,
- XBM_BACKGROUND,
- XBM_ASCENT,
- XBM_MARGIN,
- XBM_RELIEF,
- XBM_ALGORITHM,
- XBM_HEURISTIC_MASK,
- XBM_MASK,
- XBM_LAST
-};
+ {
+ XBM_TYPE,
+ XBM_FILE,
+ XBM_WIDTH,
+ XBM_HEIGHT,
+ XBM_DATA,
+ XBM_FOREGROUND,
+ XBM_BACKGROUND,
+ XBM_ASCENT,
+ XBM_MARGIN,
+ XBM_RELIEF,
+ XBM_ALGORITHM,
+ XBM_HEURISTIC_MASK,
+ XBM_MASK,
+ XBM_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid XBM image specifications. */
static const struct image_keyword xbm_format[XBM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
- {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
- {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ };
/* Structure describing the image type XBM. */
static struct image_type xbm_type =
-{
- &Qxbm,
- xbm_image_p,
- xbm_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qxbm,
+ xbm_image_p,
+ xbm_load,
+ x_clear_image,
+ NULL
+ };
/* Tokens returned from xbm_scan. */
enum xbm_token
-{
- XBM_TK_IDENT = 256,
- XBM_TK_NUMBER
-};
+ {
+ XBM_TK_IDENT = 256,
+ XBM_TK_NUMBER
+ };
/* Return non-zero if OBJECT is a valid XBM-type image specification.
int value;
int LA1;
-#define match() \
- LA1 = xbm_scan (&s, end, buffer, &value)
+#define match() \
+ LA1 = xbm_scan (&s, end, buffer, &value)
-#define expect(TOKEN) \
- if (LA1 != (TOKEN)) \
- goto failure; \
- else \
- match ()
+#define expect(TOKEN) \
+ if (LA1 != (TOKEN)) \
+ goto failure; \
+ else \
+ match ()
#define expect_ident(IDENT) \
- if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
- match (); \
- else \
- goto failure
+ if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
+ match (); \
+ else \
+ goto failure
*width = *height = -1;
if (data)
\f
/***********************************************************************
XPM images
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_XPM) || defined (HAVE_NS)
/* Indices of image specification fields in xpm_format, below. */
enum xpm_keyword_index
-{
- XPM_TYPE,
- XPM_FILE,
- XPM_DATA,
- XPM_ASCENT,
- XPM_MARGIN,
- XPM_RELIEF,
- XPM_ALGORITHM,
- XPM_HEURISTIC_MASK,
- XPM_MASK,
- XPM_COLOR_SYMBOLS,
- XPM_BACKGROUND,
- XPM_LAST
-};
+ {
+ XPM_TYPE,
+ XPM_FILE,
+ XPM_DATA,
+ XPM_ASCENT,
+ XPM_MARGIN,
+ XPM_RELIEF,
+ XPM_ALGORITHM,
+ XPM_HEURISTIC_MASK,
+ XPM_MASK,
+ XPM_COLOR_SYMBOLS,
+ XPM_BACKGROUND,
+ XPM_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid XPM image specifications. */
static const struct image_keyword xpm_format[XPM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type XPM. */
static struct image_type xpm_type =
-{
- &Qxpm,
- xpm_image_p,
- xpm_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qxpm,
+ xpm_image_p,
+ xpm_load,
+ x_clear_image,
+ NULL
+ };
#ifdef HAVE_X_WINDOWS
/* Tokens returned from xpm_scan. */
enum xpm_token
-{
- XPM_TK_IDENT = 256,
- XPM_TK_STRING,
- XPM_TK_EOF
-};
+ {
+ XPM_TK_IDENT = 256,
+ XPM_TK_STRING,
+ XPM_TK_EOF
+ };
/* Scan an XPM data and return a character (< 256) or a token defined
by enum xpm_token above. *S and END are the start (inclusive) and
*beg = *s - 1;
while (*s < end
&& (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
- ++*s;
+ ++*s;
*len = *s - *beg;
return XPM_TK_IDENT;
}
int best_key, have_mask = 0;
XImagePtr ximg = NULL, mask_img = NULL;
-#define match() \
- LA1 = xpm_scan (&s, end, &beg, &len)
+#define match() \
+ LA1 = xpm_scan (&s, end, &beg, &len)
-#define expect(TOKEN) \
- if (LA1 != (TOKEN)) \
- goto failure; \
- else \
- match ()
+#define expect(TOKEN) \
+ if (LA1 != (TOKEN)) \
+ goto failure; \
+ else \
+ match ()
-#define expect_ident(IDENT) \
- if (LA1 == XPM_TK_IDENT \
- && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
- match (); \
- else \
- goto failure
+#define expect_ident(IDENT) \
+ if (LA1 == XPM_TK_IDENT \
+ && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
+ match (); \
+ else \
+ goto failure
if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
goto failure;
\f
/***********************************************************************
Color table
- ***********************************************************************/
+***********************************************************************/
#ifdef COLOR_TABLE_SUPPORT
\f
/***********************************************************************
Algorithms
- ***********************************************************************/
+***********************************************************************/
static XColor *x_to_xcolors (struct frame *, struct image *, int);
static void x_from_xcolors (struct frame *, struct image *, XColor *);
strategies. */
static int emboss_matrix[9] = {
- /* x - 1 x x + 1 */
- 2, -1, 0, /* y - 1 */
- -1, 0, 1, /* y */
- 0, 1, -2 /* y + 1 */
+ /* x - 1 x x + 1 */
+ 2, -1, 0, /* y - 1 */
+ -1, 0, 1, /* y */
+ 0, 1, -2 /* y + 1 */
};
static int laplace_matrix[9] = {
- /* x - 1 x x + 1 */
- 1, 0, 0, /* y - 1 */
- 0, 0, 0, /* y */
- 0, 0, -1 /* y + 1 */
+ /* x - 1 x x + 1 */
+ 1, 0, 0, /* y - 1 */
+ 0, 0, 0, /* y */
+ 0, 0, -1 /* y + 1 */
};
/* Value is the intensity of the color whose red/green/blue values
\f
/***********************************************************************
PBM (mono, gray, color)
- ***********************************************************************/
+***********************************************************************/
static int pbm_image_p (Lisp_Object object);
static int pbm_load (struct frame *f, struct image *img);
/* Indices of image specification fields in gs_format, below. */
enum pbm_keyword_index
-{
- PBM_TYPE,
- PBM_FILE,
- PBM_DATA,
- PBM_ASCENT,
- PBM_MARGIN,
- PBM_RELIEF,
- PBM_ALGORITHM,
- PBM_HEURISTIC_MASK,
- PBM_MASK,
- PBM_FOREGROUND,
- PBM_BACKGROUND,
- PBM_LAST
-};
+ {
+ PBM_TYPE,
+ PBM_FILE,
+ PBM_DATA,
+ PBM_ASCENT,
+ PBM_MARGIN,
+ PBM_RELIEF,
+ PBM_ALGORITHM,
+ PBM_HEURISTIC_MASK,
+ PBM_MASK,
+ PBM_FOREGROUND,
+ PBM_BACKGROUND,
+ PBM_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword pbm_format[PBM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `pbm'. */
static struct image_type pbm_type =
-{
- &Qpbm,
- pbm_image_p,
- pbm_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qpbm,
+ pbm_image_p,
+ pbm_load,
+ x_clear_image,
+ NULL
+ };
/* Return non-zero if OBJECT is a valid PBM image specification. */
\f
/***********************************************************************
PNG
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_PNG) || defined (HAVE_NS)
/* Indices of image specification fields in png_format, below. */
enum png_keyword_index
-{
- PNG_TYPE,
- PNG_DATA,
- PNG_FILE,
- PNG_ASCENT,
- PNG_MARGIN,
- PNG_RELIEF,
- PNG_ALGORITHM,
- PNG_HEURISTIC_MASK,
- PNG_MASK,
- PNG_BACKGROUND,
- PNG_LAST
-};
+ {
+ PNG_TYPE,
+ PNG_DATA,
+ PNG_FILE,
+ PNG_ASCENT,
+ PNG_MARGIN,
+ PNG_RELIEF,
+ PNG_ALGORITHM,
+ PNG_HEURISTIC_MASK,
+ PNG_MASK,
+ PNG_BACKGROUND,
+ PNG_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword png_format[PNG_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `png'. */
static struct image_type png_type =
-{
- &Qpng,
- png_image_p,
- png_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qpng,
+ png_image_p,
+ png_load,
+ x_clear_image,
+ NULL
+ };
/* Return non-zero if OBJECT is a valid PNG image specification. */
\f
/***********************************************************************
JPEG
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_JPEG) || defined (HAVE_NS)
/* Indices of image specification fields in gs_format, below. */
enum jpeg_keyword_index
-{
- JPEG_TYPE,
- JPEG_DATA,
- JPEG_FILE,
- JPEG_ASCENT,
- JPEG_MARGIN,
- JPEG_RELIEF,
- JPEG_ALGORITHM,
- JPEG_HEURISTIC_MASK,
- JPEG_MASK,
- JPEG_BACKGROUND,
- JPEG_LAST
-};
+ {
+ JPEG_TYPE,
+ JPEG_DATA,
+ JPEG_FILE,
+ JPEG_ASCENT,
+ JPEG_MARGIN,
+ JPEG_RELIEF,
+ JPEG_ALGORITHM,
+ JPEG_HEURISTIC_MASK,
+ JPEG_MASK,
+ JPEG_BACKGROUND,
+ JPEG_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword jpeg_format[JPEG_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `jpeg'. */
static struct image_type jpeg_type =
-{
- &Qjpeg,
- jpeg_image_p,
- jpeg_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qjpeg,
+ jpeg_image_p,
+ jpeg_load,
+ x_clear_image,
+ NULL
+ };
/* Return non-zero if OBJECT is a valid JPEG image specification. */
struct jpeg_stdio_mgr *src;
if (cinfo->src != NULL)
- src = (struct jpeg_stdio_mgr *) cinfo->src;
+ src = (struct jpeg_stdio_mgr *) cinfo->src;
else
{
/* First time for this JPEG object? */
sizeof (struct jpeg_stdio_mgr));
src = (struct jpeg_stdio_mgr *) cinfo->src;
src->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- JPEG_STDIO_BUFFER_SIZE);
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ JPEG_STDIO_BUFFER_SIZE);
}
src->file = fp;
}
/* Create the JPEG decompression object. Let it read from fp.
- Read the JPEG image header. */
+ Read the JPEG image header. */
fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
if (NILP (specified_data))
fn_jpeg_read_header (&cinfo, 1);
/* Customize decompression so that color quantization will be used.
- Start decompression. */
+ Start decompression. */
cinfo.quantize_colors = 1;
fn_jpeg_start_decompress (&cinfo);
width = img->width = cinfo.output_width;
\f
/***********************************************************************
TIFF
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_TIFF) || defined (HAVE_NS)
/* Indices of image specification fields in tiff_format, below. */
enum tiff_keyword_index
-{
- TIFF_TYPE,
- TIFF_DATA,
- TIFF_FILE,
- TIFF_ASCENT,
- TIFF_MARGIN,
- TIFF_RELIEF,
- TIFF_ALGORITHM,
- TIFF_HEURISTIC_MASK,
- TIFF_MASK,
- TIFF_BACKGROUND,
- TIFF_INDEX,
- TIFF_LAST
-};
+ {
+ TIFF_TYPE,
+ TIFF_DATA,
+ TIFF_FILE,
+ TIFF_ASCENT,
+ TIFF_MARGIN,
+ TIFF_RELIEF,
+ TIFF_ALGORITHM,
+ TIFF_HEURISTIC_MASK,
+ TIFF_MASK,
+ TIFF_BACKGROUND,
+ TIFF_INDEX,
+ TIFF_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword tiff_format[TIFF_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
- {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
+ };
/* Structure describing the image type `tiff'. */
static struct image_type tiff_type =
-{
- &Qtiff,
- tiff_image_p,
- tiff_load,
- x_clear_image,
- NULL
-};
+ {
+ &Qtiff,
+ tiff_image_p,
+ tiff_load,
+ x_clear_image,
+ NULL
+ };
/* Return non-zero if OBJECT is a valid TIFF image specification. */
size_t len;
int index;
}
-tiff_memory_source;
+ tiff_memory_source;
static size_t
tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
\f
/***********************************************************************
GIF
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_GIF) || defined (HAVE_NS)
/* Indices of image specification fields in gif_format, below. */
enum gif_keyword_index
-{
- GIF_TYPE,
- GIF_DATA,
- GIF_FILE,
- GIF_ASCENT,
- GIF_MARGIN,
- GIF_RELIEF,
- GIF_ALGORITHM,
- GIF_HEURISTIC_MASK,
- GIF_MASK,
- GIF_IMAGE,
- GIF_BACKGROUND,
- GIF_LAST
-};
+ {
+ GIF_TYPE,
+ GIF_DATA,
+ GIF_FILE,
+ GIF_ASCENT,
+ GIF_MARGIN,
+ GIF_RELIEF,
+ GIF_ALGORITHM,
+ GIF_HEURISTIC_MASK,
+ GIF_MASK,
+ GIF_IMAGE,
+ GIF_BACKGROUND,
+ GIF_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword gif_format[GIF_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `gif'. */
static struct image_type gif_type =
-{
- &Qgif,
- gif_image_p,
- gif_load,
- gif_clear_image,
- NULL
-};
+ {
+ &Qgif,
+ gif_image_p,
+ gif_load,
+ gif_clear_image,
+ NULL
+ };
/* Free X resources of GIF image IMG which is used on frame F. */
size_t len;
int index;
}
-gif_memory_source;
+ gif_memory_source;
/* Make the current memory source available to gif_read_from_memory.
It's done this way because not all versions of libungif support
#endif /* HAVE_GIF */
+/***********************************************************************
+ imagemagick
+***********************************************************************/
+#if defined (HAVE_IMAGEMAGICK)
+Lisp_Object Vimagemagick_render_type;
+
+/* The symbol `imagemagick' identifying images of this type. */
+
+Lisp_Object Qimagemagick;
+Lisp_Object Vimagemagick_render_type;
+
+/* Indices of image specification fields in imagemagick_format, below. */
+
+enum imagemagick_keyword_index
+ {
+ IMAGEMAGICK_TYPE,
+ IMAGEMAGICK_DATA,
+ IMAGEMAGICK_FILE,
+ IMAGEMAGICK_ASCENT,
+ IMAGEMAGICK_MARGIN,
+ IMAGEMAGICK_RELIEF,
+ IMAGEMAGICK_ALGORITHM,
+ IMAGEMAGICK_HEURISTIC_MASK,
+ IMAGEMAGICK_MASK,
+ IMAGEMAGICK_BACKGROUND,
+ IMAGEMAGICK_HEIGHT,
+ IMAGEMAGICK_WIDTH,
+ IMAGEMAGICK_ROTATION,
+ IMAGEMAGICK_CROP,
+ IMAGEMAGICK_LAST
+ };
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":height", IMAGE_INTEGER_VALUE, 0},
+ {":width", IMAGE_INTEGER_VALUE, 0},
+ {":rotation", IMAGE_NUMBER_VALUE, 0},
+ {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ };
+/* Free X resources of imagemagick image IMG which is used on frame F. */
+
+static void
+imagemagick_clear_image (struct frame *f,
+ struct image *img)
+{
+ printf("clearing imagemagick image\n");
+ x_clear_image (f, img);
+}
+
+
+
+/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do
+ this by calling parse_image_spec and supplying the keywords that
+ identify the IMAGEMAGICK format. */
+
+static int
+imagemagick_image_p (Lisp_Object object)
+{
+ struct image_keyword fmt[IMAGEMAGICK_LAST];
+ bcopy (imagemagick_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
+}
+
+/* The GIF library also defines DrawRectangle, but its never used in Emacs.
+ Therefore rename the function so it doesnt collide with ImageMagick. */
+#define DrawRectangle DrawRectangleGif
+#include <wand/MagickWand.h>
+
+/* imagemagick_load_image is a helper function for imagemagick_load,
+ which does the actual loading given contents and size, apart from
+ frame and image structures, passed from imagemagick_load.
+
+ Uses librimagemagick to do most of the image processing.
+
+ non-zero when successful.
+*/
+
+static int
+imagemagick_load_image (/* Pointer to emacs frame structure. */
+ struct frame *f,
+ /* Pointer to emacs image structure. */
+ struct image *img,
+ /* String containing the IMAGEMAGICK data to
+ be parsed. */
+ unsigned char *contents,
+ /* Size of data in bytes. */
+ unsigned int size,
+ /* Filename, either pass filename or
+ contents/size. */
+ unsigned char *filename)
+{
+ size_t width;
+ size_t height;
+
+ MagickBooleanType
+ status;
+
+ XImagePtr ximg;
+ Lisp_Object specified_bg;
+ XColor background;
+ int x;
+ int y;
+
+ MagickWand *image_wand;
+ MagickWand *ping_wand;
+ PixelIterator *iterator;
+ PixelWand **pixels;
+ MagickPixelPacket pixel;
+ Lisp_Object image;
+ Lisp_Object value;
+ Lisp_Object crop, geometry;
+ long ino;
+ int desired_width, desired_height;
+ double rotation;
+ int imagemagick_rendermethod;
+ int pixelwidth;
+ ImageInfo *image_info;
+ ExceptionInfo *exception;
+ Image * im_image;
+
+
+ /* Handle image index for image types who can contain more than one
+ image. Interface :index is same as for GIF. First we "ping" the
+ image to see how many sub-images it contains. Pinging is faster
+ than loading the image to find out things about it.
+ */
+ printf("im ping file %s\n", filename);
+ image = image_spec_value (img->spec, QCindex, NULL);
+ ino = INTEGERP (image) ? XFASTINT (image) : 0;
+ ping_wand=NewMagickWand();
+ MagickSetResolution(ping_wand, 2, 2);
+ if (filename != NULL)
+ {
+ status = MagickPingImage(ping_wand, filename);
+ }
+ else
+ {
+ status = MagickPingImageBlob(ping_wand, contents, size);
+ }
+
+ if (ino >= MagickGetNumberImages(ping_wand))
+ {
+ image_error ("Invalid image number `%s' in image `%s'",
+ image, img->spec);
+ UNGCPRO;
+ return 0;
+ }
+
+ if (MagickGetNumberImages(ping_wand) > 1)
+ img->data.lisp_val =
+ Fcons (Qcount,
+ Fcons (make_number (MagickGetNumberImages(ping_wand)),
+ img->data.lisp_val));
+
+ DestroyMagickWand (ping_wand);
+ /* Now, after pinging, we know how many images are inside the
+ file. If its not a bundle, just one.
+ */
+
+ if (filename != NULL)
+ {
+ printf("im read file %s\n", filename);
+ image_info=CloneImageInfo((ImageInfo *) NULL);
+ (void) strcpy(image_info->filename, filename);
+ image_info -> number_scenes = 1;
+ image_info -> scene = ino;
+ exception=AcquireExceptionInfo();
+
+ im_image = ReadImage (image_info, exception);
+ CatchException(exception);
+
+ printf("im wand from image\n");
+ image_wand = NewMagickWandFromImage(im_image);
+ }
+ else
+ {
+ image_wand = NewMagickWand();
+ status = MagickReadImageBlob(image_wand, contents, size);
+ }
+ image_error ("im read failed", Qnil, Qnil);
+ if (status == MagickFalse) goto imagemagick_error;
+
+
+ /* if(ino == 0) */
+ /* MagickSetFirstIterator(image_wand); */
+ /* else */
+ /* MagickSetIteratorIndex(image_wand, ino); */
+
+ //MagickSetFirstIterator(image_wand);
+
+
+ /* If width and/or height is set in the display spec assume we want
+ to scale to those values. if either h or w is unspecified, the
+ unspecified should be calculated from the specified to preserve
+ aspect ratio. */
+
+ value = image_spec_value (img->spec, QCwidth, NULL);
+ desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
+ value = image_spec_value (img->spec, QCheight, NULL);
+ desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
+
+ height = MagickGetImageHeight (image_wand);
+ width = MagickGetImageWidth (image_wand);
+
+ if(desired_width != -1 && desired_height == -1)
+ {
+ /* w known, calculate h*/
+ desired_height = ( (double)desired_width / width ) * height;
+ }
+ if(desired_width == -1 && desired_height != -1)
+ {
+ /* h known, calculate w*/
+ desired_width = ( (double)desired_height / height ) * width;
+ }
+ if(desired_width != -1 && desired_height != -1)
+ {
+ printf("MagickScaleImage %d %d\n", desired_width, desired_height);
+ status = MagickScaleImage(image_wand, desired_width, desired_height);
+ if (status == MagickFalse) {
+ image_error ("Imagemagick scale failed", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+ }
+
+
+ /* crop behaves similar to image slicing in Emacs but is more memory
+ efficient */
+ crop = image_spec_value (img->spec, QCcrop, NULL);
+
+ if(CONSP (crop))
+ {
+ /*
+ after some testing, it seems MagickCropImage is the fastest
+ crop function in ImageMagick. This crop function seems to do
+ less copying than the alternatives, but it still reads the
+ entire image into memory before croping, which is aparently
+ difficult to avoid when using imagemagick.
+ */
+
+ int w,h,x,y;
+ w=XFASTINT(XCAR(crop));
+ h=XFASTINT(XCAR(XCDR(crop)));
+ x=XFASTINT(XCAR(XCDR(XCDR(crop))));
+ y=XFASTINT(XCAR(XCDR(XCDR(XCDR(crop)))));
+ printf("MagickCropImage(image_wand, %d,%d, %d,%d)\n", w, h, x, y);
+ MagickCropImage(image_wand, w,h, x,y);
+ }
+
+ /* Furthermore :rotation. we need background color and angle for
+ rotation. */
+ /*
+ TODO background handling for rotation specified_bg =
+ image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP
+ (specified_bg)
+ */
+ value = image_spec_value (img->spec, QCrotation, NULL);
+ if (FLOATP (value))
+ {
+ PixelWand* background = NewPixelWand();
+ PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/
+
+ rotation = extract_float (value);
+ printf ("MagickRotateImage %f\n", rotation);
+
+ status = MagickRotateImage (image_wand, background, rotation);
+ DestroyPixelWand (background);
+ if (status == MagickFalse)
+ {
+ image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+ }
+
+ /* Finaly we are done manipulating the image, figure out resulting
+ width, height, and then transfer ownerwship to Emacs.
+ */
+ height = MagickGetImageHeight (image_wand);
+ width = MagickGetImageWidth (image_wand);
+ if (status == MagickFalse)
+ {
+ image_error ("Imagemagick image get size failed", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+ if (! check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+ /* We can now get a valid pixel buffer from the imagemagick file, if all
+ went ok. */
+
+
+ init_color_table ();
+ imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type)
+ ? XFASTINT (Vimagemagick_render_type) : 0);
+ if (imagemagick_rendermethod == 0)
+ {
+ /* Try to create a x pixmap to hold the imagemagick pixmap. */
+ if (!x_create_x_image_and_pixmap (f, width, height, 0,
+ &ximg, &img->pixmap))
+ {
+ image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+ /* Copy imagegmagick image to x with primitive yet robust pixel
+ pusher loop. This has been tested a lot with many different
+ images.
+ */
+
+ /* Copy pixels from the imagemagick image structure to the x image map. */
+ iterator = NewPixelIterator (image_wand);
+ if ((iterator == (PixelIterator *) NULL))
+ {
+ image_error ("Imagemagick pixel iterator creation failed",
+ Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+ for (y = 0; y < (long) MagickGetImageHeight(image_wand); y++)
+ {
+ pixels = PixelGetNextIteratorRow (iterator, &width);
+ if ((pixels == (PixelWand **) NULL))
+ break;
+ for (x = 0; x < (long) width; x++)
+ {
+ PixelGetMagickColor (pixels[x], &pixel);
+ XPutPixel (ximg, x, y,
+ lookup_rgb_color (f,
+ pixel.red,
+ pixel.green,
+ pixel.blue));
+ }
+ }
+ DestroyPixelIterator (iterator);
+ }
+
+ if (imagemagick_rendermethod == 1)
+ {
+ /* Try if magicexportimage is any faster than pixelpushing. */
+ int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
+ char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
+ /* Try to create a x pixmap to hold the imagemagick pixmap. */
+ printf("imagedepth:%d exportdepth:%s\n", imagedepth, exportdepth);
+ if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
+ &ximg, &img->pixmap)){
+ image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+ goto imagemagick_error;
+ }
+
+
+ /* Oddly, the below code doesnt seem to work:*/
+ /* switch(ximg->bitmap_unit){ */
+ /* case 8: */
+ /* pixelwidth=CharPixel; */
+ /* break; */
+ /* case 16: */
+ /* pixelwidth=ShortPixel; */
+ /* break; */
+ /* case 32: */
+ /* pixelwidth=LongPixel; */
+ /* break; */
+ /* } */
+ /*
+ Here im just guessing the format of the bitmap.
+ happens to work fine for:
+ - bw djvu images
+ on rgb display.
+ seems about 3 times as fast as pixel pushing(not carefully measured)
+ */
+ pixelwidth = CharPixel;/*??? TODO figure out*/
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+ MagickExportImagePixels(image_wand,
+ 0, 0,
+ width, height,
+ exportdepth,
+ pixelwidth,
+ /*&(img->pixmap));*/
+ ximg->data);
+#else
+ image_error("You dont have MagickExportImagePixels, upgrade ImageMagick!",
+ Qnil, Qnil);
+#endif
+ }
+
+
+#ifdef COLOR_TABLE_SUPPORT
+ /* Remember colors allocated for this image. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+#endif /* COLOR_TABLE_SUPPORT */
+
+
+ img->width = width;
+ img->height = height;
+
+ /* Put the image into the pixmap, then free the X image and its
+ buffer. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+
+
+ /* Final cleanup. image_wand should be the only resource left. */
+ DestroyMagickWand (image_wand);
+
+ return 1;
+
+ imagemagick_error:
+ /* TODO more cleanup. */
+ image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
+ printf("Imagemagick error, see *Messages*\n");
+ return 0;
+}
+
+
+/* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if
+ successful. this function will go into the imagemagick_type structure, and
+ the prototype thus needs to be compatible with that structure. */
+
+static int
+imagemagick_load (struct frame *f,
+ struct image *img)
+{
+ int success_p = 0;
+ Lisp_Object file_name;
+
+ /* If IMG->spec specifies a file name, create a non-file spec from it. */
+ file_name = image_spec_value (img->spec, QCfile, NULL);
+ if (STRINGP (file_name))
+ {
+ Lisp_Object file;
+ unsigned char *contents;
+ int size;
+ struct gcpro gcpro1;
+
+ file = x_find_image_file (file_name);
+ GCPRO1 (file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", file_name, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ success_p = imagemagick_load_image (f, img, 0, 0, SDATA(file_name));
+ UNGCPRO;
+ }
+ /* Else its not a file, its a lisp object. Load the image from a
+ lisp object rather than a file. */
+ else
+ {
+ Lisp_Object data;
+
+ data = image_spec_value (img->spec, QCdata, NULL);
+ success_p = imagemagick_load_image (f, img, SDATA (data),
+ SBYTES (data), NULL);
+ }
+
+ return success_p;
+}
+
+/* Structure describing the image type `imagemagick'. Its the same
+ type of structure defined for all image formats, handled by Emacs
+ image functions. See struct image_type in dispextern.h. */
+
+static struct image_type imagemagick_type =
+ {
+ /* An identifier showing that this is an image structure for the
+ IMAGEMAGICK format. */
+ &Qimagemagick,
+ /* Handle to a function that can be used to identify a IMAGEMAGICK
+ file. */
+ imagemagick_image_p,
+ /* Handle to function used to load a IMAGEMAGICK file. */
+ imagemagick_load,
+ /* Handle to function to free resources for IMAGEMAGICK. */
+ imagemagick_clear_image,
+ /* An internal field to link to the next image type in a list of
+ image types, will be filled in when registering the format. */
+ NULL
+ };
+
+
+
+
+DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
+ doc: /* Return image file types supported by ImageMagick.
+ Since ImageMagick recognizes a lot of file-types that clash with Emacs,
+ such as .c, we want to be able to alter the list at the lisp level. */)
+ (void)
+{
+ Lisp_Object typelist = Qnil;
+ size_t numf;
+ ExceptionInfo ex;
+ char** imtypes = GetMagickList ("*", &numf, &ex);
+ int i;
+ Lisp_Object Qimagemagicktype;
+ for (i = 0; i < numf; i++)
+ {
+ Qimagemagicktype = intern (imtypes[i]);
+ typelist = Fcons (Qimagemagicktype, typelist);
+ }
+ return typelist;
+}
+
+#endif /* defined (HAVE_IMAGEMAGICK) */
+
+
\f
/***********************************************************************
SVG
- ***********************************************************************/
+***********************************************************************/
#if defined (HAVE_RSVG)
/* Indices of image specification fields in svg_format, below. */
enum svg_keyword_index
-{
- SVG_TYPE,
- SVG_DATA,
- SVG_FILE,
- SVG_ASCENT,
- SVG_MARGIN,
- SVG_RELIEF,
- SVG_ALGORITHM,
- SVG_HEURISTIC_MASK,
- SVG_MASK,
- SVG_BACKGROUND,
- SVG_LAST
-};
+ {
+ SVG_TYPE,
+ SVG_DATA,
+ SVG_FILE,
+ SVG_ASCENT,
+ SVG_MARGIN,
+ SVG_RELIEF,
+ SVG_ALGORITHM,
+ SVG_HEURISTIC_MASK,
+ SVG_MASK,
+ SVG_BACKGROUND,
+ SVG_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword svg_format[SVG_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `svg'. Its the same type of
structure defined for all image formats, handled by emacs image
functions. See struct image_type in dispextern.h. */
static struct image_type svg_type =
-{
- /* An identifier showing that this is an image structure for the SVG format. */
- &Qsvg,
- /* Handle to a function that can be used to identify a SVG file. */
- svg_image_p,
- /* Handle to function used to load a SVG file. */
- svg_load,
- /* Handle to function to free sresources for SVG. */
- x_clear_image,
- /* An internal field to link to the next image type in a list of
- image types, will be filled in when registering the format. */
- NULL
-};
+ {
+ /* An identifier showing that this is an image structure for the SVG format. */
+ &Qsvg,
+ /* Handle to a function that can be used to identify a SVG file. */
+ svg_image_p,
+ /* Handle to function used to load a SVG file. */
+ svg_load,
+ /* Handle to function to free sresources for SVG. */
+ x_clear_image,
+ /* An internal field to link to the next image type in a list of
+ image types, will be filled in when registering the format. */
+ NULL
+ };
/* Return non-zero if OBJECT is a valid SVG image specification. Do
\f
/***********************************************************************
Ghostscript
- ***********************************************************************/
+***********************************************************************/
#ifdef HAVE_X_WINDOWS
#define HAVE_GHOSTSCRIPT 1
/* Indices of image specification fields in gs_format, below. */
enum gs_keyword_index
-{
- GS_TYPE,
- GS_PT_WIDTH,
- GS_PT_HEIGHT,
- GS_FILE,
- GS_LOADER,
- GS_BOUNDING_BOX,
- GS_ASCENT,
- GS_MARGIN,
- GS_RELIEF,
- GS_ALGORITHM,
- GS_HEURISTIC_MASK,
- GS_MASK,
- GS_BACKGROUND,
- GS_LAST
-};
+ {
+ GS_TYPE,
+ GS_PT_WIDTH,
+ GS_PT_HEIGHT,
+ GS_FILE,
+ GS_LOADER,
+ GS_BOUNDING_BOX,
+ GS_ASCENT,
+ GS_MARGIN,
+ GS_RELIEF,
+ GS_ALGORITHM,
+ GS_HEURISTIC_MASK,
+ GS_MASK,
+ GS_BACKGROUND,
+ GS_LAST
+ };
/* Vector of image_keyword structures describing the format
of valid user-defined image specifications. */
static const struct image_keyword gs_format[GS_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
- {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
- {":loader", IMAGE_FUNCTION_VALUE, 0},
- {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
- {":ascent", IMAGE_ASCENT_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
-};
+ {
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
+ {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 1},
+ {":loader", IMAGE_FUNCTION_VALUE, 0},
+ {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
+ };
/* Structure describing the image type `ghostscript'. */
static struct image_type gs_type =
-{
- &Qpostscript,
- gs_image_p,
- gs_load,
- gs_clear_image,
- NULL
-};
+ {
+ &Qpostscript,
+ gs_image_p,
+ gs_load,
+ gs_clear_image,
+ NULL
+ };
/* Free X resources of Ghostscript image IMG which is used on frame F. */
\f
/***********************************************************************
Tests
- ***********************************************************************/
+***********************************************************************/
#if GLYPH_DEBUG
/***********************************************************************
Initialization
- ***********************************************************************/
+***********************************************************************/
#ifdef HAVE_NTGUI
/* Image types that rely on external libraries are loaded dynamically
DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
doc: /* Initialize image library implementing image type TYPE.
-Return non-nil if TYPE is a supported image type.
+ Return non-nil if TYPE is a supported image type.
Image types pbm and xbm are prebuilt; other types are loaded here.
Libraries to load are specified in alist LIBRARIES (usually, the value
return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
#endif
+#if defined (HAVE_IMAGEMAGICK)
+ if (EQ (type, Qimagemagick)){
+ /* MagickWandGenesis() initalizes the imagemagick library. */
+ MagickWandGenesis();
+ return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
+ libraries);
+ }
+#endif
+
#ifdef HAVE_GHOSTSCRIPT
if (EQ (type, Qpostscript))
return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
return Qnil;
}
+
void
syms_of_image (void)
{
/* Must be defined now becase we're going to update it below, while
defining the supported image types. */
DEFVAR_LISP ("image-types", &Vimage_types,
- doc: /* List of potentially supported image types.
-Each element of the list is a symbol for an image type, like 'jpeg or 'png.
-To check whether it is really supported, use `image-type-available-p'. */);
+ doc: /* List of potentially supported image types.
+ Each element of the list is a symbol for an image type, like 'jpeg or 'png.
+ To check whether it is really supported, use `image-type-available-p'. */);
Vimage_types = Qnil;
DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
- doc: /* Alist of image types vs external libraries needed to display them.
+ doc: /* Alist of image types vs external libraries needed to display them.
Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
representing a supported image type, and the rest are strings giving
Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
DEFVAR_LISP ("max-image-size", &Vmax_image_size,
- doc: /* Maximum size of images.
-Emacs will not load an image into memory if its pixel width or
-pixel height exceeds this limit.
-
-If the value is an integer, it directly specifies the maximum
-image height and width, measured in pixels. If it is a floating
-point number, it specifies the maximum image height and width
-as a ratio to the frame height and width. If the value is
-non-numeric, there is no explicit limit on the size of images. */);
+ doc: /* Maximum size of images.
+ Emacs will not load an image into memory if its pixel width or
+ pixel height exceeds this limit.
+
+ If the value is an integer, it directly specifies the maximum
+ image height and width, measured in pixels. If it is a floating
+ point number, it specifies the maximum image height and width
+ as a ratio to the frame height and width. If the value is
+ non-numeric, there is no explicit limit on the size of images. */);
Vmax_image_size = make_float (MAX_IMAGE_SIZE);
Vimage_type_cache = Qnil;
staticpro (&QCheuristic_mask);
QCindex = intern_c_string (":index");
staticpro (&QCindex);
+ QCgeometry = intern (":geometry");
+ staticpro (&QCgeometry);
+ QCcrop = intern (":crop");
+ staticpro (&QCcrop);
+ QCrotation = intern (":rotation");
+ staticpro (&QCrotation);
QCmatrix = intern_c_string (":matrix");
+
staticpro (&QCmatrix);
QCcolor_adjustment = intern_c_string (":color-adjustment");
staticpro (&QCcolor_adjustment);
ADD_IMAGE_TYPE (Qpng);
#endif
+#if defined (HAVE_IMAGEMAGICK)
+ Qimagemagick = intern ("imagemagick");
+ staticpro (&Qimagemagick);
+ ADD_IMAGE_TYPE (Qimagemagick);
+#endif
+
#if defined (HAVE_RSVG)
Qsvg = intern_c_string ("svg");
staticpro (&Qsvg);
#endif /* HAVE_RSVG */
defsubr (&Sinit_image_library);
+#ifdef HAVE_IMAGEMAGICK
+ defsubr (&Simagemagick_types);
+#endif
defsubr (&Sclear_image_cache);
defsubr (&Simage_flush);
defsubr (&Simage_size);
#endif
DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
- doc: /* Non-nil means always draw a cross over disabled images.
-Disabled images are those having a `:conversion disabled' property.
-A cross is always drawn on black & white displays. */);
+ doc: /* Non-nil means always draw a cross over disabled images.
+ Disabled images are those having a `:conversion disabled' property.
+ A cross is always drawn on black & white displays. */);
cross_disabled_images = 0;
DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
- doc: /* List of directories to search for window system bitmap files. */);
+ doc: /* List of directories to search for window system bitmap files. */);
Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
- doc: /* Maximum time after which images are removed from the cache.
-When an image has not been displayed this many seconds, Emacs
-automatically removes it from the image cache. If the cache contains
-a large number of images, the actual eviction time may be shorter.
-The value can also be nil, meaning the cache is never cleared.
-
-The function `clear-image-cache' disregards this variable. */);
+ doc: /* Maximum time after which images are removed from the cache.
+ When an image has not been displayed this many seconds, Emacs
+ automatically removes it from the image cache. If the cache contains
+ a large number of images, the actual eviction time may be shorter.
+ The value can also be nil, meaning the cache is never cleared.
+ The function `clear-image-cache' disregards this variable. */);
Vimage_cache_eviction_delay = make_number (300);
+#ifdef HAVE_IMAGEMAGICK
+ DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type,
+ doc: /* Choose between ImageMagick render methods. */);
+#endif
+
}
+
void
init_image (void)
{
+
}
+
+
/* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
(do not change this comment) */