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

Imagemagick image writer #1304

Merged
merged 15 commits into from
Jan 31, 2018
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,15 @@ install
*.bak

*.h#

\.build-tools\.cson

\.clang_complete

src/DGtal/shapes/doc/\.#packageShapes\.dox

src/DGtal/shapes/doc/#packageShapes\.dox#

tests/base/testTrace2\.cpp

tests/base/testTrace3\.cpp
4 changes: 3 additions & 1 deletion .travis/before_global.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export SRC_DIR="`pwd`"

export CCOMPILER=$CC
export CXXCOMPILER=$CXX

export MAGICK_CONFIG_PATH=".travis/delegate.mgk"
$MAGICK_CODER_MODULE_PATH
$MAGICK_FILTER_MODULE_PATH
##Preparing folders
mkdir deps/
mkdir deps/local
145 changes: 145 additions & 0 deletions .travis/delegate.mgk
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?xml version="1.0"?>
<!--
Delegate command file.

Commands which specify

decode="in_format" encode="out_format"

specify the rules for converting from in_format to out_format
These rules may be used to translate directly between formats.

Commands which specify only

decode="in_format"

specify the rules for converting from in_format to some format that
GraphicsMagick will automatically recognize. These rules are used to
decode formats.

Commands which specify only

encode="out_format"

specify the rules for an "encoder" which may accept any input format.

For delegates other than gs-color, gs-mono, and mpeg-encode
the substitution rules are as follows:

%i input image filename
%o output image filename
%u unique temporary filename
%z secondary unique temporary filename

