From: Fabrice Popineau <fabrice.popineau@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: "Óscar Fuentes" <ofv@wanadoo.es>,
"Juanma Barranquero" <lekktu@gmail.com>,
"Emacs developers" <emacs-devel@gnu.org>
Subject: Re: 64-bit build on Windows
Date: Sat, 21 Jan 2017 21:40:44 +0100 [thread overview]
Message-ID: <CAFgFV9PbyVqoi1O1EGByAo-BQt_Jd-cK_exn-BqUTVd1WYh73w@mail.gmail.com> (raw)
In-Reply-To: <838tq45gsk.fsf@gnu.org>
[-- Attachment #1.1: Type: text/plain, Size: 1623 bytes --]
2017-01-21 20:55 GMT+01:00 Eli Zaretskii <eliz@gnu.org>:
> > From: Fabrice Popineau <fabrice.popineau@gmail.com>
> > Date: Sat, 21 Jan 2017 20:23:29 +0100
> > Cc: Eli Zaretskii <eliz@gnu.org>, Óscar Fuentes <ofv@wanadoo.es>,
> > Emacs developers <emacs-devel@gnu.org>
> >
> > If Emacs on Windows is built to use the DLLs, and they are not
> available (let's say you downloaded a
> > binary tarball built with Imagemagick support, but you don't have the
> DLLs in your system), Windows
> > won't allow emacs.exe to run. That's a big problem.
> >
> > ???
> >
> > Not when you use LoadLibrary and fortunately.
>
> The coe that uses LoadLibrary is based on dynamic-library-alist, so as
> long as Imagemagick DLLs are not in that alist, there's no LoadLibrary
> to load them.
>
> > > What happens if the jpeg or xpm or png dlls are not found ?
> >
> > Nothing, because they are not statically linked. If Emacs was built
> with jpeg support (or png, etc.), it will
> > check at runtime (and on demand, the first time a jpeg function is
> needed) that the jpeg DLL can be
> > loaded. If not, the function will fail and Emacs will take note that
> the DLL is unavailable.
> >
> > And it is the same for ImageMagick.
>
> Please describe how this would work, without using
> dynamic-library-alist.
>
But I never said that it would work without using dynamic-library-alist ?
I said that I may have missed that part of the patch when I have posted it.
I was objecting to the fact that IM has to be statically linked.
The attached patch should be a proof of concept.
Fabrice
[-- Attachment #1.2: Type: text/html, Size: 2447 bytes --]
[-- Attachment #2: master-imagemagick.diff --]
[-- Type: text/plain, Size: 13983 bytes --]
diff --git a/configure.ac b/configure.ac
index dcba7eb..53a2d27 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2462,7 +2461,7 @@ AC_DEFUN
if test "${with_imagemagick}" != "no"; then
## 6.3.5 is the earliest version known to work; see Bug#17339.
## 6.8.2 makes Emacs crash; see Bug#13867.
- IMAGEMAGICK_MODULE="Wand >= 6.3.5 Wand != 6.8.2"
+ IMAGEMAGICK_MODULE="MagickWand >= 6.3.5 MagickWand != 6.8.2"
EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE])
AC_SUBST(IMAGEMAGICK_CFLAGS)
AC_SUBST(IMAGEMAGICK_LIBS)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index ecb7284..6921ed8 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -280,6 +280,7 @@
(load "term/w32-win")
(load "disp-table")
(when (eq system-type 'windows-nt)
+ (load "image")
(load "w32-fns")
(load "ls-lisp")
(load "dos-w32"))))
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index fda9388..d168e11 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -271,6 +271,8 @@ libgnutls-version
'(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
'(glib "libglib-2.0-0.dll")
'(gobject "libgobject-2.0-0.dll")
+ '(magickwand "libMagickWand-7.Q16HDRI-0.dll" "libMagickWand-7.Q16-0.dll")
+ '(magickcore "libMagickCore-7.Q16HDRI-0.dll" "libMagickCore-7.Q16-0.dll")
(if (>= libgnutls-version 30400)
'(gnutls "libgnutls-30.dll")
'(gnutls "libgnutls-28.dll" "libgnutls-26.dll"))
diff --git a/src/image.c b/src/image.c
index 39677d2..04480f3 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2307,7 +2403,7 @@ x_find_image_fd (Lisp_Object file, int *pfd)
happens, e.g., under Auto Image File Mode.) 'openp'
didn't open the file, so we should, because the caller
expects that. */
- fd = emacs_open (SSDATA (file_found), O_RDONLY, 0);
+ fd = emacs_open (SSDATA (file_found), O_RDONLY | O_BINARY, 0);
}
}
else /* fd < 0, but not -2 */
@@ -8244,16 +8382,227 @@ imagemagick_image_p (Lisp_Object object)
/* The GIF library also defines DrawRectangle, but its never used in Emacs.
Therefore rename the function so it doesn't collide with ImageMagick. */
#define DrawRectangle DrawRectangleGif
+#ifdef __MINGW64__
+#include <ImageMagick-7/MagickWand/MagickWand.h>
+#else
#include <wand/MagickWand.h>
+#endif
/* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
Emacs seems to work fine with the hidden version, so unhide it. */
+#ifdef __MINGW64__
+#include <ImageMagick-7/MagickCore/version.h>
+#else
#include <magick/version.h>
+#endif
#if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
extern WandExport void PixelGetMagickColor (const PixelWand *,
MagickPixelPacket *);
#endif
+#ifdef WINDOWSNT
+DEF_DLL_FN (MagickWand *, CloneMagickWand, (const MagickWand *));
+DEF_DLL_FN (MagickWand *, DestroyMagickWand, (MagickWand *));
+DEF_DLL_FN (MagickWand *, DestroyPixelIterator, (PixelIterator *));
+DEF_DLL_FN (PixelWand *, DestroyPixelWand, (PixelWand *));
+DEF_DLL_FN (MagickBooleanType, MagickCropImage, (MagickWand *, const size_t, const size_t, const ssize_t, const ssize_t));
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+DEF_DLL_FN (MagickBooleanType, MagickExportImagePixels, (MagickWand *, const ssize_t, const ssize_t, const size_t, const size_t, const char *, const StorageType, void *));
+#endif
+DEF_DLL_FN (char *, MagickGetException, (const MagickWand *, ExceptionType *));
+DEF_DLL_FN (MagickWand *, MagickGetImage, (MagickWand *));
+DEF_DLL_FN (DisposeType, MagickGetImageDelay, (MagickWand *));
+DEF_DLL_FN (DisposeType, MagickGetImageDispose, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetImageHeight, (MagickWand *));
+DEF_DLL_FN (MagickBooleanType, MagickGetImagePage, (MagickWand *, size_t *, size_t *, ssize_t *, ssize_t *));
+DEF_DLL_FN (char *, MagickGetImageSignature, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetImageWidth, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetNumberImages, (MagickWand *));
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+DEF_DLL_FN (MagickWand *, MagickMergeImageLayers, (MagickWand *, const ImageLayerMethod));
+#else
+DEF_DLL_FN (MagickWand *, MagickFlattenImages, (MagickWand *));
+#endif
+DEF_DLL_FN (MagickBooleanType, MagickReadImage, (MagickWand *, const char *));
+DEF_DLL_FN (MagickBooleanType, MagickReadImageBlob, (MagickWand *, const void *, const size_t));
+DEF_DLL_FN (void *, MagickRelinquishMemory, (void *));
+DEF_DLL_FN (MagickBooleanType, MagickRotateImage, (MagickWand *, const PixelWand *, const double));
+DEF_DLL_FN (MagickBooleanType, MagickScaleImage, (MagickWand *, const size_t, const size_t));
+DEF_DLL_FN (MagickBooleanType, MagickSetFilename, (MagickWand *, const char *));
+DEF_DLL_FN (MagickBooleanType, MagickSetImageBackgroundColor, (MagickWand *, const PixelWand *));
+DEF_DLL_FN (MagickBooleanType, MagickSetIteratorIndex, (MagickWand *, const ssize_t));
+DEF_DLL_FN (void, MagickWandGenesis, (void));
+DEF_DLL_FN (void, MagickWandTerminus, (void));
+DEF_DLL_FN (MagickWand *, NewMagickWand, (void));
+DEF_DLL_FN (PixelIterator *, NewPixelIterator, (MagickWand *));
+DEF_DLL_FN (PixelWand *, NewPixelWand, (void));
+DEF_DLL_FN (double, PixelGetAlpha, (const PixelWand *));
+DEF_DLL_FN (void, PixelGetMagickColor, (const PixelWand *, PixelInfo *));
+DEF_DLL_FN (PixelWand **, PixelGetNextIteratorRow, (PixelIterator *, size_t *));
+DEF_DLL_FN (MagickBooleanType, PixelSetIteratorRow, (PixelIterator *, const ssize_t));
+DEF_DLL_FN (void, PixelSetPixelColor, (PixelWand *, const PixelInfo *));
+DEF_DLL_FN (void, PixelSetRed, (PixelWand *, const double));
+DEF_DLL_FN (void, PixelSetGreen, (PixelWand *, const double));
+DEF_DLL_FN (void, PixelSetBlue, (PixelWand *, const double));
+DEF_DLL_FN (MagickBooleanType, PixelSyncIterator, (PixelIterator *));
+
+DEF_DLL_FN (ExceptionInfo *, DestroyExceptionInfo, (ExceptionInfo *));
+DEF_DLL_FN (char *, DestroyString, (char *));
+DEF_DLL_FN (ExceptionInfo *, AcquireExceptionInfo, ());
+DEF_DLL_FN (char **, GetMagickList, (const char *, size_t *, ExceptionInfo *));
+
+static bool
+init_imagemagick_functions (void)
+{
+ HMODULE magickwand, magickcore;
+
+ if (!(magickcore = w32_delayed_load (Qmagickcore))
+ || !(magickwand = w32_delayed_load (Qmagickwand)))
+ return 0;
+
+ LOAD_DLL_FN (magickwand, CloneMagickWand);
+ LOAD_DLL_FN (magickwand, DestroyMagickWand);
+ LOAD_DLL_FN (magickwand, DestroyPixelIterator);
+ LOAD_DLL_FN (magickwand, DestroyPixelWand);
+ LOAD_DLL_FN (magickwand, MagickCropImage);
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+ LOAD_DLL_FN (magickwand, MagickExportImagePixels);
+#endif
+ LOAD_DLL_FN (magickwand, MagickGetException);
+ LOAD_DLL_FN (magickwand, MagickGetImage);
+ LOAD_DLL_FN (magickwand, MagickGetImageDelay);
+ LOAD_DLL_FN (magickwand, MagickGetImageDispose);
+ LOAD_DLL_FN (magickwand, MagickGetImageHeight);
+ LOAD_DLL_FN (magickwand, MagickGetImagePage);
+ LOAD_DLL_FN (magickwand, MagickGetImageSignature);
+ LOAD_DLL_FN (magickwand, MagickGetImageWidth);
+ LOAD_DLL_FN (magickwand, MagickGetNumberImages);
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+ LOAD_DLL_FN (magickwand, MagickMergeImageLayers);
+#else
+ LOAD_DLL_FN (magickwand, MagickFlattenImages);
+#endif
+ LOAD_DLL_FN (magickwand, MagickReadImage);
+ LOAD_DLL_FN (magickwand, MagickReadImageBlob);
+ LOAD_DLL_FN (magickwand, MagickRelinquishMemory);
+ LOAD_DLL_FN (magickwand, MagickRotateImage);
+ LOAD_DLL_FN (magickwand, MagickScaleImage);
+ LOAD_DLL_FN (magickwand, MagickSetFilename);
+ LOAD_DLL_FN (magickwand, MagickSetImageBackgroundColor);
+ LOAD_DLL_FN (magickwand, MagickSetIteratorIndex);
+ LOAD_DLL_FN (magickwand, MagickWandGenesis);
+ LOAD_DLL_FN (magickwand, MagickWandTerminus);
+ LOAD_DLL_FN (magickwand, NewMagickWand);
+ LOAD_DLL_FN (magickwand, NewPixelIterator);
+ LOAD_DLL_FN (magickwand, NewPixelWand);
+ LOAD_DLL_FN (magickwand, PixelGetAlpha);
+ LOAD_DLL_FN (magickwand, PixelGetMagickColor);
+ LOAD_DLL_FN (magickwand, PixelGetNextIteratorRow);
+ LOAD_DLL_FN (magickwand, PixelSetIteratorRow);
+ LOAD_DLL_FN (magickwand, PixelSetPixelColor);
+ LOAD_DLL_FN (magickwand, PixelSetRed);
+ LOAD_DLL_FN (magickwand, PixelSetGreen);
+ LOAD_DLL_FN (magickwand, PixelSetBlue);
+ LOAD_DLL_FN (magickwand, PixelSyncIterator);
+
+ LOAD_DLL_FN (magickcore, DestroyExceptionInfo);
+ LOAD_DLL_FN (magickcore, DestroyString);
+ LOAD_DLL_FN (magickcore, AcquireExceptionInfo);
+ LOAD_DLL_FN (magickcore, GetMagickList);
+
+ return 1;
+}
+
+#undef CloneMagickWand
+#undef DestroyMagickWand
+#undef DestroyPixelIterator
+#undef DestroyPixelWand
+#undef MagickCropImage
+#undef MagickExportImagePixels
+#undef MagickGetException
+#undef MagickGetImage
+#undef MagickGetImageDelay
+#undef MagickGetImageDispose
+#undef MagickGetImageHeight
+#undef MagickGetImagePage
+#undef MagickGetImageSignature
+#undef MagickGetImageWidth
+#undef MagickGetNumberImages
+#undef MagickMergeImageLayers
+#undef MagickFlattenImages
+#undef MagickReadImage
+#undef MagickReadImageBlob
+#undef MagickRelinquishMemory
+#undef MagickRotateImage
+#undef MagickScaleImage
+#undef MagickSetFilename
+#undef MagickSetImageBackgroundColor
+#undef MagickSetIteratorIndex
+#undef MagickWandGenesis
+#undef MagickWandTerminus
+#undef NewMagickWand
+#undef NewPixelIterator
+#undef NewPixelWand
+#undef PixelGetAlpha
+#undef PixelGetMagickColor
+#undef PixelGetNextIteratorRow
+#undef PixelSetIteratorRow
+#undef PixelSetPixelColor
+#undef PixelSetRed
+#undef PixelSetGreen
+#undef PixelSetBlue
+#undef PixelSyncIterator
+#undef DestroyExceptionInfo
+#undef DestroyString
+#undef AcquireExceptionInfo
+#undef GetMagickList
+
+#define CloneMagickWand fn_CloneMagickWand
+#define DestroyMagickWand fn_DestroyMagickWand
+#define DestroyPixelIterator fn_DestroyPixelIterator
+#define DestroyPixelWand fn_DestroyPixelWand
+#define MagickCropImage fn_MagickCropImage
+#define MagickExportImagePixels fn_MagickExportImagePixels
+#define MagickGetException fn_MagickGetException
+#define MagickGetImage fn_MagickGetImage
+#define MagickGetImageDelay fn_MagickGetImageDelay
+#define MagickGetImageDispose fn_MagickGetImageDispose
+#define MagickGetImageHeight fn_MagickGetImageHeight
+#define MagickGetImagePage fn_MagickGetImagePage
+#define MagickGetImageSignature fn_MagickGetImageSignature
+#define MagickGetImageWidth fn_MagickGetImageWidth
+#define MagickGetNumberImages fn_MagickGetNumberImages
+#define MagickMergeImageLayers fn_MagickMergeImageLayers
+#define MagickFlattenImages fn_MagickFlattenImages
+#define MagickReadImage fn_MagickReadImage
+#define MagickReadImageBlob fn_MagickReadImageBlob
+#define MagickRelinquishMemory fn_MagickRelinquishMemory
+#define MagickRotateImage fn_MagickRotateImage
+#define MagickScaleImage fn_MagickScaleImage
+#define MagickSetFilename fn_MagickSetFilename
+#define MagickSetImageBackgroundColor fn_MagickSetImageBackgroundColor
+#define MagickSetIteratorIndex fn_MagickSetIteratorIndex
+#define MagickWandGenesis fn_MagickWandGenesis
+#define MagickWandTerminus fn_MagickWandTerminus
+#define NewMagickWand fn_NewMagickWand
+#define NewPixelIterator fn_NewPixelIterator
+#define NewPixelWand fn_NewPixelWand
+#define PixelGetAlpha fn_PixelGetAlpha
+#define PixelGetMagickColor fn_PixelGetMagickColor
+#define PixelGetNextIteratorRow fn_PixelGetNextIteratorRow
+#define PixelSetIteratorRow fn_PixelSetIteratorRow
+#define PixelSetPixelColor fn_PixelSetPixelColor
+#define PixelSetRed fn_PixelSetRed
+#define PixelSetGreen fn_PixelSetGreen
+#define PixelSetBlue fn_PixelSetBlue
+#define PixelSyncIterator fn_PixelSyncIterator
+#define DestroyExceptionInfo fn_DestroyExceptionInfo
+#define DestroyString fn_DestroyString
+#define AcquireExceptionInfo fn_AcquireExceptionInfo
+#define GetMagickList fn_GetMagickList
+
+#endif /* !WINDOWSNT */
+
/* Log ImageMagick error message.
Useful when a ImageMagick function returns the status `MagickFalse'. */
@@ -8406,7 +8776,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
PixelWand **source, **dest;
size_t source_width, source_height;
ssize_t source_left, source_top;
- MagickPixelPacket pixel;
+ PixelInfo pixel;
DisposeType dispose;
ptrdiff_t lines = 0;
@@ -8471,7 +8841,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
if (dispose == BackgroundDispose || PixelGetAlpha (source[x]))
{
PixelGetMagickColor (source[x], &pixel);
- PixelSetMagickColor (dest[x + source_left], &pixel);
+ PixelSetPixelColor (dest[x + source_left], &pixel);
}
}
PixelSyncIterator (dest_iterator);
@@ -8516,7 +8886,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
MagickWand *image_wand;
PixelIterator *iterator;
PixelWand **pixels, *bg_wand = NULL;
- MagickPixelPacket pixel;
+ PixelInfo pixel;
Lisp_Object image;
Lisp_Object value;
Lisp_Object crop;
@@ -8912,6 +9282,11 @@ and `imagemagick-types-inhibit'. */)
char **imtypes;
size_t i;
+#if WINDOWSNT
+ if (!init_imagemagick_functions ())
+ return Qnil;
+#endif
+
ex = AcquireExceptionInfo();
imtypes = GetMagickList ("*", &numf, ex);
DestroyExceptionInfo(ex);
@@ -9926,12 +10368,16 @@ non-numeric, there is no explicit limit on the size of images. */);
#if defined (HAVE_IMAGEMAGICK)
DEFSYM (Qimagemagick, "imagemagick");
ADD_IMAGE_TYPE (Qimagemagick);
+#if defined HAVE_NTGUI && !defined CYGWIN
+ DEFSYM (Qmagickwand, "magickwand");
+ DEFSYM (Qmagickcore, "magickcore");
+#endif /* HAVE_NTGUI */
#endif
#if defined (HAVE_RSVG)
DEFSYM (Qsvg, "svg");
ADD_IMAGE_TYPE (Qsvg);
-#ifdef HAVE_NTGUI
+#if defined (HAVE_NTGUI) && !defined (CYGWIN)
/* Other libraries used directly by svg code. */
DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
DEFSYM (Qglib, "glib");
next prev parent reply other threads:[~2017-01-21 20:40 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-20 1:40 64-bit build on Windows Juanma Barranquero
2017-01-20 8:06 ` Eli Zaretskii
2017-01-21 18:29 ` Juanma Barranquero
2017-01-21 18:38 ` Eli Zaretskii
2017-01-20 13:42 ` Phillip Lord
2017-01-20 14:32 ` Óscar Fuentes
2017-01-20 15:54 ` Eli Zaretskii
2017-01-20 19:51 ` Fabrice Popineau
2017-01-21 18:25 ` Eli Zaretskii
2017-01-21 19:04 ` Fabrice Popineau
2017-01-21 19:15 ` Juanma Barranquero
2017-01-21 19:23 ` Fabrice Popineau
2017-01-21 19:30 ` Juanma Barranquero
2017-01-21 19:55 ` Eli Zaretskii
2017-01-21 20:40 ` Fabrice Popineau [this message]
2017-01-22 16:50 ` Eli Zaretskii
2017-01-22 20:38 ` Fabrice Popineau
2017-01-22 21:22 ` Paul Eggert
2017-01-22 21:39 ` Fabrice Popineau
2017-01-23 3:37 ` Eli Zaretskii
2017-01-23 3:30 ` Eli Zaretskii
2017-01-21 18:57 ` Juanma Barranquero
2017-01-21 19:52 ` Eli Zaretskii
2017-01-21 21:15 ` Juanma Barranquero
2017-01-21 21:42 ` Juanma Barranquero
2017-01-21 22:30 ` Nikolay Kudryavtsev
2017-01-21 22:43 ` Óscar Fuentes
2017-01-22 3:38 ` Eli Zaretskii
2017-01-21 21:18 ` Juanma Barranquero
2017-01-22 17:50 ` Stephen Leake
2017-01-22 18:07 ` Eli Zaretskii
2017-01-22 20:30 ` Fabrice Popineau
2017-01-21 18:37 ` Juanma Barranquero
2017-01-26 19:05 ` Arash Esbati
2017-01-27 6:07 ` Fabrice Popineau
-- strict thread matches above, loose matches on Subject: below --
2017-01-21 23:12 Angelo Graziosi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAFgFV9PbyVqoi1O1EGByAo-BQt_Jd-cK_exn-BqUTVd1WYh73w@mail.gmail.com \
--to=fabrice.popineau@gmail.com \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=lekktu@gmail.com \
--cc=ofv@wanadoo.es \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.