Como colorir um ícone em tons de cinza em um fundo não branco?

Como colorir um ícone em tons de cinza em um fundo não branco?

Eu tenho um ícone preto sobre transparente em um arquivo png. Quero usar este ícone em locais diferentes em um documento LaTeX em cores diferentes. Como bônus, seria bom se eu pudesse dar à metade superior do ícone uma cor diferente da metade inferior, porque às vezes ele aparece na borda de fundos diferentes.

Esta respostamostra como colorir um arquivo png em tons de cinza e é fácil dar à metade superior uma cor diferente da metade inferior. Infelizmente, é necessário que o logotipo esteja em um fundo branco:

\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
    \fill[yellow!50!white] (0,1) rectangle (2,2);
    \fill[gray!50!black]   (0,0) rectangle (2,1);

    \begin{scope}[blend group=screen]
        \node[inner sep=0,line width=0] (logo) at (1,1) [anchor=center] {\includegraphics{icon-bw}};
        \fill[blue] (logo.west) rectangle (logo.north east);
        \fill[green] (logo.south west) rectangle (logo.east);
    \end{scope}
\end{tikzpicture}
\end{document}

Adicionado um exemplo de ícone com fundo branco: ícone-bw.png

Se eu usar um png preto para transparente, todo o nó será pintado de azul e verde.

Um exemplo de ícone com fundo transparente: ícone.png

Esta respostamostra como usar um arquivo png como máscara de transparência. Mas como movo o ícone para que fique centralizado em (1,1)?

\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{fadings}

\begin{tikzfadingfrompicture}[name=icon]
    \begin{scope}[transparency group]
    \node (icon) [fill, draw, white] {\includegraphics[height=1cm]{icon}};
    \begin{scope}[blend mode=difference]
    \fill[white] (icon.south west) rectangle (icon.north east);
    \end{scope}
    \end{scope}
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}
    \fill[yellow!50!white] (0,1) rectangle (2,2);
    \fill[gray!50!black]   (0,0) rectangle (2,1);

    % How I intend to use it
    \begin{scope}[scope fading=icon, fit fading=false]
        \fill[blue] (0.5,1) rectangle (1.5,1.5);
        \fill[green] (0.5,0.5) rectangle (1.5,1);
    \end{scope}

    % Approach of the original answer. The icon is not positioned correctly.
    % The specified coordinate does not seem to make any difference.
    \path[scope fading=icon,fit fading=false] (1,1);
    \node[fill=yellow,minimum width=1cm,minimum height=1cm] {};
\end{tikzpicture}
\end{document}

No meu caso de uso real, o ícone consiste apenas em preto e transparência. Portanto, seria aceitável se uma resposta não funcionasse com tons de cinza intermediários.

Responder1

O padrão de esmaecimento será centralizado em (0,0) e a única maneira de movê-lo é mover o conteúdo do nó usando coisas como \hspacee \raisebox. Mover a implementação apenas usa o padrão naquele local (fora da borda). Como ele está centralizado, você deve movê-lo duas vezes mais longe do que ele realmente se move.

\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{fadings}

\begin{tikzfadingfrompicture}[name=icon,inner sep=0]
  \node [fill=transparent!0]
    {\hspace{2cm}\raisebox{2cm}{\includegraphics[height=2cm, width=2cm]{images/icon}}};
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}
  \fill[yellow!50!white] (0,1) rectangle (2,2);
  \fill[gray!50!black]   (0,0) rectangle (2,1);
  \begin{scope}[shift={(1,1)}]
    \path[scope fading=icon, fit fading=false];
    \node[bottom color=blue,top color=green,minimum width=2cm,minimum height=2cm]{};
  \end{scope}
\end{tikzpicture}
\end{document}

demonstração

Responder2

Esta resposta difere da de John Kormylo principalmente em dois pontos:

  • Estou usando fading transformonde estou aplicando o desvanecimento em vez de \hspacee \raiseboxna definição de desvanecimento. Observe também que estou usando path fadingem vez de scope fading. Não tenho certeza de quão grande é a diferença, mas não consegui fazê-lo funcionar com passagem scope fadinge fading transformcom um scopeambiente.
  • Estou invertendo as cores do arquivo png para que as partes pretas sejam preenchidas em vez das partes transparentes.
\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{fadings}

\newcommand\IconNodeContent{%
    \includegraphics[height=1cm]{icon}%
}

\begin{tikzfadingfrompicture}[name=icon]
    % I am using \fill[white] with blend mode=difference to invert the colors
    % so that I can use my black on transparent icon without needing to convert it to white on transparent/black.
    % This has the down side that the area around the icon node is not transparent but opaque.
    % I am increasing the transparent area a little with draw thick to avoid a visible rectangle around the icon when filling it later.
    \begin{scope}[transparency group]
    \node (icon) [fill, draw, thick, white] {\IconNodeContent};
    \begin{scope}[blend mode=difference]
    \fill[white] (icon.south west) rectangle (icon.north east);
    \end{scope}
    \end{scope}
\end{tikzfadingfrompicture}

\begin{document}
\begin{tikzpicture}
    % draw background
    \fill[yellow!50!white] (0,1) rectangle (2,2);
    \fill[gray!50!black]   (0,0) rectangle (2,1);

    % create an invisible node to define size and position of icon
    \node (icon) at (1,1) [anchor=center, transparent] {\IconNodeContent};
    % draw the top half of the icon in one color, shifting the coordinates 1pt inwards to make sure no border is visible
    \fill[blue,  path fading=icon, fit fading=false, fading transform={shift=(icon.center)}] ([shift={(1pt,-1pt)}] icon.north west) rectangle ([shift={(-1pt,+0pt)}] icon.east);
    % draw the bottom half of the icon in another color, shifting the coordinates 1pt inwards to make sure no border is visible
    \fill[green, path fading=icon, fit fading=false, fading transform={shift=(icon.center)}] ([shift={(1pt,+1pt)}] icon.south west) rectangle ([shift={(-1pt,-0pt)}] icon.east);
\end{tikzpicture}
\end{document}

saída

informação relacionada