Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to make montage work #2

Open
mirkov opened this issue Dec 2, 2019 · 6 comments
Open

Trying to make montage work #2

mirkov opened this issue Dec 2, 2019 · 6 comments

Comments

@mirkov
Copy link

mirkov commented Dec 2, 2019

Hi,

I am trying to use %magickmontageimage. Based on some C code on the web, I came with following code:

(cl:in-package :cl-user)

(defpackage gm.montage-demo
  (:use :cl :gm))

(in-package gm.montage-demo)

(defparameter *white-image*
  (probe-file
   (merge-pathnames "test/resource/320x240_white.jpg"
		    (asdf:system-source-directory
		     :cl-graphicsmagick))))

(defparameter *black-image*
  (probe-file
   (merge-pathnames "test/resource/320x240_black.jpg"
		    (asdf:system-source-directory
		     :cl-graphicsmagick))))

(defparameter *montage*
  (merge-pathnames "montage.jpg"
		   (uiop:temporary-directory)))

(defun do-montage ()
  (with-magick-wand (wand :output-path (namestring *montage*))
    (%magickreadimage wand (namestring *white-image*))
    (%magickreadimage wand (namestring *black-image*))
    (with-drawing-wand (drawing-wand)
      (let* ((tile-geometry "2x1")
	     (thumbnail-geometry "64x64+5+5")
	     (mode :%FrameMode)
	     (frame "")) 
	(%magickmontageimage wand drawing-wand tile-geometry thumbnail-geometry mode frame)))))

However, when I examine the test file created by do-montage in the temp directory, I only see the black image.

I played with various input parameter settings, and was unable to affect the output in any way. I suspect I am misusing the code in some way.

Any thoughts on what I am doing wrong?

Thanks

Mirko

@mirkov
Copy link
Author

mirkov commented Dec 2, 2019

You are right that there are very few demos on MagickMontageImage. This is what guided my code:

I found an old post from 2010 for ImageMagick https://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=16972#p62965. My interpretation of the C code is that the wand can read multiple images.

Furthermore, according to the documentation for MagickReadImage http://www.graphicsmagick.org/wand/magick_wand.html#magickreadimage, it reads an image or image sequence.

I tried passing an image sequence by concatenating file names

(%magickreadimage wand 
		      (concatenate 'string (namestring *black-image*)
				   ", "
				   (namestring *white-image*)))

but MagickReadImage interpreted the argument as a single filename instead of two. I also tried with a space separator.

As a workaround, I used montage's command-line interface to get what I wanted.

In the meantime, I may post the question on a user forum how to pass an image sequence to MatickReadImage.

@muyinliu
Copy link
Owner

muyinliu commented Dec 2, 2019

OK. I found the solution. Here is the code:

(defun do-montage ()
  (with-magick-wand (wand)
    (%MagickReadImage wand (namestring *white-image*))
    (%MagickReadImage wand (namestring *black-image*))
    (with-drawing-wand (drawing-wand)
      (let* ((tile-geometry "2x1+0+0")
             (thumbnail-geometry "640x240+0+0")
             (mode :%ConcatenateMode)
             (frame "0x0+0+0")
             (montaged-wand (%MagickMontageImage wand
                                                 drawing-wand
                                                 tile-geometry
                                                 thumbnail-geometry
                                                 mode
                                                 frame)))
        (%MagickWriteImage montaged-wand (namestring *montage*))))))

The key part of this it's that you should %MagickWriteImage the returned %MagickWand of function %MagickMontageImage, NOT the object wand.

@muyinliu
Copy link
Owner

muyinliu commented Dec 2, 2019

I deleted all the useless comments I made before to avoid misunderstand when other programmers browse current page.

Hope that my answer help you.

@mirkov
Copy link
Author

mirkov commented Dec 3, 2019

Thank you very much for figuring it out. Using your example I defined montage-images like so:

(defun montage-images (input-path-list output-path
		       &key (thumbnail-geometry "")
			 (tile-geometry "")
			 (mode :%undefinedmode)
			 (frame "0x0+0+0"))
  "Place composite image in output-path by combining several separate images

Return magick-wand"
  (with-magick-wand (wand)
    (dolist (input-path input-path-list wand)
      (%MagickReadImage wand (namestring input-path)))
    (with-drawing-wand (drawing-wand)
      (let ((montaged-wand 
	     (%MagickMontageImage wand
				  drawing-wand
                                  tile-geometry
                                  thumbnail-geometry
                                  mode
                                  frame)))
        (%MagickWriteImage montaged-wand output-path)))
    wand))

Thanks again

@mirkov mirkov closed this as completed Dec 3, 2019
@mirkov
Copy link
Author

mirkov commented Dec 3, 2019

No comments other than my previous post.

@muyinliu
Copy link
Owner

muyinliu commented Dec 3, 2019

The macro with-magick-wand will call %DestroyMagickWand with wand at the end, so you should NOT return wand(because it's already destroyed). Returning the output-path is better in this case.

@mirkov mirkov reopened this Dec 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants