新卒エンジニア研修の座学でImageMagickの話をしました。
ը૾ՃαʔόΛ࡞ͬͯΈΑ͏Լॏതࢿ(.01FQBCP *OD৽ଔΤϯδχΞݚम࠲ֶ*NBHF.BHJDL࣮ફೖ
View Slide
ΤϯδχΞ ೖࣾɾ৽ଔظԼॏതࢿ!TIJNPKV@&$ࣄۀ෦46;63*νʔϜTIJNPKVPSH
͓͠ͳ͕͖wࠓͷΰʔϧw46;63*ͱը૾ॲཧw*NBHF.BHJDLΛ৮ͬͯΈΑ͏wը૾ՃαʔόΛ࡞ͬͯΈΑ͏
ࠓͷΰʔϧw*NBHF.BHJDLΛ༻ͨ͠ը૾ՃΛͬͯΈͯɺwը૾ॲཧͨͷͦ͠͏ʂͬͯͳΔ͜ͱwഎޙʹ͋ΔࣜɺମܥతͳཧղͷͨΊͷཧʹ͍ͭͯ ൃදऀͷࣝෆʹΑΓѻ͍·ͤΜ
46;63*ͱը૾ॲཧ
46;63*ͱը૾ॲཧwΞοϓ͞Εͨը૾ΛΞΠςϜը૾ͱ߹ͯ͠αϜωΠϧΛ࡞Δw5γϟπͷγϫʹ߹Θͤͯը૾Λมܗ σΟεϓϨΠεϝϯτϚοϐϯάͤͨ͞ΓwӨΛ͚ͭͨΓ৭Λมͨ͠Γ
*NBHF.BHJDLΛ৮ͬͯΈΑ͏
ͱΓ͋͑ͣΠϯετʔϧ$ brew install imagemagickOR$ sudo apt-get install -y imagemagickOR$ sudo yum -y install ImageMagick
*NBHF.BHJDLwը૾Ճͱ͍͑͜Εͱ͍͏༗໊ϥΠϒϥϦwϝδϟʔ͔ΒϚΠφʔ·Ͱ͞·͟·ͳը૾ܗࣜʹରԠwػೳ͕ଟ͗ͯ͢੬ऑੑͨͼͨͼൃݟ͞ΕΔ͘Β͍ʜw$Ͱ࣮͞Εɺଟ͘ͷݴޠͰόΠϯσΟϯά͕͋Δw3VCZɿSNBHJDL NJOJ@NBHJDLHFNw1)1ɿ*NBHJDL֦ுϥΠϒϥϦͳͲ
ίϚϯυwJNBHFNBHJDLͱ͍͏ίϚϯυͳ͍ wػೳ͝ͱʹDPOWFSUJEFOUJGZͳͲͷίϚϯυʹΘ͔Ε͍ͯΔwͨͩ͠ɺ*NBHF.BHJDL͔Βͯ͢NBHJDLίϚϯυͷγϯϘϦοΫϦϯΫʹͳ͍ͬͯΔ
*NBHF.BHJDL 6CVOUV$ ls -Alh /usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16total 88K-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 animate-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 compare-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 composite-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 conjure-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 convert-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 display-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 identify-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 import-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 mogrify-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 montage-rwxr-xr-x 1 root root 6.3K Jul 31 13:22 stream
*NBHF.BHJDL .BD)PNFCSFX$ ls -Alh /usr/local/Cellar/imagemagick/7.0.7-7/bin | grep -v configtotal 64lrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 animate -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 compare -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 composite -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 conjure -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 convert -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 display -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 identify -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 import -> magick-r-xr-xr-x 1 shimoju admin 18K 10 9 18:25 magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 magick-script -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 mogrify -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 montage -> magicklrwxr-xr-x 1 shimoju admin 6B 10 7 21:02 stream -> magick
JEFOUJGZwը૾ͷใΛग़ྗͰ͖ΔwαΠζΛͬ͞ͱΓ͍ͨͱ͖ͱ͔ɺwେྔͷը૾ͷத͔ΒαΠζ͕ҧ͏ͷΛ୳ͨ͠Γͱ͔
JEFOUJGZ$ identify *.jpgoriginal.jpg JPEG 800x533 800x533+0+0 8-bit sRGB 104823B 0.000u 0:00.000resize.jpg JPEG 400x267 400x267+0+0 8-bit sRGB 37116B 0.000u 0:00.000ϑΥʔϚοτจࣈྻ͜͜ΒΜࢀরɿhttps://www.imagemagick.org/script/escape.php$ identify -format '{"width": %w, "height": %h}' *.jpg | jq{"width": 800,"height": 533}$ identify -format '%wx%h %f\n' *.jpg | grep -v 800x533200x200 crop.jpg
DPOWFSUw͞·͟·ͳը૾ՃΛߦ͑Δɺ*NBHF.BHJDLͷϝΠϯίϚϯυwҎ߱ͯ͢DPOWFSUίϚϯυΛѻ͍͖ͬͯ·͢
దͳը૾Λ༻ҙ͠·͢ਖ਼ํܗ͡Όͳ͍΄͏͕͍͍Ͱ͢ɻ͜ͷը૾YQYग़యɿIUUQTXXXQBLVUBTPDPNQPTUIUNM
ճస SPUBUFճస$ convert -rotate 90 original.jpg rotate.jpg্Լస$ convert -flip original.jpg flip.jpgࠨӈస$ convert -flop original.jpg flop.jpg্Լࠨӈస$ convert -flip -flop original.jpg flipflop.jpg
αϯϓϧ TBNQMFϐΫηϧΛؒҾ͘$ convert -sample 10% original.jpg sample.jpg10%ʹͳΔΑ͏ʹϐΫηϧΛؒҾ͍ͨ͋ͱɺ1000%ʹͳΔΑ͏ʹ֦େ→ݩը૾ͱಉ͡αΠζͰϞβΠΫ͕͔͔Δ$ convert -sample 10% -sample 1000% original.jpg sample.jpg
ϦαΠζ SFTJ[FσϑΥϧτͰΞεϖΫτൺΛม͑ͳ͍ɿࢦఆͨ͠෯ɾߴ͞ʹऩ·ΔΑ͏ʹϦαΠζ͞ΕΔ$ convert -resize 400x400 original.jpg resize.jpg$ identify resize.jpgresize.jpg JPEG 400x267 400x267+0+0 8-bit sRGB 37116B 0.000u 0:00.000!Λ͚ͭΔͱΞεϖΫτൺΛແࢹͯ͠ࢦఆͨ͠ʹϦαΠζ͢Δ$ convert -resize 400x400! original.jpg resize2.jpg෯·ͨߴ͞ͷΈࢦఆͰ͖Δ$ convert -resize 400x original.jpg resize3.jpg
Τοδݕग़ FEHFෆ࿈ଓʹมԽ͍ͯ͠ΔՕॴΛݕग़͢Δ$ convert -edge 5 original.jpg edge.jpgΛมԽͤͯ͞ΈΑ͏$ convert -edge 10 original.jpg edge.jpg$ convert -edge 1 original.jpg edge.jpg
Γൈ͖ DSPQ-gravityͰج४Λࢦఆ-crop widthxheightͰΓൈ͘αΠζΛࢦఆ+/-Ͱج४͔Βͷx,y࠲ඪΛࢦఆ$ convert -gravity center -crop 200x200+0+0 original.jpg crop.jpgը૾ӈ্Λج४ʹɺxʹ140px,yʹ50pxҠಈ͠ɺͦͷ͔Β200x200pxΓൈ͘$ convert -gravity northeast -crop 200x200+140+50 original.jpg crop.jpg
ృΓ͠ FYUFOUࢦఆͨ͠αΠζʹͳΔΑ͏ʹ༨നΛՃ͢Δ༨നͷ৭-backgroundͰࢦఆͰ͖Δਖ਼ํܗͷαΠζ͕ඞཁͳͷʹ4:3ͷը૾͔͠ͳ͍ͱ͔ʹศར$ convert -background black -gravity center \-extent 800x800 original.jpg extent.jpgPNG(ಁա͕ѻ͑ΔϑΥʔϚοτ)Ͱ͋ΕtransparentͰಁաͰ͖Δ$ convert -background transparent -gravity north \-extent 1000x1000 original.jpg extent.png
ͦΖͦΖ߹ͨ͘͠ͳ͖ͬͯͨΑͶʁ
ͦͷલʹจࣈͷը૾Λ࡞͓ͬͯ͜͏$ convert -background transparent \-fill '#ff6060' -font Arial -pointsize 128 label:LGTM lgtm.pngࢦఆαΠζͰ࡞$ convert -size 400x200 -gravity center -background transparent \-fill '#ff6060' -font Arial -pointsize 128 label:LGTM lgtm.png
߹ DPNQPTJUForiginal.jpgͷ্ʹlgtm.pngΛ߹ͯ͠ɺcompose-over.jpgͱͯ͠ग़ྗ$ convert original.jpg lgtm.png -gravity center \-compose over -composite compose-over.jpg-geometryͰج४͔ΒҠಈ$ convert original.jpg lgtm.png -gravity center -geometry +150+50 \-compose over -composite compose-over.jpg
ඳըϞʔυ CMFOENPEF-composeͰඳըϞʔυΛࢦఆ͢Δࢉ (multiply)$ convert original.jpg lgtm.png -gravity center -geometry +150+50 \-compose multiply -composite compose-multiply.jpgΦʔόʔϨΠ (overlay)$ convert original.jpg lgtm.png -gravity center -geometry +150+50 \-compose overlay -composite compose-overlay.jpgݮࢉ (subtract)$ convert original.jpg lgtm.png -gravity center -geometry +150+50 \-compose subtract -composite compose-subtract.jpg
ඳըϞʔυ CMFOENPEFwॏͶΒΕͨը૾ΛͲͷΑ͏ʹ߹͢Δ͔ΛࢦఆͰ͖Δw IUUQJNBHFNBHJDLSVMF[KQBSDIJWFTw1IPUPTIPQͳͲͷը૾ฤूιϑτʹ͋Δͷͱಉ༷w࣮ࡍͲΜͳܭࢉͰࢉग़͞ΕΔ͔ιʔεΛಡΊΘ͔Δʜ͕ɺײ֮Λ͔ͭΉʹ(*.1ͷυΩϡϝϯτ͕Θ͔Γ͍͢w IUUQTEPDTHJNQPSHKBHJNQDPODFQUTMBZFSNPEFTIUNMwྫʣࢉɿ߹ը૾ͷ৭্ଆͷ৭Լଆͷ৭
ը૾ՃαʔόΛ࡞ͬͯΈΑ͏
-FOTɿ46;63*ͷը૾Ճαʔόw46;63*Ͱ͍ͬͯΔը૾ՃαʔόΛʮ-FOTʯͱݺΜͰ͍Δwը૾ॲཧʹ*NBHF.BHJDLΛ༻w5γϟπͷαϜωΠϧը૾ੜॲཧ͜͜ΒΜw ࣾϦϙδτϦͷ63-ͷͨΊলུ
-(5.(FOFSBUPS ͯ͠ͳ͍wͦͷ໊ʮ:04"406ʯwIUUQTHJUIVCDPNTIJNPKVZPTBTPVw3&"%.&ΛಡΜͰΠϯετʔϧ͍ͯͩ͘͠͞wॳճͷϏϧυͪΐͬͱ͕͔͔࣌ؒΓ·͢ʜʜwϦϙδτϦԼʹదͳը૾Λஔ͍ͯɺ IUUQMPDBMIPTUJNBHFTJNBHFKQHʹΞΫηεͯ͠ΈΔ
(Pݴޠw(PPHMF͕։ൃͨ͠ɺ͍ΖΜͳͷ͕ͳ͍ݴޠ ౖΒΕͦ͏wΫϥε͕ͳ͍ɺΑͬͯܧঝͳ͍wྫ֎͕ͳ͍wδΣωϦΫε͕ͳ͍wؔܕ༝དྷͷύϥμΠϜͳ͍wෆมม0QUJPOBMɺNBQpMUFSͳͲͷίϨΫγϣϯૢ࡞
(Pݴޠwݴޠ༷Λখ͘͢͞Δ͜ͱͰɺίϯύΠϧ͕ߴͰशಘ༰қw͔ͳ͍ྖҬ͋Δ͕ɺదͨ͠ྖҬͰҖྗΛൃش͢ΔwόΠφϦ͕ੜ͞ΕΔͨΊɺ$-*πʔϧϛυϧΣΞʹศརw੩తܕͷԸܙΛड͚ͳ͕ΒɺܕਪͰܕΛ໌ࣔͤͣʹ։ൃͰ͖ΔwฒߦॲཧΛߦ͏ͨΊͷݴޠ༷ HPSPVUJOF͕͋Γɺൺֱత؆୯ʹฒߦϓϩάϥϛϯά͕Ͱ͖Δ
දతͳιϑτΣΞwίϚϯυϥΠϯπʔϧwHIRɺQUɺIVHPɺOZBIDMJwϛυϧΣΞɾαʔόw%PDLFSɺDPOTVMɺ%SPOFɺ45/4wൺֱతখ͞ͳ ϚΠΫϩαʔϏεࢦͳ"1*αʔόwϩϦϙοϓʂϚωʔδυΫϥυͷ"1*αʔόwը૾Ճɾ৴αʔϏε*NBHF'MVY
ίʔυΛಡΜͰΈΑ͏wNBJOHPwΤϯτϦϙΠϯτɻϦΫΤετϧʔλʔίϯτϩʔϥʔw4JOBUSBͳͲͷΑ͏ͳϚΠΫϩϑϨʔϜϫʔΫελΠϧwDPOWFSUFSJNBHFHPwը૾ՃΛநԽͨ͠ύοέʔδɻ͜͜Ͱ*NBHF.BHJDLΛར༻
ίʔυΛ͍ͬͯ͡ΈΑ͏wυΩϡϝϯτΛಡΈͳ͕ΒwJNBHJDLɿDPOWFSUFSJNBHFHPͰར༻wIUUQTHPEPDPSHHPQLHJOHPHSBQIJDTJNBHJDLWJNBHJDLwHJOɿNBJOHPͰར༻wIUUQTHPEPDPSHHJUIVCDPNHJOHPOJDHJO
·ͱΊw46;63*Ͱը૾ॲཧ͕Ͳ͏ΘΕ͍ͯΔ͔Λͬͨw*NBHF.BHJDLΛͬͨ؆୯ͳը૾ՃΛͬͯΈͨwը૾ՃαʔόΛ͍ͬͯ͡Έͨw(Pݴޠʹ৮ΕͯΈͨ
·ͱΊwΰʔϧୡͰ͖·͔ͨ͠ʁw*NBHF.BHJDLΛ༻ͨ͠ը૾ՃΛͬͯΈͯɺwը૾ॲཧͨͷͦ͠͏ʂͬͯͳΔ͜ͱ
͜ΕͰ܅-(5.ը૾࡞Γ์ͩʂ