(Dies ist mein Spickzettel für den Vortrag auf der UbuCon 2014 in Katlenburg. Das meiste wird sich als Live-Demo abspielen, vorgeführt am Notebook direkt, projeziert auf die Beamer-Leinwand; ich werde meine vorbereiteten Folien nicht zeigen. Einige Links zu vertiefenden Materialien befinden sich am Ende dieses Dokuments.)
Im Rahmen dieses Vortrages werde ich anhand mehrerer relativ einfachen Beispiele vorführen, wie man mit ImageMagick-Kommandos Aufgaben der eigenen Bildbearbeitung bewältigt. Dazu gehören:
Diese Beispiele dienen dann zugleich als Aufhänger dafür, einige komplexere Funktionen von ImageMagick zu zeigen.
Zunächst Herstellung eines PNG:
convert rose: rose.png
Was ist rose:
?!??
Ein ‘eingebautes’ Bild. Fest in ImageMagick integriert. Zweck: man kann Kommandos schonmal testen, ohne sich erstmal Bilder beschaffen zu müssen.
Es gibt noch andere eingebaute Bilder: netscape:
, wizard:
, logo:
und granite:
for i in netscape wizard logo granite ; do
convert ${i}: ${i}.png
done
In ImageMagick ‘eingebaute’ Test-Bilder: wizard:
, logo:
, netscape:
, granite:
und rose:
Woran erkennt ImageMagick, was das Zielformat der Konvertierung sein soll? An der Datei-Endung.
Funktionieren bei JPEGs auch .jpeg
, .jpg
, .JPG
, JPEG
oder gar .jPeG
??! Ja.
for i in jpg JpEG; do
convert wizard: wizard.${i}
done
md5sum wizard.* | sort
Ach so, wir wollten ja eigentlich ein PNG nach GIF konvertieren! So geht’s:
convert wizard.png wizard.gif
Aber auch das geht:
convert wizard.png gif:name-ohne-datei-endung
convert wizard.png gif:name-mit-irrefuehrender-datei-endung.txt
convert wizard.png gif:name-mit-irrefuehrender-datei-endung.jpeg
ImageMagick erkennt normalerweise an der Datei-Endung, welches Ziel-Format man wünscht. Falls Namen ohne Endung (oder mit falscher Endung) im Spiel sind, dann kann [BEZEICHNER]:
vor dem Namen erzwingen, dass ImageMagick das entsprechende Format verwendet.
Kommando identify
:
identify rose.png
Ergebnis:
rose.png PNG 70x46 70x46+0+0 8-bit sRGB 6.97KB 0.000u 0:00.000
Man kann auch mehrere Dateien auf einmal “identifizieren”:
identify rose*.*
Ergebnis:
rose.gif GIF 70x46 70x46+0+0 8-bit sRGB 256c 4.11KB 0.000u 0:00.000
rose.png[1] PNG 70x46 70x46+0+0 8-bit sRGB 6.97KB 0.000u 0:00.000
rose.jpg[2] JPEG 70x46 70x46+0+0 8-bit sRGB 2.07KB 0.000u 0:00.009
rose.JPG[3] JPEG 70x46 70x46+0+0 8-bit sRGB 2.07KB 0.000u 0:00.000
rose.jpeg[4] JPEG 70x46 70x46+0+0 8-bit sRGB 2.15KB 0.000u 0:00.000
rose.jpg[5] JPEG 70x46 70x46+0+0 8-bit sRGB 2.07KB 0.000u 0:00.000
Oder die Dateien aus dem vorhergehenden Abschnitt:
identify name-{mit,ohne}-*
name-mit-irrefuehrender-datei-endung.jpeg GIF 480x640 480x640+0+0 8-bit sRGB 256c 99.7KB 0.000u 0:00.000
name-mit-irrefuehrender-datei-endung.txt[1] GIF 480x640 480x640+0+0 8-bit sRGB 256c 99.7KB 0.010u 0:00.000
name-ohne-datei-endung[2] GIF 480x640 480x640+0+0 8-bit sRGB 256c 99.7KB 0.000u 0:00.000
ImageMagick lässt sich beim Input also nicht von falschen Datei-Endungen an der Nase herumführen. Es verwendet seine eigene ‘Magie’ um das ihm vor die Nase gesetzte Format zu bestimmen.
identify JPEG:name-mit-irrefuehrender-datei-endung.jpeg
identify: Not a JPEG file: starts with 0x47 0x49
`name-mit-irrefuehrender-datei-endung.jpeg' @ error/jpeg.c/JPEGErrorHandler/322.
Der Vorgabe eines Formats zur Erzwingen einer entsprechenden Behandlung der Datei (per [FORMAT]:
-Vorsilbe) klappt also ebenfalls nicht, da ImageMagick seine eigene Prüfung unabhängig davon durchführt.
identify
— ich möchte mehr wissen! Geht’s vielleicht etwas detaillierter? – Na klar! Kuckstdu:
identify -verbose rose.png
Ergebnis:
Image: rose.png
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: DirectClass
Geometry: 70x46+0+0
Units: Undefined
Type: TrueColor
Endianess: Undefined
Colorspace: sRGB
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
Channel statistics:
Pixels: 3220
Red:
min: 35 (0.137255)
max: 255 (1)
mean: 145.712 (0.57142)
standard deviation: 69.2953 (0.271746)
kurtosis: -1.385
skewness: 0.14637
Green:
min: 22 (0.0862745)
max: 255 (1)
mean: 89.2602 (0.35004)
standard deviation: 52.4698 (0.205764)
kurtosis: 2.63898
skewness: 1.81893
Blue:
min: 24 (0.0941176)
max: 255 (1)
mean: 80.4683 (0.315562)
standard deviation: 55.1114 (0.216123)
kurtosis: 3.01818
skewness: 1.9795
Image statistics:
Overall:
min: 22 (0.0862745)
max: 255 (1)
mean: 105.147 (0.412341)
standard deviation: 59.4199 (0.233019)
kurtosis: 1.2733
skewness: 1.45983
Rendering intent: Perceptual
Gamma: 0.45455
Chromaticity:
red primary: (0.64,0.33)
green primary: (0.3,0.6)
blue primary: (0.15,0.06)
white point: (0.3127,0.329)
Background color: white
Border color: srgb(223,223,223)
Matte color: grey74
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 70x46+0+0
Dispose: Undefined
Iterations: 0
Compression: Zip
Orientation: Undefined
Properties:
date:create: 2014-10-17T22:37:50+02:00
date:modify: 2014-10-17T22:11:32+02:00
png:bKGD: chunk was found (see Background color, above)
png:cHRM: chunk was found (see Chromaticity, above)
png:gAMA: gamma=0.45454544 (See Gamma, above)
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 2
png:IHDR.color_type: 2 (Truecolor)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 70, 46
png:sRGB: intent=0 (Perceptual Intent)
png:text: 2 tEXt/zTXt/iTXt chunks were found
signature: a698f2fe0c6c31f83d19554a6ec02bac79c961dd9a87e7ed217752e75eb615d7
Artifacts:
filename: quarry-pit/rose.png
verbose: true
Tainted: False
Filesize: 6.97KB
Number pixels: 3.22K
Pixels per second: 3.22EB
User time: 0.000u
Elapsed time: 0:01.000
Version: ImageMagick 6.8.9-8 Q16 x86_64 2014-10-03 http://www.imagemagick.org
Es gibt eine Reihe von ‘Escapes’, die ImageMagick verwendet, um bestimmte Eigenschaften von Dateien anzusprechen. %W
entspricht z.B. der Bild-Breite, %H
der Bild-Höhe. Diese kann man u.a. verwenden, um per identify -format "%W x %H"
die Breite und die Höhe eines Bildes auszugeben.
Vollständige Liste:
\n newline
\r carriage return
< less-than character.
> greater-than character.
& ampersand character.
%% a percent sign
%b file size of image read in
%c comment meta-data property
%d directory component of path
%e filename extension or suffix
%f filename (including suffix)
%g layer canvas page geometry (equivalent to "%Wx%H%X%Y")
%h current image height in pixels
%i image filename (note: becomes output filename for "info:")
%k CALCULATED: number of unique colors
%l label meta-data property
%m image file format (file magic)
%n number of images in current image sequence
%o output filename (used for delegates)
%p index of image in current image list
%q quantum depth (compile-time constant)
%r image class and colorspace
%s scene number (from input unless re-assigned)
%t filename without directory or extension (suffix)
%u unique temporary filename (used for delegates)
%w current width in pixels
%x x resolution (density)
%y y resolution (density)
%z image depth (as read in unless modified, image save depth)
%A image transparency channel enabled (true/false)
%C image compression type
%D image GIF dispose method
%G original image size (%wx%h; before any resizes)
%H page (canvas) height
%M Magick filename (original file exactly as given, including read mods)
%O page (canvas) offset ( = %X%Y )
%P page (canvas) size ( = %Wx%H )
%Q image compression quality ( 0 = default )
%S ?? scenes ??
%T image time delay (in centi-seconds)
%U image resolution units
%W page (canvas) width
%X page (canvas) x offset (including sign)
%Y page (canvas) y offset (including sign)
%Z unique filename (used for delegates)
%@ CALCULATED: trim bounding box (without actually trimming)
%# CALCULATED: 'signature' hash of image values
Das Spezial-Ausgabeformat .txt
schreibt zeilenweise für jeden einzelnen Pixel seine Koordinate und seinen Farbwert in eine einfache (u.U. sehr große!) Textdatei:
convert rose: rose.txt
oder auch
convert rose: txt:- | head -n 10
Ergebnis:
# ImageMagick pixel enumeration: 70,46,255,srgb
0,0: (48,47,45) #302F2D srgb(48,47,45)
1,0: (50,48,46) #32302E srgb(50,48,46)
2,0: (54,50,47) #36322F srgb(54,50,47)
3,0: (56,51,46) #38332E srgb(56,51,46)
4,0: (58,51,45) #3A332D srgb(58,51,45)
5,0: (57,50,45) #39322D srgb(57,50,45)
6,0: (56,48,45) #38302D srgb(56,48,45)
7,0: (57,49,46) #39312E srgb(57,49,46)
8,0: (56,48,45) #38302D srgb(56,48,45)
Diese Textdatei kann man selbstverständlich editieren, oder per sed
-Kommando, Perl-Skript oder programmatisch anderweitig manipulieren. Und ImageMagick kann diese modifizierte Textdatei wieder als Input verwenden, um daraus ein “echtes” Bild zu erzeugen:
convert rose.txt nelkenstrauss.png
(Übrigens sind bei diesem speziellen Text-Datei-Format nicht alle 4 Spalten erforderlich. Die erste Spalte mit den Pixel-Koordinaten ist selbstverständlich zwingend; von den anderen dreien reicht eine alleine aus – sie drücken ja jeweils denselben Farbwert auf unterschiedliche Weise aus…)
convert -version
Ergebnis (z.B.):
Version: ImageMagick 6.8.9-8 Q16 x86_64 2014-10-03 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules
Delegates: bzlib cairo djvu fftw fontconfig freetype gslib gvc jbig jng jp2 jpeg lcms lqr ltdl lzma openexr \
pangocairo png ps rsvg tiff webp wmf x xml zlib
convert -list configure
Ergebnis:
Path: /opt/local/lib/ImageMagick-6.8.9//config-Q16/configure.xml
Name Value
-------------------------------------------------------------------------------
CC /usr/bin/clang
CFLAGS -I/opt/local/include/lqr-1 -I/opt/local/include/glib-2.0 \
-I/opt/local/lib/glib-2.0/include -I/opt/local/include \
-I/opt/local/include/freetype2 -I/opt/local/include \
-I/opt/local/include/libpng16 -pipe -Os -arch x86_64 -Wall \
-march=corei7-avx -fexceptions -D_FORTIFY_SOURCE=0 -D_THREAD_SAFE \
-pthread -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
CODER_PATH /opt/local/lib/ImageMagick-6.8.9/modules-Q16/coders
CONFIGURE ./configure '--prefix=/opt/local' '--enable-shared' '--enable-static' \
'--disable-ltdl-install' '--disable-silent-rules' '--with-frozenpaths' \
'--with-openexr' '--disable-hdri' '--with-dps' '--with-bzlib' '--with-djvu' \
'--with-fontconfig' '--with-gslib' '--with-jbig' '--with-jpeg' '--with-lcms' \
'--with-openjp2' '--with-png' '--with-tiff' '--with-webp' '--with-zlib' \
'--with-modules' '--with-xml' '--without-perl' '--without-fpx' '--with-wmf' \
'--with-gvc' '--with-rsvg' '--with-lqr' '--with-pango' '--with-x' \
'--with-gs-font-dir=/opt/local/share/fonts/urw-fonts' 'CC=/usr/bin/clang' \
'CFLAGS=-pipe -Os -arch x86_64' \
'LDFLAGS=-L/opt/local/lib -Wl,-headerpad_max_install_names -arch x86_64' \
'CPPFLAGS=-I/opt/local/include' 'CXX=/usr/bin/clang++' 'CXXFLAGS=-pipe -Os \
-arch x86_64 -stdlib=libc++'
CONFIGURE_PATH /opt/local/etc/ImageMagick-6/
COPYRIGHT Copyright (C) 1999-2014 ImageMagick Studio LLC
CPPFLAGS -I/opt/local/include/ImageMagick-6
CXX /usr/bin/clang++
CXXFLAGS -pipe -Os -arch x86_64 -stdlib=libc++ -D_THREAD_SAFE -pthread
DEFS -DHAVE_CONFIG_H
DELEGATES bzlib djvu mpeg fftw fontconfig freetype gslib jbig jng jpeg lcms lqr lzma \
openexr openjp2 pango png ps rsvg tiff webp wmf x xml zlib
DISTCHECK_CONFIG_FLAGS 'CC=/usr/bin/clang' 'CFLAGS=-pipe -Os -arch x86_64' \
'CPPFLAGS=-I/opt/local/include' 'CXX=/usr/bin/clang++' \
'LDFLAGS=-L/opt/local/lib -Wl,-headerpad_max_install_names -arch x86_64' \
--disable-deprecated --with-quantum-depth=16 --with-umem=no \
--with-autotrace=no --with-fpx=no --with-fontpath= \
--with-gs-font-dir=/opt/local/share/fonts/urw-fonts --with-perl=no
DOCUMENTATION_PATH /opt/local/share/doc/ImageMagick-6
EXEC-PREFIX /opt/local
EXECUTABLE_PATH /opt/local/bin
FEATURES DPC Modules
FILTER_PATH /opt/local/lib/ImageMagick-6.8.9/modules-Q16/filters
HOST x86_64-apple-darwin13.4.0
INCLUDE_PATH /opt/local/include/ImageMagick-6
LDFLAGS -L/opt/local/lib -L/opt/local/lib -Wl,-headerpad_max_install_names -arch x86_64 \
-L/opt/local/lib
LIB_VERSION 0x689
LIB_VERSION_NUMBER 6,8,9,8
LIBRARY_PATH /opt/local/lib/ImageMagick-6.8.9
LIBS -llcms2 -L/opt/local/lib -lfreetype -L/opt/local/lib -llqr-1 -lglib-2.0 -lintl \
-lfftw3 -L/opt/local/lib -lfontconfig -lfreetype -lXext -lSM -lICE -lX11 \
-lXt -L/opt/local/lib -llzma -lbz2 -lz -lltdl -lm
NAME ImageMagick
PCFLAGS -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
PREFIX /opt/local
QuantumDepth 16
RELEASE_DATE 2014-10-03
SHARE_PATH /opt/local/share/ImageMagick-6
SHAREARCH_PATH /opt/local/lib/ImageMagick-6.8.9/config-Q16
SVN_REVISION 16502
TARGET_CPU x86_64
TARGET_OS darwin13.4.0
TARGET_VENDOR apple
VERSION 6.8.9
WEBSITE http://www.imagemagick.org
Path: [built-in]
Name Value
-------------------------------------------------------------------------------
FEATURES
NAME ImageMagick
QuantumDepth 16
Ich möchte noch mehr wissen! Geht das?
convert -list list
Ergebnis:
[....]
Coder
Color
Colorspace
Command
Complex
Compose
Compress
Configure
DataType
Debug
Decoration
Delegate
Direction
Dispose
Distort
[....]
Besonders interessant:
convert -list color
convert -list colorspace
convert -list command
convert -list delegate
convert -list font
convert -list magic
convert -list mime
convert -list style
Am besten: selbst rumschmökern!
Ergebnis (Beispiel):
convert -list delegate
Path: /opt/local/etc/ImageMagick-6/delegates.xml
Delegate Command
-------------------------------------------------------------------------------
blender => "blender" -b "%i" -F PNG -o "%o""\n"/opt/local/bin/convert" \
-concatenate "%o*.png" "%o"
bmp<= jxr "mv "%i" "%i.bmp"; "JxrEncApp" -i "%i.bmp" -o "%o.jxr"; mv "%i.bmp" \
"%i"; mv "%o.jxr" "%o"
bmp<= wdp "mv "%i" "%i.bmp"; "JxrEncApp" -i "%i.bmp" -o "%o.jxr"; mv "%i.bmp" \
"%i"; mv "%o.jxr" "%o"
cdr => "uniconvertor" "%i" "%o.svg"; mv "%o.svg" "%o"
cgm => "uniconvertor" "%i" "%o.svg"; mv "%o.svg" "%o"
dng:decode => "/opt/local/bin/ufraw-batch" --silent --create-id=also --out-type=png \
--out-depth=16 "--output=%u.png" "%i"
doc => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` \
"%i" 2> "%Z"; mv "%i.pdf" "%o"
docx => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` \
"%i" 2> "%Z"; mv "%i.pdf" "%o"
dot => "/opt/local/bin/dot" -Tsvg "%i" -o "%o"
dvi => "/opt/local/bin/dvips" -q -o "%o" "%i"
dxf => "uniconvertor" "%i" "%o.svg"; mv "%o.svg" "%o"
eps<=>pdf "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 "-sDEVICE=pdfwrite" "-sOutputFile=%o" "-f%i"
eps<=>ps "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 \
"-sDEVICE=ps2write" "-sOutputFile=%o" "-f%i"
fig => "uniconvertor" "%i" "%o.svg"; mv "%o.svg" "%o"
hpg => "hp2xx" -q -m eps -f `basename "%o"` "%i"; mv -f `basename "%o"` "%o"
hpgl => "hp2xx" -q -m eps -f `basename "%o"` "%i"; mv -f `basename "%o"` "%o"
htm => "/opt/local/bin/html2ps" -U -o "%o" "%i"
html => "/opt/local/bin/html2ps" -U -o "%o" "%i"
https => "/opt/local/bin/curl" -s -k -L -o "%o" "https:%M"
ilbm => "/opt/local/bin/ilbmtoppm" "%i" > "%o"
jxr => "mv "%i" "%i.jxr"; "JxrDecApp" -i "%i.jxr" -o "%o.bmp" -c 0; \
mv "%i.jxr" "%i"; mv "%o.bmp" "%o"
man => "/opt/local/bin/groff" -man -Tps "%i" > "%o"
miff<= show "/opt/local/bin/display" -delay 0 -window-group %[group] \
-title "%l " "ephemeral:%i"
mpeg:decode => "avconv" -v -1 -i "%i" -vframes %S -vcodec pam -an -f rawvideo \
-y "%u.pam" 2> "%Z"
odt => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` \
"%i" 2> "%Z"; mv "%i.pdf" "%o"
pdf<=>eps "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 \
"-sDEVICE=epswrite" "-sOutputFile=%o" "-f%i"
pdf<=>ps "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 \
"-sDEVICE=ps2write" "-sOutputFile=%o" "-f%i"
plt => "/bin/echo" "set size 1.25,0.62; set terminal postscript portrait color \
solid; set output \'%o\'; load \'%i\'" > "%u";"/opt/local/bin/gnuplot" \
"%u"
png<= webp "/opt/local/bin/cwebp" -quiet -q %Q "%i" -o "%o"
pnm<= ilbm "/opt/local/bin/ppmtoilbm" -24if "%i" > "%o"
pov => "povray" "+i%i" -D0 "+o%o" +fn%q +w%w +h%h +a -q9 "-kfi%s" "-kff%n";\
"/opt/local/bin/convert" -concatenate "%o*.png" "%o"
ppt => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` \
"%i" 2> "%Z"; mv "%i.pdf" "%o"
pptx => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` \
"%i" 2> "%Z"; mv "%i.pdf" "%o"
ps<=>eps "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 \
"-sDEVICE=epswrite" "-sOutputFile=%o" "-f%i"
ps<=>pdf "/opt/local/bin/gsx" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT \
-dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 \
"-sDEVICE=pdfwrite" "-sOutputFile=%o" "-f%i"
ps<= print "lpr "%i"
rgba<= rle "rawtorle" -o "%o" -v "%i"
scan => "/opt/local/bin/scanimage" -d "%i" > "%o"
scanx => "/opt/local/bin/scanimage" > "%o"
shtml => "/opt/local/bin/html2ps" -U -o "%o" "%i"
sid => "mrsidgeodecode" -if sid -i "%i" -of tif -o "%o" > "%u"
svg => "/opt/local/bin/rsvg-convert" -o "%o" "%i"
tiff<= launch "/opt/local/bin/gimp" "%i"
txt<=>ps "/opt/local/bin/enscript" -o "%o" "%i"
wdp => "mv "%i" "%i.jxr"; "JxrDecApp" -i "%i.jxr" -o "%o.bmp"; mv "%i.jxr" "%i"; \
mv "%o.bmp" "%o"
webp => "/opt/local/bin/dwebp" -pam "%i" -o "%o"
wmf => "/opt/local/bin/wmf2eps" -o "%o" "%i"
xls => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` "%i" 2> "%Z"; \
mv "%i.pdf" "%o"
xlsx => "soffice" --headless --convert-to pdf --outdir `dirname "%i"` "%i" 2> "%Z"; \
mv "%i.pdf" "%o"
Path: /Users/kurtpfeifle/.magick/delegates.xml
Delegate Command
-------------------------------------------------------------------------------
flip => "convert '%i' -flip 'miff:%o"
5 Pixel dicker Rahmen:
convert logo: -frame 5 logo-framed.png
Logo mit -frame 5
…
Aber die Farbe? Ich will rot!
convert logo: -mattecolor red -frame 5 logo-framed.png
Logo mit -mattecolor red -frame 5
…
Aber rechts und links soll er dicker sein als oben und unten!
convert logo: -mattecolor red -frame 20x1 logo-framed.png
Logo mit -mattecolor red -frame 20x1
…
convert a.jpg a.png
Unschwer zu erraten, was dieses Kommando bewirkt, oder?
Beim nächsten Kommando wird’s erheblich schwerer:
convert \
label.gif \
+matte \
\
\( \
+clone \
-shade 110x90 \
-normalize \
-negate \
+clone \
-compose Plus \
-composite \
\) \
\
\( -clone 0 \
-shade 110x50 \
-normalize \
-channel BG \
-fx 0 \
+channel \
-matte \
\) \
\
-delete 0 \
+swap \
-compose Multiply \
-composite \
button.gif
Bei diesem Kommando das Ergebnis erraten? Ziemlich unmöglich…
Ein ImageMagick-Kommando besteht aus…
stream
, mogrify
, animate
oder display
)Möglich sind: convert
, composite
, montage
, compare
, import
, stream
, animate
, mogrify
, display
oder conjure
Für Input-Dateien sind folgende Konzepte möglich:
Beispiel:
convert *.jpg output.gif
Beispiel:
convert -size 640x480 -depth 8 rgb:bilddateiname image.png
Beispiel:
convert pattern:checkerboard output.png
convert pattern:hexagons output.gif
Beispiele:
convert logo: gif:- | display gif:-
convert logo: gif:fd:1 | display -resize 50% gif:fd:0
# Es gilt: STDIN == fd:0
# STDOUT == fd:1
# STDERR == fd:2
#
# Dateien mit Deskriptor-Nummern N>2 ansprechen mit fd:N
Beispiele:
convert 'multipage.tiff[4]' output.pdf
convert 'document.pdf[1]' output.jpeg
convert 'images.gif[3-7]' output.mng
# Benutzen von einfachen Anführungszeichen, damit die Shell nix falsch macht mit den eckigen Klammern
# ACHTUNG: Zählung fängt bei '0' an. Seite 1 eines PDFs also per `[0]`, Frame 3 eines animierten GIFs also per `[4]`!
Beispiele:
convert -size 6000x4000 -depth 8 'rgb:bilddateiname[500x500+2750+1750]' output.png
Beispiele:
convert '*.jpg' -resize 96x96 symbolbild-%03d.png
convert '*.jpg[96x96]' symbolbild-%03d.png # ist äquivalent
Beispiele:
convert '*.jpg' -crop 120x120+10+5 thumbnail%03d.png
convert '*.jpg[120x120+10+5]' thumbnail%03d.png # ist äquivalent
Beispiele:
convert @meine-bilder.txt mein-filmchen.gif
# wobei z.B.:
cat meine-bilder.txt
bild-001.jpg
bild-002.jpg
bild-003.jpg
oder:
convert bild-%04d.png[3-5] ...
# versucht die folgenden Bild-Dateinamen zu lesen:
bild-0003.png
bild-0004.png
bild-0005.png
Dazu gehören:
-adjoin • -affine • -alpha • -antialias • -authenticate • -background • -bias • -black-point-compensation • -blue-primary • -bordercolor • -caption • -channel • -comment • -compress • -debug • -define • -delay • -density • -depth • -direction • -display • -dispose • -dither • -encoding • -endian • -extract • -family • -fill • -filter • -font • -format • -fuzz • -geometry • -gravity • -green-primary • -interlace • -intent • -interpolate • -label • -limit • -linewidth • -log • -loop • -mask • -mattecolor • -monitor • -orient • -page • -pointsize • -preview • -quality • -quiet • -red-primary • -region • -render • -repage • -sampling-factor • -scene • -seed • -size • -stretch • -stroke • -strokewidth • -style • -texture • -tile • -transparent-color • -treedepth • -type • -undercolor • -units • -verbose • -virtual-pixel • -weight
Image Settings gelten…
Image Settings können wirken auf…
Dazu gehören:
-annotate • -black-threshold • -blur • -border • -charcoal • -chop • -clip • -clip-path • -clip-mask • -colors • -colorize • -colorspace • -compose • -contrast • -convolve • -crop • -cycle • -despeckle • -draw • -edge • -emboss • -enhance • -equalize • -evaluate • -extent • -flip • -flop • -floodfill • -frame • -gamma • -gaussian-blur • -implode • -lat • -level • -map • -median • -modulate • -monochrome • -negate • -noise • -normalize • -opaque • -ordered-dither • -paint • -posterize • -raise • -profile • -radial-blur • -raise • -random-threshold • -resample • -resize • -roll • -rotate • -sample • -scale • -sepia-tone • -segment • -shade • -shadow • -sharpen • -shave • -shear • -sigmoidal-contrast • -solarize • -splice • -spread • -strip • -swirl • -threshold • -transparent • -thumbnail • -tint • -transform • -trim • -unsharp • -version • -wave • -white-point • -white-threshold
Dazu gehören:
-append • -affinity • -average • -clut • -coalesce • -combine • -compare • -complex • -composite • -crop • -debug • -deconstruct • -delete • -evaluate-sequence • -fft • -flatten • -fx • -hald-clut • -ift • -identify • -insert • -layers • -limit • -map • -maximum • -minimum • -morph • -mosaic • -optimize • -print • -process • -quiet • -separate • -swap • -write
Image Sequence Operators unterscheiden sich von Image Settings:
Image Operators unterscheiden sich von Image Settings. Sie wirken…
Alle Kommandozeilen-Optionen, die…
…sind Image Operators.
Dazu gehören:
-adaptive-resize • -border • -borderwidth • -chop • -crop • -density • -extent • -extract • -frame • -geometry • -iconGeometry • -liquid-rescale • -page • -region • -repage • -resize • -sample • -scale • -shave • -splice • -thumbnail • -window
Generelle Syntax für das Setzen von Werten der Image Geometry Settings:
{dimension}{offset} |
Allgemeine Syntax zur Angabe von Werten für die Geometrie-Einstellungen. Innerhalb der Werte darf nirgendwo ein Leerzeichen vorkommen. |
{offset} |
Angabe von {offset} ist optional. Erfolgt in der Form ±x±y . Voreinstellung ist +0+0 . Werte in Pixeln. Bedeutung: +x bewirkt Verschiebung nach rechts; -x bewirkt Verschiebung nach links; +y verschiebt nach unten; -y verschiebt nach oben; Vorzeichen für beide Angaben sind erforderlich. |
{dimension} |
{dimension} gibt die Abmessungen oft in Form von {breite}x{hoehe} an. (Ausnahme bei Angabe von Z% oder X%xY% als prozentuale Skalierung.) Details zu {dimension} -Angaben in der nächsten Tabelle. |
Generelle Syntax für {dimension}
-Angaben zur Image Geometry (1):
Z% |
Skaliert Breite und Höhe gleichermaßen um den genannten Prozentsatz. Bewahrt das Seitenverhältnis. |
X%xY% |
Skaliert die Breite um X% , die Höhe um Y% . (Nur ein einziges % -Symbol ist erforderlich. Es sind demnach gleichbedeutend: *X%xY* , *XxY%* und *X%xY%* .) |
{Breite}x |
Skaliert die Breite auf die angegebene Anzahl von Pixeln. Höhe wird automatisch so berechnet, dass das Seitenverhältnis bewahrt bleibt. |
x{Hoehe} |
Skaliert die Höhe auf die angegebene Anzahl von Pixeln. Breite wird automatisch so berechnet, dass das Seitenverhältnis bewahrt bleibt. |
Generelle Syntax für {dimension}
-Angaben zur Image Geometry (2):
{Breite}x{Hoehe} |
Die maximale Anzahl von Pixeln für die Breite beträgt {Breite} . Die maximale Anzahl von Pixeln für die Höhe beträgt {Hoehe} . Die Skalierung erfolgt so, dass das Seitenverhältnis bewahrt bleibt. ({Breite}x{Hoehe} bildet also ein Rechteck, in welches das Bild komplett reinpasst.) |
{Breite}x{Hoehe}^ |
Das ^ -Zeichen am Ende ist signifikant. Die minimale Anzahl von Pixeln für die Breite beträgt {Breite} . Die minimale Anzahl von Pixeln für die Höhe beträgt {Hoehe} . Die Skalierung erfolgt so, dass das Seitenverhältnis bewahrt bleibt. ({Breite}x{Hoehe} bildet also ein Rechteck, welches in das Bild komplett reinpasst.) |
Generelle Syntax für {dimension}
-Angaben zur Image Geometry (3):
{Breite}x{Hoehe}! |
Das ! -Zeichen am Ende ist signifikant. Die exakte Anzahl von Pixeln für die Breite beträgt {Breite} . Die exakte Anzahl von Pixeln für die Höhe beträgt {Hoehe} . Die Skalierung erfolgt so, dass das Seitenverhältnis gegebenenfalls völlig ignoriert wird.. ({Breite}x{Hoehe} bildet also ein Rechteck, welches das Bild komplett ausfüllt, gegebenenfalls mit entsprechender Verzerrung [Dehnung oder Stauchung in eine oder zwei Richtungen].) |
{Breite}x{Hoehe}> |
Das > -Zeichen am Ende ist signifikant. Verkleinert ein Bild, falls es in einer oder beiden Dimensionen größer ist als die entsprechende Angabe(n). |
Generelle Syntax für {dimension}
-Angaben zur Image Geometry (4):
{Breite}x{Hoehe}< |
Das < -Zeichen am Ende ist signifikant. Vergrößert ein Bild, falls es in einer oder beiden Dimensionen kleiner ist als die entsprechende Angabe(n). |
{Gebiet}@ |
Größen-Veränderung des Bildes auf das spezifizierte Gebiet. Seitenverhältnis bleibt erhalten. |
Folgende Parameter erfordern die Übergabe von geometry
-Werten, meist in der Form WxH±x±y
:
-density geometry # horizontal and vertical density of the image
-page geometry # size and location of an image canvas (setting)
-sampling-factor geometry
-size geometry # width and height of image
-tile-offset geometry
-adaptive-blur geometry
-adaptive-resize geometry
-adaptive-sharpen geometry
-annotate geometry # text
-blur geometry # reduce image noise and reduce detail levels
-border geometry # surround image with a border of color
-brightness-contrast geometry #
-canny geometry # detect edges in the image
-chop geometry # remove pixels from the image interior
-contrast-stretch geometry
-extent geometry # set the image size
-extract geometry # extract area from image
-floodfill geometry # color
-frame geometry # surround image with an ornamental border
-gaussian-blur geometry
-geometry geometry # preferred size or location of the image
-hough-lines geometry
-interpolative-resize geometry
-lat geometry # local adaptive thresholding
-linear-stretch geometry
-liquid-rescale geometry
-mean-shift geometry # delineate arbitrarily shaped clusters in the image
-median geometry # apply a median filter to the image
-mode geometry # make each pixel the 'predominant color' of the
-motion-blur geometry
-noise geometry # add or reduce noise in an image
-region geometry # apply options to a portion of the image
-repage geometry # size and location of an image canvas
-resample geometry # change the resolution of an image
-resize geometry # resize the image
-roll geometry # roll an image vertically or horizontally
-sample geometry # scale image with pixel sampling
-scale geometry # scale the image
-selective-blur geometry
-shadow geometry # simulate an image shadow
-sharpen geometry # sharpen the image
-shave geometry # shave pixels from the image edges
-shear geometry # slide one edge of the image along the X or Y axis
-sigmoidal-contrast geometry
-sketch geometry # simulate a pencil sketch
-splice geometry # splice the background color into the image
-statistic type geometry
-thumbnail geometry # create a thumbnail of the image
-unsharp geometry # sharpen the image
-vignette geometry # soften the edges of the image in vignette style
-wave geometry # alter an image along a sine wave
-crop geometry # cut out a rectangular region of the image
-smush geometry # smush an image sequence together
Ein Image Stack erlaubt es, ein einzelnes Bild (oder eine Bild-Sequenz) von der Haupt-Kommandozeile zu separieren und sozusagen erstmal ‘beiseite zu nehmen’, außerhalb der Haupt-Kommandozeile zu manipulieren, und dann das Ergebnis dieses Neben-Geleises wieder in die Haupt-Kommandozeile einzuspeisen.
Einen Image Stack umschließt man in runden Klammern, die man per Rückstrich/backslash escapen muss, und die (mindestens) ein zusätzliches Leerzeichen vom Image Stack trennt: \( ...image stack... )\
Beispiel: Kommando
convert wand.png \( wizard.jpg -rotate 30 \) +append images.png
^ ^ ^^^^^ ^ ^ ^^^^ ^ ^
| | ||||| | | |||| | |
| | ||||| | | |||| | +----Ausgabe-Datei (Ergebnis)
| | ||||| | | |||| |
| | ||||| | | |||| +----Image Sequence Operator (hängt Ergebnis
| | ||||| | | |||| des Image Stacks an die Input-Datei)
| | ||||| | | ||||
| | ||||| | | |||+----zusätzliches Leerzeichen zur Abtrennung
| | ||||| | | ||| des Image Stacks
| | ||||| | | ||+----runde Schließklammer zur Abtrennung des
| | ||||| | | || Image Stacks
| | ||||| | | |+----Rückstrich zum Escapen der runden
| | ||||| | | | Schließklammer
| | ||||| | | +----zusätzliches Leerzeichen zur Abtrennung des
| | ||||| | | Image Stacks
| | ||||| | +----Parameter für den Image Operator des
| | ||||| | Image Stacks
| | ||||| +----Image Operator des Image Stacks: rotiert das Bild
| | ||||| des Image Stacks
| | ||||+----Input-Bild des Image Stacks
| | ||||
| | |||+----zusätzliches Leerzeichen zur Abtrennung des Image Stacks
| | |||
| | ||+----runde Öffnungsklammer zur Abtrennung des Image Stacks
| | ||
| | |+----Rückstrich zum Escapen der runden Öffungsklammer
| | |
| | +----zusätzliches Leerzeichen zur Abtrennung des Image Stacks
| |
| +----Input-Datei
|
+----Kommando
Beispiel: Ergebnis
Ergebnis von: convert wizard: \( wizard: -resize 80% -rotate -30 \) +append -mattecolor red -frame 3x3 images.png
ImageMagick kennt mehrere Konzepte, um die Ausgabe-Dateinamen zu spezifizieren::
STDOUT
convert input.png OUT.JPEG
convert input.png OUT.jpeg
convert input.png OUT.JpgG
convert input.png OUT.JpEg
convert input.png OUT.png
convert input.png OUT.TIFF
convert input.png OUT.tIFF
convert input.png OUT.TIf
convert input.png jpeg:OUT.data
convert input.png Jpeg:OUT.dat
convert input.png jpeg:OUT
convert input.png jPEg:OUT.jpg
convert input.png jpeg:OUT.png # Auch hier entsteht ein JPEG!
convert input.png PNG:OUT
convert input.png Tiff:OUT
convert input.png tif:OUT
Angenommen, in der Textdatei meine-bilder.txt
stehen die Dateinamen verschiedener Bilder, durch Leerraum getrennt:
erste.Tif zweite.PNG dritte.jpg
"die vierte.jpeg"
fuenf.gif
rose:
[...]
Dann kann ImageMagick alle in der Datei genannten Bilder wie folgt verwenden:
convert @meine-bilder.txt output.gif
convert @meine-bilder.txt *.png
STDOUT
convert input.png jpeg:-
convert input.png Jpeg:fd:1
Wiederholung: Es gibt drei grundsätzlich unterschiedliche Kategorien von Kommando-Parametern.
Alle diese Parameter gibt es (mindestens) in der Form -parameter ...
. Die meisten davon gibt es außerdem in der Abwandlung +parameter ...
. Die +
-Form modifiziert die Bedeutung der -
-Form.
Nochmals: im Zweifel bitte die Ausgabe von convert -help
konsultieren. Diese listet alle Parameter nach Kategorien getrennt auf.
…und zwar soll der Dateiname in die jeweilige Abbildung integriert werden.
Initiale Abbildung, erster Versuch:
convert \
nature-FbJDP.png \
-gravity south \
-annotate 0 '%f' \
nature-output.jpg
Abbildung original (links) — mit fast unlesbarer Beschriftung (Mitte) — besser… (rechts)
Kommando:
for img in *.png; do
width=$(identify -format %W ${img})
width=$(( ${width} * 9 / 10 ))
convert \
-background '#0008' \
-gravity center \
-fill yellow \
-size ${width}x100 \
caption:"${img}" \
"${img}" \
+swap \
-gravity south \
-composite \
"with-caption-${img}"
done
Noch mehr Text… Geht das auch?
width=$(identify -format %W nature-FbJDP.png)
convert \
-background '#0008' \
-gravity center \
-fill white \
-size ${width}x100 \
caption:"This is a sample text to test \
the automatic sizing of fonts by ImageMagick." \
nature-FbJDP.png \
+swap \
-gravity north \
-composite \
output1.png
convert \
-background '#0008' \
-gravity center \
-fill white \
-size ${width}x100 \
caption:"This is a even longer sample text. \
It also serves to test if automatic sizing of fonts \
by ImageMagick works as expected: just don't specify \
any fontsize, and let ImageMagick go for the best fit..." \
nature-FbJDP.png \
+swap \
-gravity north \
-composite \
output2.png
Abbildung original (links) — mit mehr Text (Mitte) — mit viiiieeel mehr Text… (rechts). Textbox-Größe war fix – ImageMagick passte die Font-Größe automatisch so an, dass der Text reinpasst.
Übrigens kann man auch ganze Textseiten zu einem Bild konvertieren:
man convert \
| \
col -b \
| expand \
| \
head -n 17 \
| \
convert -font Source-Code-Pro \
-background lightblue \
-fill blue \
-size 700x350 \
text:- \
-delete 1--1 \
-trim \
text_manpage.png
Ergebnis:
Man page für convert
zu einem GIF der Größe 700x350 gewandelt…
convert logo: -crop 300x300+150+150 logo-cropped.png
logo-cropped.png
Kommando:
# Generierung von 121 PNGs:
for i in {100..120}; do
convert logo: -scale ${i}x logo-${i}-breit.png
done
# Kommando zum Erzeugen eines ersten GIFs:
convert \
logo-1??-breit.png \
\( \
-clone 1--1 \
\) \
logo-animiert-1.gif
# Kommando zum Erzeugen des zweiten GIFs:
convert \
logo-1??-breit.png \
\( \
-clone 1--1 \
-reverse \
\) \
logo-animiert-2.gif
Ergebnis:
Lässt sich leider in PDF nicht animiert darstellen… Es sind zwei animierte GIFs entstanden. Der Unterschied, den der Zusatz-Parameter -reverse
des 2. Kommandos ausmacht, ist beim Vergleich der Ergebnisse leicht zu erkennen.
Kommentiertes Kommando:
for i in {100..120}; do # Erstellt in einer Schleife insgesamt 121 PNGs
convert logo: -scale ${i}x logo-${i}-breit.png #+ mit Dateienamen 'logo-100-breit.png' bis
done #+ 'logo-120-breit.png'. Deren Breite in Pixeln
#+ variiert von 100 bis 120 px.
convert \ # Startet die ImageMagick; bereitet es auf die Aufgabe "Konvertierung" vor.
logo-1??-breit.png \ # Lädt alle zuvor erstellten 'logo-1xx-breit.png'-Bilder in aufsteigender Folge.
\ # ImageMagick hat jetzt 121 Bilder geladen.
\( \ # Startet einen neuen 'image stack' --- außerhalb des Haupt-Kommandos.
-clone 1--1 \ # Klont die bisher geladenen Bilder von Index '1' bis Index '-1'.
\ # Im externen Stack befinden sich jetzt die Bilder 'logo-100*' bis 'logo-120*'.
-reverse \ # Kehrt die Reihenfolge aller Bilder im externen 'image stack' um.
\ # Im externen Stack befinden sich jetzt die Bilder 'logo-120*' bis 'logo-100*'.
\) \ # Beendet den 'image stack' und lädt alle Bilder darin ins Haupt-Kommando.
\ # Im Haupt-Stack befinden sich jetzt insgesamt 242 Bilder (die 121 ursprünglichen
\ #+ sowie die 121 ge-klonten in umgekehrter Reihenfolgen.
logo-animiert.gif # Erzeugt ein GIF aus den geladenen Bildern. Bei mehreren geladenen Bildern
#+ ist das Resultat automatisch ein animiertes GIF.
Geschwindigkeit der Animation, Wiederholung/Looping ist selbstverständlich über zusätzliche Parameter beinflußbar…
Auch: aus einem *.AVI ein animiertes *.GIF!
convert -quiet -delay 1 some.avi some.gif
Zuerst 2 oder mehr verschiedene (aber ähnliche!) Bilder herstellen:
convert rose: rose.png
convert rose: rose.jpg
convert rose: rose.tif
convert rose: rose.gif
Dann vergleichen mit dem compare
-Kommando, dabei das Vergleichs-Ergebnis jeweils in eine Datei delta-....png
schreiben:
compare rose.png rose.png delta-png-png.png
compare rose.png rose.jpg delta-png-jpg.png
compare rose.png rose.tif delta-png-tif.png
compare rose.png rose.gif delta-png-gif.png
compare rose.jpg rose.tif delta-jpg-tif.png
compare rose.jpg rose.gif delta-jpg-gif.png
compare rose.tif rose.gif delta-tif-gif.png
Per Default ist in den “Delta”-Dateien im Hintergrund die zweite Vergleichsdatei (etwas ausgegraut) eingeblendet. Die Differenz-Pixel sind rot, die identischen Pixel sind weiß.
Wie man sieht: die verlustfreien Formate PNG und TIFF zeigen überhaupt keine roten Pixel, also gar keine Unterschiede. . Zwischen diesen und den verlust-behafteten Formaten JPEG und GIF ist praktisch jeder einzelne Pixel verschieden – wenn auch eventuell nur mit leicht unterschiedlichen Farbwerten.
Wenn man über sehr kleine Unterschiede hinwegsehen möchte, kann man per -fuzz 3%
z.B. alle Differenzen ausblenden, die kleiner als 3% sind. Mit den Zusatz-Optionen -highlight-color
und -lowlight-color
kann man statt der rot-weissen Darstellung der Unterschiede andere Farben erzwingen.
compare rose.png rose.png -highlight-color blue -fuzz 3% delta-png-png-fuzz-3pc.png
compare rose.png rose.jpg -highlight-color blue -fuzz 3% delta-png-jpg-fuzz-3pc.png
compare rose.png rose.tif -highlight-color blue -fuzz 3% delta-png-tif-fuzz-3pc.png
compare rose.png rose.gif -highlight-color blue -fuzz 3% delta-png-gif-fuzz-3pc.png
compare rose.jpg rose.tif -highlight-color blue -fuzz 3% delta-jpg-tif-fuzz-3pc.png
compare rose.jpg rose.gif -highlight-color blue -fuzz 3% delta-jpg-gif-fuzz-3pc.png
compare rose.tif rose.gif -highlight-color blue -fuzz 3% delta-tif-gif-fuzz-3pc.png
Das Beispiel rose:
als Ausgangspunkt zur Demo des compare
-Kommandos war evtl. nicht das best-geeignetste (es war die kleinste Beispiel-Datei, die gerade vorhanden war und sich zum Einbau in diese HTML-Seite eignet.)
compare
arbeitet mit einer Voreinstellung von 72 PPI. Sehr häufig reicht das aus, um vorhandene Unterschiede grob zu visualisieren. Wer eine feinere Auflösung benötigt, kann per -density 200
, -density 600
oder -density 345
eine beliebig höhere Auflösung wählen. Der Vergleichsvorgang dauert hier natürlich etwas länger und die erzeugte “Delta”-Datei wird größer!
Man kann compare
auch verwenden, um feinste (oder auch gröbere) Unterschiede sichtbar zu machen z.B. zwischen zwei PDF-Seiten:
Erstellung zweier leicht unterschiedlicher PDFs mit Ghostscript
gs -o pdf1.pdf \
-sDEVICE=pdfwrite \
-g3000x500 \
-c "/Courier findfont 32 scalefont setfont \
10.0 10.0 moveto \
(Hello, UbuCon!) show \
showpage"
gs -o pdf2.pdf \
-sDEVICE=pdfwrite \
-g3000x500 \
-c "/Courier findfont 32 scalefont setfont \
10.1 10.1 moveto \
(Hello, UbuCom!) show \
showpage"
Vergleichen:
compare pdf1.pdf pdf2.pdf delta-pdf.png
compare -density 600 pdf1.pdf pdf2.pdf delta-pdf-600ppi.png
compare -density 600 pdf1.pdf pdf2.pdf -compose src delta-pdf-600ppi-src.png
Wer den ausgegrauten Hintergrund der Referenz-Datei nicht sehen möchte, blendet ihn durch Hinzufügen von -compose src
komplett aus. Übrig bleiben nur die roten und weißen Pixel.
Bei genauem Hinschauen zeigt sich, dass die gröbere Auflösung von 72 PPI zwar ausreicht, um die unterschiedlichen Buchstaben n
und m
zu erfassen. Dass der Buchstabe l
bei 72 PPI scheinbar sehr stark abweichend positioniert ist, alle anderen Buchstaben jedoch “perfekt”, liegt daran, …
Die systematische Verschiebung der Worte oben und links um jeweils einen Zehntel Punkt zu erkennen, gelang erst bei 600 PPI…
Kommando:
convert logo: -resize '500x250!' resized-logo.png
Ergebnis:
Logo, gestaucht
Ausgangspunkt:
Perspektiven-Änderung: aus rotem ‘Schief’-Eck soll blaues Rechteck werden
convert \
-verbose \
http://i.stack.imgur.com/SN7sm.jpg \
-matte \
-virtual-pixel transparent \
-distort perspective '7,40 4,30 4,124 4,123 85,122 100,123 85,2 100,30' \
output.png
Ist Euch was aufgefallen? ImageMagick kann sich Input auch per HTTP (und per HTTPS ebenfalls) aus dem Web holen!
Operation:
Perspektiven-Änderung: alt (links) und neu (rechts)
Magick’s image operator war hier: -distort perspective
.
Dieser operator nimmt als Argumente 8 verschiedene Pixel-Koordinaten:
7,40
==> 4,30
4,124
==> 4,123
85,122
==> 100,123
85,2
==> 100,30
Der rote Rahmen zeigt die 4 Original-Koordinaten. Der blaue Rahmen zeigt die 4 Ziel-Koordinaten.
Bild-Dimensionen:
Frage stammt von Stackoverflow.com. Leider waren die Angaben nicht so ganz eindeutig.
Dies sind die Größen-Verhältnisse von Original-Bild und Ziel-Bild:
Original-Bild
Vergleich der Dimensionen von Original-Bild und Zielbild zeigt, dass die Skalierung unter Beibehaltung des Seitenverhältnisses nicht möglich ist…
Es gibt also verschiedene Möglichkeiten, das Bild zu verkleinern. Sehen wir sie uns an…
convert WPTgp.jpg -gravity Center -crop 290x310+0+0 WPT-cropped.jpg
WPT-cropped.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-cropped.jpg
290 Pixel breit, 310 Pixel hoch
convert WPTgp.jpg -resize x310 WPT-keep-height.jpg
WPT-keep-height.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-keep-height.jpg
237 Pixel breit, 310 Pixel hoch
convert WPTgp.jpg -resize 290x WPT-keep-width.jpg
WPT-keep-width.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-keep-width.jpg
290 Pixel breit, 380 Pixel hoch
convert WPTgp.jpg -resize 290x310\! WPT-distorted.jpg
WPT-distorted.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-distorted.jpg
290 Pixel breit, 310 Pixel hoch
convert WPTgp.jpg \
-resize 290x310 \
-gravity center \
-background orange \
-extent 290x310 \
WPT-padded.jpg
WPT-padded.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-padded.jpg
290 Pixel breit, 310 Pixel hoch
Wer die “Seam Carving”-Methode nicht kennt, sollte sich mal per Suchmaschine über diese Technologie erkundigen. Und da z.B. auf den folgenden Link stoßen:
Aber auf einmal (d.h. in einem einzigen Schritt) geht’s leider nicht! Dann geht’s schief, weil das Bild ja in zwei Dimensionen verändert werden soll, sowohl Breite, als auch Höhe:
convert WPTgp.jpg -liquid-rescale 290x310\! WPT-liquid-gone-wrong.jpg
WPT-liquid-gone-wrong.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-liquid-gone-wrong.jpg
290 Pixel breit, 310 Pixel hoch
Aber in 2 Schritten funktioniert’s:
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 290x310 WPT-liquid-1.jpg
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 48.4% WPT-liquid-2.jpg
WPT-liquid-1.jpg
identify -format "%W Pixel breit, %H Pixel hoch\n" WPT-liquid-{1,2}.jpg
290 Pixel breit, 310 Pixel hoch
290 Pixel breit, 310 Pixel hoch
Die Zeit ist jetzt leider um…