Définir un fond transparent à l'aide d'ImageMagick et de l'invite de ligne de commande

120

Supposons que vous ayez une image (PNG ou JPG). Cette image a un fond blanc et j'ai besoin de rendre ce fond transparent.

J'ai essayé avec ces exemples:

  • convert original.png -background none transparent.png
  • convert original.png -background white -flatten -alpha off transparent.png

mais sans résultats souhaitables.

Comment puis-je le faire?

IMPORTANT: utilisation convertde la ligne de commande.

Israël
la source
Odd - Je pensais que la commande pertinente était convert original.png -transparent white new.pngmais en l'essayant, je ne peux pas la faire fonctionner. En passant, êtes-vous sûr que votre arrière-plan est en fait blanc (#FFFFFF), ou est-il juste presque blanc (par exemple #FEFEFE)?
mathématique.coffee
@ mathematical.coffee Ok je comprends, laissez-moi vérifier si ce n'est pas le cas et je vais continuer ce fil. Je vous remercie.
Israël
@ mathématique.coffee Salut encore, j'ai vérifié les couleurs et cette image a un arrière-plan comme #FFFFFF, en d'autres termes "blanc". :( Ce n'est pas le cas!
Israël

Réponses:

140

J'utilise ImageMagick 6.6.9-7 sur Ubuntu 12.04.
Ce qui a fonctionné pour moi était le suivant:

convert test.png -transparent white transparent.png

Cela a changé tout le blanc du test.png en transparent.

Rijk
la source
6
Cela n'a pas fonctionné pour moi jusqu'à ce que je réalise que JPG ne sera pas transparent. Une fois que je suis passé au PNG, il a fait exactement ce que je voulais - il me suffit de changer "blanc" en "rgb ($ r, $ g, $ b)".
Roger Dueck
2
Bon Dieu! c'est bien!
agilob
2
Cela convertira non seulement l'arrière-plan en transparent, mais chaque pixel blanc. Existe-t-il un moyen de convertir l'arrière-plan uniquement en transparent?
Alejandro Lozdziejski
2
@AlejandroLozdziejski - comment définissez-vous "l'arrière-plan"?
Jules
1
@AlejandroLozdziejski: Bonne question. Veuillez voir ma solution qui utilise un remplissage à partir des bords, à la recherche de couleurs à peu près identiques à celles du pixel supérieur gauche.
hackerb9
79

J'ai eu le même problème. Dans lequel je dois supprimer le fond blanc du format d'image jpg / png en utilisant ImageMagick.

Ce qui a fonctionné pour moi était:

1) Convertissez le format d'image en png: convert input.jpg input.png

2) convert input.png -fuzz 2% -transparent white output.png

Sandeep Pal
la source
6
C'est bien d'avoir un bord plus lisse entre le fond transparent et le premier plan opaque. Si vous convertissez des icônes bruyantes de JPG en PNG et que vous souhaitez ajouter de la transparence, vous pouvez également ajouter un filtrage médian:mogrify -format png -median 2 -fuzz 5% -transparent white ico_*.jpg
Tomasz Gandor
44

Solution

color=$( convert filename.png -format "%[pixel:p{0,0}]" info:- )
convert filename.png -alpha off -bordercolor $color -border 1 \
    \( +clone -fuzz 30% -fill none -floodfill +0+0 $color \
       -alpha extract -geometry 200% -blur 0x0.5 \
       -morphology erode square:1 -geometry 50% \) \
    -compose CopyOpacity -composite -shave 1 outputfilename.png

Explication

C'est plutôt un peu plus long que les réponses simples données précédemment, mais cela donne de bien meilleurs résultats: (1) La qualité est supérieure en raison de l'alpha antialiasé, et (2) seul l'arrière-plan est supprimé par opposition à une seule couleur. ("Arrière-plan" est défini comme approximativement de la même couleur que le pixel supérieur gauche, en utilisant un remplissage à partir des bords de l'image.)

De plus, le canal alpha est également érodé d'un demi-pixel pour éviter les halos. Bien sûr, les opérations morphologiques d'ImageMagick ne fonctionnent pas (encore?) Au niveau des sous-pixels, vous pouvez donc voir que je fais exploser le canal alpha à 200% avant de s'éroder.

Comparaison des résultats

Voici une comparaison de l'approche simple ("-fuzz 2% -transparent white") par rapport à ma solution, lorsqu'elle est exécutée sur le logo ImageMagick . J'ai aplati les deux images transparentes sur un fond marron pour rendre les différences apparentes (cliquez pour les originaux).

Le simple remplacement du blanc par transparent ne fonctionne pas toujours Le canal alpha et le remplissage anti-crénelage semblent beaucoup mieux

Remarquez comment la barbe du sorcier a disparu dans l'approche simple. Comparez les bords de l'assistant pour voir comment l'alpha anti-crénelé aide la figure à se fondre en douceur dans l'arrière-plan.

Bien sûr, j'admets complètement qu'il y a des moments où vous voudrez peut-être utiliser la solution la plus simple. (Par exemple: c'est beaucoup plus facile à retenir et si vous convertissez en GIF, vous êtes de toute façon limité à l'alpha 1 bit.)

script shell mktrans

