如何在 TikZ 影像中使用大量任意 RGB 顏色?

如何在 TikZ 影像中使用大量任意 RGB 顏色?

我有一個包含一些 TikZ 圖像的文檔,這些圖像是從我編寫的程式自動生成的。所有影像都非常相似,並且每個影像都包含大量具有不同的任意 RGB 顏色的方塊。我的問題是:為這麼多的方塊著色的最佳方法是什麼?

到目前為止,我使用的方法包括在繪製每個正方形之前fillcolor使用巨集定義顏色\definecolor,並使用該顏色填充正方形。這意味著每次我繪製一個新的正方形時,我都會fillcolor再次定義。

但是,我不太確定這是這樣做的方法。 pdflatex 在編譯文件時似乎需要大量內存,並且由於某些奇怪的原因,如果我包含超過5 個圖像,則會耗盡內存(即使當我從5 個圖像增加到6 個圖像時將內存量增加十倍) 。它是否有可能存儲我定義的所有顏色,並且我需要在再次fillcolor調用之前使 pdflatex “忘記” \definecolor

更新:以下是我在文件中想要的 TikZ 圖像之一的範例(它是使用有限體積法和流體體積法對兩相流體模擬中相分數場的可視化,是的,我知道,流體界面並不完全清晰):

TikZ 影像包含 1990 個不同顏色的方塊

此特定影像由 1990 個填充方塊和 4 個未填充方塊組成。

首先,對於每個正方形,fillcolor是用 定義的\definecolor,並且正方形用該顏色填充:

\definecolor{fillcolor}{rgb}{1.000000,0.241735,0.000000}
\fill[fillcolor] (0.203125,0.578125) rectangle (0.218750,0.593750);

然後繪製每個正方形的邊,例如

\draw (0.203125,0.578125) rectangle (0.218750,0.593750);

答案1

正如我在評論中所說, if \definecolor,只是將顏色定義儲存在 TeX 宏中,然後重新定義它將回收相同的宏,因此不會使用更多記憶體。

然而,也有可能\defincolor正在推送某種定義 PDF 引擎顏色的文字 PDF 程式碼。在這種情況下,據我所知,不應該使用更多的記憶體來多次重新定義相同的顏色。

不管怎樣,為了以防萬一,可以使用沒有先前定義的 RGB 顏色。方法如下。

  • 原則上,tikz識別形式的顏色規格{rgb:red,255;green,255;blue:255}。但它並沒有像人們所期望的那樣被解釋。例如,[fill={rgb:red,255;green,255;blue,0}]不會產生黃色,而是產生黑色的黃色(見下圖)。我找不到有關此規範如何運作的文件。顯然,將所有redgreenblue值相加,然後將每個特定值除以總數。也就是說,我們指定的不是絕對位元組值,而是相對權重。因此,要得到黃色,我們可以這樣寫:{rgb:red,1;green:1;blue:-1}。我發現這種語法相當不方便(而且,我們怎麼能得到“白色”?)

  • PGF 使用內部巨集:\pgfsys@color@rgb@fill它具有預期的行為。它接收rg和分量的三個數值b,即 0-255 值。所以我們可以在填滿指令之前使用這個巨集來設定填滿色。

這是顯示幾個選項的程式碼:

\documentclass{article}
\usepackage{tikz}

% Define a more convenient macro without @ in its name
\makeatletter
\def\fillRGB#1#2#3{\pgfsys@color@rgb@fill{#1}{#2}{#3}}
\makeatother
\begin{document}

% Standard xcolor defined color
\definecolor{RGByellow}{RGB}{255,255,0}

% Some examples
\tikz{\node[draw,fill=RGByellow]{defined colour};}

\tikz{\node[draw,fill={rgb:red,255;green,255;blue,0}]{Tikz rgb: 255,255,0};}

\tikz{\node[draw,fill={rgb:red,1;green,1;blue,-1}]{Tikz rgb: 1,1,-1};}