%# input image signature
%b image file size
%c input image comment
%d original filename directory part
%e original filename extension part
%f original filename
%t original filename top (base) part
%g window group
%h image rows (height)
%k input image number colors
%l input image label
%m input image format ("magick")
%n input image number of scenes
%p page number
%q input image depth
%r input image storage class, colorspace, and matte
%s scene number
%w image columns (width)
%x input image x resolution
%y input image y resolution
%[ input image attribute (e.g. "%[EXIF:Orientation]")
%% pass through literal %

Under Unix, all text (non-numeric) substitutions should be
surrounded with double quotes for the purpose of security, and
because any double quotes occuring within the substituted text will
be escaped using a backslash.

Commands (excluding file names) containing one or more of the
special characters ";&|><" (requiring that multiple processes be
executed) are executed via the Unix shell with text substitutions
carefully excaped to avoid possible compromise. Otherwise, commands
are executed directly without use of the Unix shell.

Use 'gm convert -list delegates' to verify how the contents of this
file has been parsed.

-->
<delegatemap>
<delegate decode="autotrace" stealth="True" command='"autotrace" -output-format svg -output-file "%o" "%i"' />
<delegate decode="browse" stealth="True" command='"xdg-open" "http://www.GraphicsMagick.org/" &' />
<delegate decode="cgm" command='"ralcgm" -d ps < "%i" > "%o" 2>/dev/null' />
<delegate decode="dcraw" command='"dcraw" -c -w "%i" > "%o"' />
<delegate decode="dot" command='"dot" -Tps "%i" -o "%o"' />
<delegate decode="dvi" command='"dvips" -q -o "%o" "%i"' />
<delegate decode="edit" stealth="True" command='"xterm" -title "Edit Image Comment" -e vi "%o"' />
<delegate decode="emf" command='"wmf2eps" -o "%o" "%i"' />
<delegate decode="eps" encode="pdf" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pdfwrite "-sOutputFile=%o" -- "%i" -c quit' />
<delegate decode="eps" encode="ps" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pswrite "-sOutputFile=%o" -- "%i" -c quit' />
<delegate decode="fig" command='"fig2dev" -L ps "%i" "%o"' />
<delegate decode="gplt" command='"echo" "set size 1.25,0.62; set terminal postscript portrait color solid; set output \"%o\"; load \"%i\"" > "%u"; "gnuplot" "%u"' />

<!-- Read monochrome Postscript, EPS, and PDF -->
<delegate decode="gs-mono" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pbmraw -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<!-- Read grayscale Postscript, EPS, and PDF -->
<delegate decode="gs-gray" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pgmraw -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<!-- Read colormapped Postscript, EPS, and PDF -->
<delegate decode="gs-palette" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pcx256 -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<!-- Read color Postscript, EPS, and PDF -->
<delegate decode="gs-color" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=ppmraw -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<!-- Read color+alpha Postscript, EPS, and PDF -->
<delegate decode="gs-color+alpha" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pngalpha -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<!-- Read CMYK Postscript, EPS, and PDF -->
<delegate decode="gs-cmyk" stealth="True" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pam -dTextAlphaBits=%u -dGraphicsAlphaBits=%u -r%s %s "-sOutputFile=%s" -- "%s" -c quit' />

<delegate decode="hpg" command='"hp2xx" -q -m eps -f `basename "%o"` "%i" && mv -f `basename "%o"` "%o"' />
<delegate decode="hpgl" command='"hp2xx" -q -m eps -f `basename "%o"` "%i" && mv -f `basename "%o"` "%o"' />
<!-- Read HTML file -->
<delegate decode="htm" command='"html2ps" -U -o "%o" "%i"' />
<!-- Read HTML file -->
<delegate decode="html" command='"html2ps" -U -o "%o" "%i"' />
<delegate decode="ilbm" command='"ilbmtoppm" "%i" > "%o"' />
<!-- Read UNIX manual page -->
<delegate decode="man" command='"groff" -man -Tps "%i" > "%o"' />
<!-- Read MPEG file using mpeg2decode -->
<delegate decode="mpeg" command='"mpeg2decode" -q -b "%i" -f -o3 "%u%%05d"; gm convert -temporary "%u*.ppm" "miff:%o" ; rm -f "%u"*.ppm ' />
<!-- Write MPEG file using mpeg2encode -->
<delegate encode="mpeg-encode" stealth="True" command='"mpeg2encode" "%i" "%o"' />
<!-- Convert PDF to Encapsulated Poscript using Ghostscript -->
<delegate decode="pdf" encode="eps" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=epswrite "-sOutputFile=%o" -- "%i" -c quit' />
<!-- Convert PDF to Postcript using Ghostscript -->
<delegate decode="pdf" encode="ps" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pswrite "-sOutputFile=%o" -- "%i" -c quit' />
<!-- Convert PNM file to ILBM format using ppmtoilbm -->
<delegate decode="pnm" encode="ilbm" mode="encode" command='"ppmtoilbm" -24if "%i" > "%o"' />
<delegate decode="pnm" encode="launch" mode="encode" command='"gimp" "%i"' />
<delegate decode="pnm" encode="win" mode="encode" command='"gm" display -immutable "%i"' />
<!-- Read Persistance Of Vision file using povray -->
<delegate decode="pov" command='povray "+i"%i"" +o"%o" +fn%q +w%w +h%h +a -q9 -kfi"%s" -kff"%n"
"gm" convert -adjoin "%o*.png" "%o"' />
<delegate decode="ps" encode="eps" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=epswrite "-sOutputFile=%o" -- "%i" -c quit' />
<delegate decode="ps" encode="pdf" mode="bi" command='"gs" -q -dBATCH -dMaxBitmap=50000000 -dNOPAUSE -sDEVICE=pdfwrite "-sOutputFile=%o" -- "%i" -c quit' />
<delegate decode="ps" encode="print" mode="encode" command='"/usr/bin/lpr" "%i"' />
<!-- Read Radiance file using ra_ppm -->
<delegate decode="rad" command='"ra_ppm" -g 1.0 "%i" "%o"' />
<!-- Convert RGBA file to URT RLE using rawtorle -->
<delegate decode="rgba" encode="rle" mode="encode" command='"gm" mogrify -flip -size %wx%h "rgba:%i"
"rawtorle" -w %w -h %h -n 4 -o "%o" "%i"' />
<!-- Scan an image using Sane's scanimage -->
<delegate decode="scan" command='"scanimage" -d "%i" > "%o"' />
<!-- Read HTML file -->
<delegate decode="shtml" command='"html2ps" -U -o "%o" "%i"' />
<!-- Convert ASCII text to Postscript using 'enscript' command -->
<delegate decode="txt" encode="ps" mode="bi" command='"enscript" -o "%o" "%i"' />
<!-- Render WMF file using wmf2eps (fallback in case libwmf not available) -->
<delegate decode="wmf" command='"wmf2eps" -o "%o" "%i"' />
<delegate encode="show" stealth="True" command='"gm" display -immutable -delay 0 -window_group %g -title "%l of %f" "tmp:%o" &' />
</delegatemap>
2 changes: 1 addition & 1 deletion .travis/install_deps_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Note: gmp and boost already installed
#
brew update
#brew install qt5 doxygen homebrew/science/hdf5 graphviz graphicsmagick fftw eigen
#brew install qt5 doxygen homebrew/science/hdf5 graphviz graphicsmagick fftw eigen
brew install qt5 graphicsmagick fftw eigen
# Explicit install of libqglviewer
brew install http://liris.cnrs.fr/david.coeurjolly/misc/libqglviewer.rb
Expand Down
14 changes: 13 additions & 1 deletion .travis/main_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,19 @@ echo "NeedExample $NEEDEXAMPLESANDTESTS"
### DGtal Examples and Examples
if [ $NEEDEXAMPLESANDTESTS = "true" ];
then
ctest -j 3 --output-on-failure
cd examples ; make -j 3
cd ../tests ; make -j 3

if [ -f io/writers/testMagickWriter ]; then
io/writers/testMagickWriter -s
fi
if [ -f io/readers/testMagickReader ]; then
io/readers/testMagickReader
fi

ctest -j 3--output-on-failure


fi

### DGtal doc
Expand Down
8 changes: 6 additions & 2 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@
for instance to add callbacks to key or mouse events, or to modify
what is drawn on the window.
(Jacques-Olivier Lachaud, [#1259](https://github.com/DGtal-team/DGtal/pull/1259))
- TableReader can now read all elements contained in each line of a file
- TableReader can now read all elements contained in each line of a file
with the new method getLinesElementsFromFile().
(Bertrand Kerautret, [#1260](https://github.com/DGtal-team/DGtal/pull/1260))
(Bertrand Kerautret,
[#1260](https://github.com/DGtal-team/DGtal/pull/1260))
- New ImageMagick writer to export images to PNG or JPG formats for
instance. (David Coeurjolly,
[#1304](https://github.com/DGtal-team/DGtal/pull/1304))
- SimpleDistanceColorMap new colormap to easily display distance maps.
(David Coeurjolly, [#1302](https://github.com/DGtal-team/DGtal/pull/1302))

Expand Down
1 change: 1 addition & 0 deletions src/DGtal/io/doc/moduleIO.dox
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Hence, for image writers, some functors may return a DGtal::Color or a scalar
|------------|---------|---------------------------------|---------------------------------------------|---------------|----------------------------------------------------------|
| 2D | PGM | Grayscale netpbm image format | the functor should return an unsigned char | PGMWriter | http://netpbm.sourceforge.net/ |
| | PPM | Color netpbm image format | the functor should return a DGtal::Color | PPMWriter | http://netpbm.sourceforge.net/ |
| | any ImageMagick format | Color image format (png,jpg...) | the functor must return a DGtal::Color | MagickWriter | with @a WITH_MAGICK build http://www.imagemagick.org |
| | any 2D ITK format | Grayscale or 2D ITK image | the functor should return a ITKIOTrait<Image::Value>::ValueOut | ITKWriter | with @a WITH_ITK build flag, http://www.itk.org/ |
| 3D | PGM3D | Grayscale netpbm image format | the functor should return an unsigned char | PGMWriter | |
| | PPM3D | Color netpbm image format | the functor should return a DGtal::Color | PPMWriter | |
Expand Down
129 changes: 129 additions & 0 deletions src/DGtal/io/writers/MagickWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) 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, see <http://www.gnu.org/licenses/>.
*
**/

#pragma once

/**
* @file MagickWriter.h
* @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr )
* Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
*
* @date 2017/12/30
*
* Header file for module MagickWriter.cpp
*
* This file is part of the DGtal library.
*/

#if defined(MagickWriter_RECURSES)
#error Recursive header files inclusion detected in MagickWriter.h
#else // defined(MagickWriter_RECURSES)
/** Prevents recursive inclusion of headers. */
#define MagickWriter_RECURSES

#if !defined MagickWriter_h
/** Prevents repeated inclusion of headers. */
#define MagickWriter_h

//////////////////////////////////////////////////////////////////////////////
// Inclusions
#include <iostream>
#include <string>
#include "DGtal/base/CUnaryFunctor.h"
#include "DGtal/base/BasicFunctors.h"
#include "DGtal/io/writers/MagickWriter.h"
#include "DGtal/io/Color.h"

#ifndef WITH_MAGICK
#pragma error "You must activate imagemagick (-DWITH_MAGICK=true) to include this file"
#endif
#include <Magick++.h>
//////////////////////////////////////////////////////////////////////////////

namespace DGtal
{

/////////////////////////////////////////////////////////////////////////////
// template class MagickWriter
/**
* Description of template struct 'MagickWriter' <p>
* \brief Aim: Export image using Imagemagick backend.
*
* If imagemagick is enabled (with WITH_MAGICK set to true), this writer
* export any image to a generic color Magick++ image (png, jpg, gif, bmp...) using
* a given colormap functor.
*
* The file format is given by the filename extension during the export.
*
* @tparam TImage the Image type.
* @tparam TFunctor the type of functor used in the export. The return type
* of the functor must be a DGtal::Color (e.g. any colormap)
*
* @see testMagickWriter.cpp
*/
template <typename TImage, typename TFunctor = functors::Identity>
struct MagickWriter
{
// ----------------------- Standard services ------------------------------
typedef TImage Image;
typedef typename TImage::Value Value;
typedef TFunctor Functor;

BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<TFunctor, Value, Color> )) ;
BOOST_STATIC_ASSERT( (TImage::Domain::dimension == 2) );

/**
* Export an Image with Imagemagick.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageMagick

*
* @param filename name of the output file the suffix is used to select
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file the -> file, the ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed

* the file format (png, bmp, jpg,...).
* @param anImage the image to export
* @param aFunctor functor used to cast image values to DGtal::Color
*
* @return true if no errors occur.
*/
static bool exportMagick(const std::string & filename, const Image &anImage,
const Functor & aFunctor = Functor())
{
Magick::InitializeMagick(NULL);
int w = (anImage.domain().upperBound()[0] - anImage.domain().lowerBound()[0])+1;
int h = (anImage.domain().upperBound()[1] - anImage.domain().lowerBound()[1])+1;
Magick::Geometry geom(w,h);
Magick::Image image(geom,"white");
for(auto point: anImage.domain())
{
Color c = aFunctor( anImage(point) );
Magick::ColorRGB magickc( c.red()/255., c.green()/255., c.blue()/255.) ;
image.pixelColor( point[0] + anImage.domain().lowerBound()[0],
(h-1) - (point[1] + anImage.domain().lowerBound()[1]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anImage.domain().upperBound()[1]-point[1] ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks , I’ll check

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that should be the same.

magickc );
}
image.write(filename);
return true;
}



};
}//namespace

// //
///////////////////////////////////////////////////////////////////////////////

#endif // !defined MagickWriter_h

#undef MagickWriter_RECURSES
#endif // else defined(MagickWriter_RECURSES)
11 changes: 10 additions & 1 deletion tests/io/writers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
SET(DGTAL_TESTS_SRC_IO_WRITERS
testCompressedVolWriter
testPNMRawWriter
testPNMRawWriter
testMeshWriter
testGenericWriter)



IF(MAGICK++_FOUND)
SET(DGTAL_TESTS_SRC_IO_WRITERS
${DGTAL_TESTS_SRC_IO_WRITERS}
testMagickWriter
)
ENDIF()


FOREACH(FILE ${DGTAL_TESTS_SRC_IO_WRITERS})
add_executable(${FILE} ${FILE})
target_link_libraries (${FILE} DGtal)
Expand Down
Loading