Comme il est peu probable que vous souhaitiez taper cette commande à plusieurs reprises, je vous recommande de l'encapsuler dans un script. Vous pouvez télécharger un script shell BASH à partir de github qui exécute ma solution suggérée. Il peut être exécuté sur plusieurs fichiers dans un répertoire et comprend des commentaires utiles au cas où vous souhaiteriez modifier les choses.

script bg_removal

À propos, ImageMagick est en fait livré avec un script appelé "bg_removal" qui utilise floodfill de la même manière que ma solution. Cependant, les résultats ne sont pas excellents car il utilise toujours l'alpha 1 bit. De plus, le script bg_removal s'exécute plus lentement et est un peu plus délicat à utiliser (il vous oblige à spécifier deux valeurs de fuzz différentes). Voici un exemple de la sortie de bg_removal.

Le script bg_removal: a une barbe, mais manque d'anticrénelage

hackerb9
la source
2
J'avais besoin de modifier le fuzz à 2%, car l'image contient une machine blanche avec un fond blanc. Et bien que ce ne soit pas parfait à 100%, c'est la meilleure solution que j'ai trouvée car je ne veux pas le faire manuellement gimpou quoi que ce soit. :)
tukusejssirs
1
Solution géniale !
0x01h
29

Cela fonctionne pour moi:

convert original.png -fuzz 10% -transparent white transparent.png

où plus le% de fuzz est petit, plus le blanc est proche ou inversement, plus le% est grand, plus la variation du blanc est autorisée à devenir transparente

Ricibald
la source
1
Hou la la! C'est exactement ce dont j'avais besoin! avant: i.imgur.com/2Rd7w1N.png , après: i.imgur.com/4RTYygo.png
Dorian
Cela ne fonctionne pas parfaitement car il est incapable de gérer les images avec une couleur blanche et un fond blanc. comme des photos d'atout.
Sr. PHP Programmer Team Lead
Pour le blanc sur blanc, essayez d'utiliser la solution de remplissage d'inondation que j'ai publiée ci-dessus . Ou utilisez mon mktransscript shell: github.com/hackerb9/mktrans
hackerb9
12

Vous pouvez l'utiliser pour rendre l'arrière-plan transparent

convert test.png -background rgba(0,0,0,0) test1.png

Ce qui précède donne le fond transparent du préfet

Sanat Kumar Panda
la source
4
Le shell pourrait nécessiter quelques citations de (): convert more-icon.png -gravity center -background 'rgba(0,0,0,0)' -extent 27x27 new-more-icon.png
Jim K.
7

En utilisant ImageMagick, c'est très similaire au code et au résultat de hackerb9, mais c'est une ligne de commande un peu plus simple. Il suppose que le pixel supérieur gauche est la couleur d'arrière-plan. Je remplis juste l'arrière-plan de transparence, puis je sélectionne le canal alpha et je le floue et je supprime la moitié de la zone floue en utilisant -level 50x100%. Ensuite, rallumez tous les canaux et aplatissez-le contre la couleur brune. Le -blur 0x1 -level 50x100% agit pour anticréneler les limites de la transparence du canal alpha. Vous pouvez régler la valeur de fuzz, la quantité de flou et la valeur de -niveau 50% pour modifier le degré d'anticrénelage.

convert logo: -fuzz 25% -fill none -draw "matte 0,0 floodfill" -channel alpha -blur 0x1 -level 50x100% +channel -background saddlebrown -flatten result.jpg

entrez la description de l'image ici

fmw42
la source
Agréable. J'aime que vous en compreniez l'essentiel dans une ligne succincte. Ceci est similaire à l'une de mes étapes intermédiaires pendant que j'écrivais le script. J'ai décidé de ne pas le faire parce que (a) il perd trop de détails nets, (b) je voulais rendre la sélection de couleur évidente afin qu'elle puisse être facilement changée, et (c) je voulais remplir de tous les bords, pas seulement du haut - coin gauche. (Il y a peut-être d'autres choses que j'oublie en ce moment).
hackerb9
2
PS Je vais supposer que "fmw" signifie Fred M. Weinhaus. Dans l'affirmative, salutations, Dr Weinhaus! À quiconque ne sait pas qui il est, il a écrit certaines des recherches fondamentales en infographie à partir des années 1970. Tout le monde devrait consulter son incroyable conucopia de scripts shell ImageMagick sur fmwconcepts.com/imagemagick .
hackerb9
1
@ hackerb9: Oui, c'est moi. Est-ce qu'on se connaît? Envoyez-moi un e-mail si vous le souhaitez. Mon adresse e-mail se trouve sur la page Web que vous avez liée.
fmw42
4

Si vous souhaitez contrôler le niveau de transparence, vous pouvez utiliser rgba. où a est l'alpha. 0 pour transparent et 1 pour opaque. Assurez-vous que le fichier de sortie final doit avoir l'extension .png pour la transparence.

convert 
  test.png 
    -channel rgba 
    -matte 
    -fuzz 40% 
    -fill "rgba(255,255,255,0.5)" 
    -opaque "rgb(255,255,255)" 
       semi_transparent.png
Gokul NK
la source
1

Oui. Eu ce même problème aussi. Voici la commande que j'ai exécutée et cela a parfaitement fonctionné: convert transparent-img1.png transparent-img2.png transparent-img3.png -channel Alpha favicon.ico

stacigh
la source