\tikz{\fillRGB{255}{255}{0}\node[fill,draw]{{\tt fillRGB: 255,255,0} };}

\end{document}

結果:

結果

答案2

我相信你的方法\definecolor很好。

我的建議是使用 PGF 基本層而不是 tikz,即使用類似的東西

\definecolor{fillcolor}{...}
\pgfsetfillcolor{fillcolor}
\pgfsetstrokecolor{fillcolor!80!black}
\pgfpathrectangle{...}{...}
\pgfusepathqfillstroke
% next one, no scope in-between...
\definecolor{fillcolor}{...}
\pgfsetfillcolor{fillcolor}
\pgfsetstrokecolor{fillcolor!80!black}
\pgfpathrectangle{...}{...}
\pgfusepathqfillstroke

請在 pgfmanual.pdf 中找到提到的命令,因為我可能拼錯了其中一些命令(我用心引用了)。

我的建議是結合描邊和填滿路徑並僅改變顏色可能對您有意義,也可以應用於 tikz 路徑。這也應該減少記憶體消耗和排版時間。

有一句話實際上超出了您的問題範圍:我對使用繪製顏色的建議fillcolor!80!black是受到預設值的啟發pgfplots,我發現與黑色輪廓相比,預設值不那麼刺眼。 pgfplots 具有與這裡相同的用例:您在這裡編寫的實際上是一種具有多面著色和顯式顏色輸入的網格/表面(在 pgfplots: 中\addplot3[surf],比較pgfplots:使用任意 RGB 顏色為 (3D) 衝浪著色)。

即使在記憶體減少之後,您仍然擁有「大量」資料點(就 TeX 應該處理的內容而言)。因此,即使減少記憶體也可能最終達到 TeX 的極限。如果一張圖像有效,但多張圖像失敗,您可能會從使用圖像外部化中受益。您還可以受益於使用動態記憶體分配lualatex而不是pdflatex動態lualatex記憶體分配。您還應該\clearpage在相鄰figure環境之間進行試驗,以確保 TeX 的記憶體中沒有舊數字(如 @JLDiaz 在評論中建議的那樣)。影像外部化和記憶體消耗的詳細資訊在「記憶體和速度注意事項」部分中進行了總結http://pgfplots.sourceforge.net/pgfplots.pdf

答案3

要在紅色和藍色(透過橙色、黃色、綠色和青色)之間製作平滑且簡單的陰影,您可以使用Hsb顏色模型(由xcolor套件提供):

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \foreach \x in {0,...,9}{
    \foreach \y in {0,...,9}{
      \pgfmathtruncatemacro{\myhue}{(\y*10+\x)*2.5}
      \definecolor{col}{rgb:Hsb}{\myhue,1,1}
      \draw[fill=col] (\x,\y) rectangle ++(1,1);
    }
  }
\end{tikzpicture}
\end{document}

或(使用另一種語法):

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \colorlet{redhsb}[hsb]{red}%
  \colorlet{bluehsb}[hsb]{blue}%
  \foreach \x in {0,...,9}{
    \foreach \y in {0,...,9}{
      \pgfmathtruncatemacro{\rat}{\y*10+\x}
      \colorlet{col}[rgb]{bluehsb!\rat!redhsb}
      \draw[fill=col] (\x,\y) rectangle ++(1,1);
    }
  }
\end{tikzpicture}
\end{document}

在此輸入影像描述

此方法可用於大量小方塊(此處為 100 x 100):

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \colorlet{redhsb}[hsb]{red}%
  \colorlet{bluehsb}[hsb]{blue}%
  \foreach \x in {0,...,100}{
    \foreach \y in {0,...,100}{
      \pgfmathtruncatemacro{\rat}{(cos(\x*4)+sin(\y*4))*25+50}
      \colorlet{col}[rgb]{bluehsb!\rat!redhsb}
      \draw[fill=col,line width=.1pt] (\x*.1,\y*.1) rectangle ++(.1,.1);
    }
  }
\end{tikzpicture}
\end{document}

在此輸入影像描述

相關內容