Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Can you create images like this:

enter image description here

when you have something like

0 = green (#54ff00)
1 = white (#ffffff)
2 = red   (#ff0000)
3 = blue  (#0048ff)

Image (Python list of integers defined above):
[[2,0,0,0,0,0,0],
 [0,3,0,0,0,0,0],
 [0,3,2,1,1,0,0],
 [0,3,2,2,2,1,1],
 [0,3,2,0,0,1,0],
 [0,0,0,0,0,1,0],
 [0,0,0,0,0,1,0]]

with TikZ?

How far I got

The following MWE defines all colors, produces a grid of the correct size (though the size is determined by hand):

\documentclass[varwidth=true, border=2pt]{standalone}
\usepackage{tikz}
\usepackage{xcolor}

\begin{document}
    \newcommand\n{7}
    \definecolor{green}{HTML}{54FF00}
    \definecolor{wite}{HTML}{FFFFFF}
    \definecolor{red}{HTML}{FF0000}
    \definecolor{blue}{HTML}{0048FF}
    \begin{tikzpicture}
        \foreach \x in {1,...,\n}{
            \foreach \y in {1,...,\n}{
                \begin{scope}[shift={(\x,\y)}]
                  \draw [fill=green] (0,0) rectangle (1,1);
                \end{scope}
            }
        }
    \end{tikzpicture}
\end{document}

Of course, I could simpy make a lot of adjusted

                \begin{scope}[shift={(\x,\y)}]
                  \draw [fill=green] (0,0) rectangle (1,1);
                \end{scope}

but I've wondered if this can (with reasonable effort) be done in TikZ / LaTeX.

My problem is giving TikZ the color array. I don't have any idea how to do this. I only know two types of looks in TikZ:

\foreach \x in {0,1,2,3,4,5}{...}
\foreach \number in {1,...,\n}{...}

I have never seen a nested over a 2D-array. All I have seen so far were 1D-Arrays of tuples (with fixed tuple size).

share|improve this question
add comment

6 Answers

up vote 12 down vote accepted

Here is a completely different approach from my other answer, and this one takes as its input, a form similar to that mentioned by the OP, namely:

\def\map{
[[2,0,0,0,0,0,0]
 [0,3,0,0,0,0,0]
 [0,3,2,1,1,0,0]
 [0,3,2,2,2,1,1]
 [0,3,2,0,0,1,0]
 [0,0,0,0,0,1,0]
 [0,0,0,0,0,1,0]]
}

In this case, this argument is passed to the macro \boxart. The box size is set with \setlength{\boxsize}{}.

EDIT: The OP has asked for a clarification on the code internals of \boxart. In this routine, I use some macros from the stringstrings package to strip out left brackets, turn commas into spaces, and turn right brackets into " . " strings. The result is a space-separated string (\thestring), that will look like

2 0 0 0 0 0 0 . 0 3 0     etc.

The \getargsC macro from readarray knows how to efficiently read space-delimited strings and is fed this string. The number of arguments in the string is stored in \narg and each argument is stored individually in \argi, \argii, \argiii, etc. Once that is done, a loop is set up (to go through \narg iterations, once for each item in \thestring), and each argument is checked. If it is a 0, a \gr is issued for a green block, and so on for 1, 2, and 3. If a . is found, a \par (paragraph) is issued. This while loop is performed inside a \parbox, so that the local line spacing can be set and the result doesn't have to start in the left column of the document (I should point out that the \parbox width was set arbitrarily by me, and may need to be manually tweaked by the user).

For the OP's edification, an \edef is an assignment where the contents of the argument are fully expanded before being assigned. Thus, what is found in \clr are the individual items from \thestring successively stored in the \arg... variables: \argi is 2, \argii is 0, ..., \argviii is ., etc.

\documentclass{article}
\usepackage{xcolor}
\usepackage{stringstrings}
\usepackage{readarray}
\newlength\boxsize
\setlength\boxsize{1ex}
\def\block#1{\fboxsep=0pt\fbox{\color{#1}\rule{\boxsize}{\boxsize}}\kern-\fboxrule}
\def\gr{\block{green}}
\def\rd{\block{red}}
\def\bl{\block{blue}}
\def\wh{\block{white}}
\newcounter{index}%
\newcommand\boxart[1]{%
  \setcounter{index}{0}%
  \convertchar[q]{#1}{,}{ }%
  \convertchar[q]{\thestring}{[}{}%
  \convertchar[q]{\thestring}{]}{ . }%
  \getargsC{\thestring}%
  \parbox[b]{8ex}{%
    \baselineskip\boxsize%
    \parindent 0ex%
    \parskip -.2\boxsize%
    \addtolength{\parskip}{-2\fboxrule}%
    \whiledo{%
      \theindex < \narg}{%
      \stepcounter{index}%
      \edef\clr{\csname arg\romannumeral\theindex\endcsname}%
      \expandafter\if\clr0\gr\fi%
      \expandafter\if\clr1\wh\fi%
      \expandafter\if\clr2\rd\fi%
      \expandafter\if\clr3\bl\fi%
     \expandafter\if\clr.\par\fi%
    }%
  }%
}
\begin{document}
%0 = green (#54ff00)
%1 = white (#ffffff)
%2 = red   (#ff0000)
%3 = blue  (#0048ff)
\def\map{
[[2,0,0,0,0,0,0]
 [0,3,0,0,0,0,0]
 [0,3,2,1,1,0,0]
 [0,3,2,2,2,1,1]
 [0,3,2,0,0,1,0]
 [0,0,0,0,0,1,0]
 [0,0,0,0,0,1,0]]
}
Here it is: \boxart{\map}

\def\map{
[[2,0,0,0,0]
 [0,3,0,0,0]
 [0,3,2,0,0]
 [0,3,2,1,1]
 [0,3,0,1,0]]
}
\setlength{\boxsize}{1.2ex}
Another: \boxart{\map}
\end{document} 

enter image description here

share|improve this answer
add comment

A matrix of nodes could be an option:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}

\tikzset{ 
table/.style={
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={rectangle,draw=black,minimum size=1cm,align=center},
  nodes in empty cells
  }
}

\definecolor{0}{HTML}{54FF00}
\definecolor{1}{HTML}{FFFFFF}
\definecolor{2}{HTML}{FF0000}
\definecolor{3}{HTML}{0048FF}

\begin{tikzpicture}

\matrix (mat) [table]
{
|[fill=2]| & |[fill=0]|  & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| \\
|[fill=0]| & |[fill=3]|  & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| \\
|[fill=0]| & |[fill=3]|  & |[fill=2]| & |[fill=1]| & |[fill=1]| & |[fill=0]| & |[fill=0]| \\
|[fill=0]| & |[fill=3]|  & |[fill=2]| & |[fill=2]| & |[fill=2]| & |[fill=1]| & |[fill=1]| \\
|[fill=0]| & |[fill=3]|  & |[fill=2]| & |[fill=0]| & |[fill=0]| & |[fill=1]| & |[fill=0]| \\
|[fill=0]| & |[fill=0]|  & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| \\
|[fill=0]| & |[fill=0]|  & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| & |[fill=0]| \\
};
\end{tikzpicture}

\end{document}

Or, even shorter, selecting the dominant color as default:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}

\definecolor{0}{HTML}{54FF00}
\definecolor{1}{HTML}{FFFFFF}
\definecolor{2}{HTML}{FF0000}
\definecolor{3}{HTML}{0048FF}

\tikzset{ 
table/.style={
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={rectangle,draw=black,fill=0,minimum size=1cm,align=center},
  nodes in empty cells
  }
}

\begin{tikzpicture}

\matrix (mat) [table]
{
|[fill=2]| &   &  &  &  &  &  \\
 & |[fill=3]|  &  &  &  &  &  \\
 & |[fill=3]|  & |[fill=2]| & |[fill=1]| & |[fill=1]| &  &  \\
 & |[fill=3]|  & |[fill=2]| & |[fill=2]| & |[fill=2]| & |[fill=1]| & |[fill=1]| \\
 & |[fill=3]|  & |[fill=2]| &  &  & |[fill=1]| &  \\
 &   &  &  &  &  &  \\
 &   &  &  &  &  &  \\
};
\end{tikzpicture}

\end{document}

enter image description here

And with a slight (though a little slow) help from pgfplotstable

\documentclass[border=3pt]{standalone}
\usepackage{pgfplotstable}

\pgfplotstableread[col sep=comma]{%
2,0,0,0,0,0,0
0,3,0,0,0,0,0
0,3,2,1,1,0,0
0,3,2,2,2,1,1
0,3,2,0,0,1,0
0,0,0,0,0,1,0
0,0,0,0,0,1,0
}\mycolortable
\newcommand\n{7}
\definecolor{c0}{HTML}{54FF00}
\definecolor{c1}{HTML}{FFFFFF}
\definecolor{c2}{HTML}{FF0000}
\definecolor{c3}{HTML}{0048FF}


\begin{document}
\begin{tikzpicture}
    \foreach \x[count=\xi from 0] in {1,...,\n}{
        \foreach \y[count=\yi from 0] in {1,...,\n}{
            \begin{scope}[shift={(\x,-\y)}]
            \pgfplotstablegetelem{\yi}{\xi}\of{\mycolortable}
            \draw[ultra thick,fill=c\pgfplotsretval] (0,0) rectangle (1,1);
            \end{scope}
        }
    }
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
I've added a similar example, Gonzalo. I couldn't resist :) –  percusse Feb 2 at 0:09
1  
@percusse by all means! Great addition. –  Gonzalo Medina Feb 2 at 0:16
    
for the pgfplotstable-part: Can you get the size of the table automatically? By the way, it does not have to be a square. –  moose Feb 3 at 6:28
    
@moose All three options will allow arbitrary rectangular shapes: in the first two, simply fill the matrix of nodes with as many rows and columns as required; in the third one (pgfplotstable), define \m to control the rows and use \m and \n on the nested cycles. Regarding the question about the size of the table, I am not sure what you are asking. Could you please elaborate? –  Gonzalo Medina Feb 3 at 13:26
    
Ok, I try to make clear what I mean: I think it should not be necessary to define \n (or \m) excplicitly. These parameters are implicitly given by the information within pgfplotstableread (for example: 2,0,0,0,0,0,0\n2,0,0,0,0,0,0 is \m=2 and \n=7). –  moose Feb 3 at 13:35
add comment

Here is a very simple solution using TikZ:

\documentclass[tikz]{standalone}
\def\pixels{
  {2,0,0,0,0,0,0},
  {0,3,0,0,0,0,0},
  {0,3,2,1,1,0,0},
  {0,3,2,2,2,1,1},
  {0,3,2,0,0,1,0},
  {0,0,0,0,0,1,0},
  {0,0,0,0,0,1,0}%
}
\definecolor{pixel 0}{HTML}{54FF00}
\definecolor{pixel 1}{HTML}{FFFFFF}
\definecolor{pixel 2}{HTML}{FF0000}
\definecolor{pixel 3}{HTML}{0048FF}
\begin{document}
\begin{tikzpicture}
  \foreach \line [count=\y] in \pixels {
    \foreach \pix [count=\x] in \line {
      \draw[fill=pixel \pix] (\x,-\y) rectangle +(1,1);
    }
  }
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
+1 for simplicity (finally an answer I understand completely and that might help me to create other stuff :-) ) –  moose Feb 2 at 17:30
    
The better solution ! bravo !! –  Alain Matthes Feb 3 at 9:34
add comment

Make a stack (without tikz):

\documentclass{article}
\usepackage{xcolor}
\usepackage{stackengine}
\def\block#1{\kern-\fboxrule\fboxsep=0pt\fbox{\color{#1}\rule{1ex}{1ex}}}
\def\gr{\block{green}}
\def\rd{\block{red}}
\def\bl{\block{blue}}
\def\wh{\block{white}}
\setstackgap{S}{-\fboxrule}
\begin{document}
\Shortstack{
\rd\gr\gr\gr\gr\gr\gr\\
\gr\bl\gr\gr\gr\gr\gr\\
\gr\bl\rd\wh\wh\gr\gr\\
\gr\bl\rd\rd\rd\wh\wh\\
\gr\bl\rd\gr\gr\wh\gr\\
\gr\gr\gr\gr\gr\wh\gr\\
\gr\gr\gr\gr\gr\wh\gr
}
\end{document} 

enter image description here

share|improve this answer
add comment

A solution with PSTricks, just for fun!

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pgfmath} % it must be explicitly loaded!

\def\pixels{
  {2,0,0,0,0,0,0},
  {0,3,0,0,0,0,0},
  {0,3,2,1,1,0,0},
  {0,3,2,2,2,1,1},
  {0,3,2,0,0,1,0},
  {0,0,0,0,0,1,0},
  {0,0,0,0,0,1,0}%
}
\definecolor{pixel 0}{HTML}{54FF00}
\definecolor{pixel 1}{HTML}{FFFFFF}
\definecolor{pixel 2}{HTML}{FF0000}
\definecolor{pixel 3}{HTML}{0048FF}

\begin{document}
\begin{pspicture}[fillstyle=solid,dimen=monkey](7,-7)
    \foreach \line [count=\y from 0] in \pixels 
    {
        \foreach \pix [count=\x from 0] in \line 
        {
            \rput(\x,-\y){\psframe[fillcolor=pixel \pix](1,-1)}
        }
    }
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
2  
I really got surprised to know that color names can contain spaces. –  I am who I say I am Feb 2 at 10:08
    
dimen key provides 3 options with primate names: indri for inner, monkey for middle, and orangutan for outer. –  I am who I say I am Feb 2 at 10:18
add comment

If you don't care about the black lines, you can use a simple \rule to mimic a pixel and then use the picture environment. I guess it's not exactly what you had in mind but just in case, here you go:

 \documentclass{minimal}

 %Pixel macro and its dimension
 \newcommand{\dimension}{10pt}
 \newcommand{\pixel}[2]{\textcolor{#1}{\rule{#2}{#2}}}


 %Colors
 \usepackage{xcolor}
 \definecolor{couleura}{RGB}{255, 0, 0}
 \definecolor{couleurb}{RGB}{84, 255, 0}
 \definecolor{couleurc}{RGB}{0, 72, 255}
 \definecolor{couleurd}{RGB}{255, 255, 255}

 %Colored pixels
 \newcommand{\pixela}{\pixel{couleura}{\dimension}}
 \newcommand{\pixelb}{\pixel{couleurb}{\dimension}}
 \newcommand{\pixelc}{\pixel{couleurc}{\dimension}}
 \newcommand{\pixeld}{\pixel{couleurd}{\dimension}}

 \begin{document}

 \setlength{\unitlength}{\dimension}%
 \begin{picture}(7,7)%
     \put (0,7) {\pixela}%
     \put (1,7) {\pixelb}%
     \put (2,7) {\pixelb}%
     \put (3,7) {\pixelb}%
     \put (4,7) {\pixelb}%
     \put (5,7) {\pixelb}%
     \put (6,7) {\pixelb}%
     \put (0,6) {\pixelb}%
     \put (1,6) {\pixelc}%
     \put (2,6) {\pixelb}%
     \put (3,6) {\pixelb}%
     \put (4,6) {\pixelb}%
     \put (5,6) {\pixelb}%
     \put (6,6) {\pixelb}%
     \put (0,5) {\pixelb}%
     \put (1,5) {\pixelc}%
     \put (2,5) {\pixela}%
     \put (3,5) {\pixeld}%
     \put (4,5) {\pixeld}%
     \put (5,5) {\pixelb}%
     \put (6,5) {\pixelb}%
     \put (0,4) {\pixelb}%
     \put (1,4) {\pixelc}%
     \put (2,4) {\pixela}%
     \put (3,4) {\pixela}%
     \put (4,4) {\pixela}%
     \put (5,4) {\pixeld}%
     \put (6,4) {\pixeld}%
     \put (0,3) {\pixelb}%
     \put (1,3) {\pixelc}%
     \put (2,3) {\pixela}%
     \put (3,3) {\pixelb}%
     \put (4,3) {\pixelb}%
     \put (5,3) {\pixeld}%
     \put (6,3) {\pixelb}%
     \put (0,2) {\pixelb}%
     \put (1,2) {\pixelb}%
     \put (2,2) {\pixelb}%
     \put (3,2) {\pixelb}%
     \put (4,2) {\pixelb}%
     \put (5,2) {\pixelb}%
     \put (6,2) {\pixelb}%
     \put (0,1) {\pixelb}%
     \put (1,1) {\pixelb}%
     \put (2,1) {\pixelb}%
     \put (3,1) {\pixelb}%
     \put (4,1) {\pixelb}%
     \put (5,1) {\pixelb}%
     \put (6,1) {\pixelb}%
  \end{picture}

 \end{document}

The result:

Big drawback : the code is very long ! But on the other hand, it's pretty fast. And, if you're lazy, I wrote a python script a little while ago to generate the tex code from a png file (the png needs to have an alpha layer). You can check it out here:

http://alexisfles.ch/en/latex/pixelart.html

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.