I would like to add barely visible tracking dots in the style of these micro tracking dots to my b/w document. The tracking dots mentioned in the above look like this:

tracking dots as per (c) EFF, OP link see above

The tracking dots are aligned in a 15x8 matrix and, in the above case, include printer information, infos about the time the document was printed etc. I specifically do not want to copy the mechanism of encoding timestamps, but rather uniquely be able to identify printed pages (and, as you might have guessed, copies thereof).

I assure you to use this wisely, rarely and make ample notice of using the mechanism on my document.

If anyone has a more pratical, but still rather invisible, way of adding this type of tracking to a document I'd be quite happy to hear from you. Sadly, just adding a watermark in the background (also thanks to the good people of stackexchange ;) has not solved the issue of tracking single documents for me.

  • 2
    Here is the best one I have ever come across where the watermark is not visible: Martin Scharrer's answer at How to add an invisible watermark to pdf documents? where he hides the watermark within a period. But this does have the downside that if printed, that this watermark is pretty much lost -- but works great on electronic copies. – Peter Grill Oct 2 '12 at 7:31
  • 1
    Great addition - thanks! I will surely add this to my LaTeX "arsenal" - but in this oarticular cae I'd like to track printed documents, and, sadly, neither my printer nor everyone else's copier has a resolution high enough for this ;) – Christian Oct 2 '12 at 8:09
  • Just out of curiosity: do you want a single identifier per document, or a unique identifier per page? Is there a fixed page layout for the document (rules, header, page numbering etc)? If a single identifier per document, must it appear on each page? If it must appear on each page, should it always be in the same location? – Scott H. Oct 4 '12 at 4:51
  • @ScottH. I'd like this per-document, but if it is easier (ie if it can be derived from some metadata) then a per-page identifier would be perfectly fine as long as I have some control over it or as long as it is fairly unique. – Christian Oct 5 '12 at 9:48

Here are a couple of options:

Method 1: Dot Grid, encoded "christian"

enter image description here

\setgrid[opt arg][opt arg]{letters}


The first optional argument sets the size of a grid cell, default is 10 pt (units aren't entered). The second optional argument determines dot size. The dots are periods scaled via. \scalebox the second argument gives the scale factor, default is 0.3. Each letter in the given word is converted first to a position in the alphabet (a=1 etc.) and then that alphabetic position is converted to a 5 digit binary number. Each such binary numbers is set as a column of vertical dots: 0 = no dot, 1 = dot. Columns are read from top to bottom (the first column is always filled with dots for reference). Thus, in the picture above:

c->3rd letter->00011-> no dot, no dot, no dot, dot, dot.

The \usegrid macro then sets the grid. In the example I put it in the left header. You can put it wherever.


\prop_new:N \g__docmark_alph_num_prop
\seq_new:N \l__docmark_name_bin_seq
\tl_new:N \l__docmark_box_list_tl
\box_new:N \c__dot_box
\box_new:N \c__grid_box

% key = val: key -> letter, val -> binary rep of letter pos in alphabet
\int_step_inline:nnnn {1}{1}{26}
        \tl_set:Nx \l_tmpa_tl {\int_to_binary:n {#1}}
        \int_while_do:nn {\tl_count:N \l_tmpa_tl < 5}
                \tl_put_left:Nn \l_tmpa_tl 0
        \tl_set:Nx \l_tmpb_tl {\int_to_alph:n {#1}}
        \prop_put:NVV \g__docmark_alph_num_prop \l_tmpb_tl \l_tmpa_tl

\NewDocumentCommand{\setgrid}{ O{10} O{.5} m }
        \docmark_name_to_grid:nnn {#1}{#2}{#3}

\cs_generate_variant:Nn \hbox_gset:Nn {NV}
\cs_new:Npn \docmark_name_to_grid:nnn #1#2#3
        % scaled period, aka dot
        \hbox_gset:Nn \c__dot_box {\hbox_to_zero:n {\scalebox{#2}{.}}}

        % map letters of mandatory arg to 5 digit binaries
        \tl_map_inline:nn {#3}
                \seq_put_right:Nx \l__docmark_name_bin_seq {\prop_get:Nn \g__docmark_alph_num_prop {##1}}

        % "bookend" for reference
        \seq_put_left:Nn \l__docmark_name_bin_seq {11111}

        % for each 5 digit binary rep
        \seq_map_variable:NNn \l__docmark_name_bin_seq \l_tmpa_tl
                \int_step_inline:nnnn {1}{1}{5}
                        % for each of the 5 digits in the rep
                        \tl_set:Nx \l_tmpb_tl {\tl_item:Nn \l_tmpa_tl {##1}}

                        % if zero, no dot
                        \tl_if_in:NnF \l_tmpb_tl {0}
                                % if not zero then dot, left/right in list --> up/down in dots
                                \fp_set:Nn \l_tmpa_fp {-(##1-1)*(\tl_item:Nn \l_tmpa_tl {##1})*(#1)}
                                \tl_put_right:Nx \l__docmark_box_list_tl {\box_move_up:nn {\fp_to_dim:N \l_tmpa_fp}{\box_use:N \c__dot_box}}

                % move to next column of dots
                \tl_put_right:Nn \l__docmark_box_list_tl {\hspace{#1pt}}
        % box the dots
        \hbox_gset:NV \c__grid_box \l__docmark_box_list_tl

        \box_use:N \c__grid_box




Hi! I am a lovely sentence.


Method 2: Dots in text, encoded "abba"

enter image description here

This one gives:


The first argument again sets dot size, and the second is letters. The letters a1,...,aj are converted to integers n1..nj as above. In the ith line of text a dot will be placed beneath the nith glyph. The letters can be recovered by counting glyphs (letters, punctuation, etc) from the left until you reach a dot, and then using the corresponding letter of the alphabet. This will occur on every page. Compile with lualatex. Code borrowed liberally from here: https://tex.stackexchange.com/a/58327/14100

local GLYPH_ID = node.id("glyph")

-- adapted from https://tex.stackexchange.com/a/58327/14100
local number_sp_in_a_pdf_point = 65782

function math.round(num)
    return math.floor(num * 1000 + 0.5) / 1000

-- char width, whatsit, char pos, line number
local wd,w,pos,line

-- head is a linked list (next/prev entries pointing to the next node)
function mark_chars(head)
    while head do
      if head.id == 0 then
        -- an hbox
            pos = 0
            line = line + 1
      elseif head.id == GLYPH_ID then
            pos = pos + 1
            if pos == t[line] then
            -- if (character position) = (number of current character in name) 
        w = node.new("whatsit","pdf_literal")
        wd = math.round(head.width  / number_sp_in_a_pdf_point)
                -- cf. http://www.tug.org/TUGboat/tb32-2/tb101isambert.pdf
        w.data = string.format("q 0.2 G %g w %g -2.8 m %g %g l s Q",p,-wd/2,-wd/2,-2.8+p)
        -- insert this new node after the current glyph and move pointer (head) to
        -- the new whatsit node
        w.next = head.next
        w.prev = head
        head.next = w
        head = w
      end -- if
      head = head.next
  end -- while
  return true
end -- function

char_tab = {a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9, j=10, k=11, l=12, m=13, n=14, o=15, p=16, q=17, r=18, s=19, t=20, u=21, v=22, w=23, x=24, y=25, z=26}

t = {}
function encode(name)
    -- step through name
    for i = 1, #name do
            -- read each char
        local s = string.sub(name, i, i)
            -- store its numeric equiv in table

function mark_page(head)
    line = 0
    return head
    \directlua{luatexbase.add_to_callback('pre_output_filter', mark_page, "mark_page")}%
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer tincidunt condimentum quam, quis dignissim felis adipiscing rhoncus. Mauris quis imperdiet ligula. Maecenas quis dolor vel nunc egestas consectetur. Donec porttitor dictum tincidunt. Nunc orci ipsum, mattis vitae lobortis ut, porta eget mi. Quisque adipiscing, lacus quis molestie fermentum, nunc odio consectetur arcu, nec luctus dolor nisi quis erat. Aliquam sit amet venenatis est. Sed ut venenatis elit. Maecenas lacus leo, aliquam nec fringilla eu, lobortis quis augue.

Mauris vestibulum, augue non convallis vestibulum, ante enim aliquam eros, sit amet sollicitudin sapien ante ac diam. Quisque mi purus, vehicula eu feugiat a, blandit facilisis est. Etiam sit amet dui eget purus ultricies volutpat. Integer eu enim leo, eu faucibus neque. Donec ut sollicitudin nunc. Etiam tincidunt justo eu ante consectetur consequat. Suspendisse ultricies faucibus odio. Donec felis risus, lobortis eu pellentesque quis, imperdiet non augue. Sed massa dolor, ultrices at ultricies in, dapibus a ante. Sed sit amet augue felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

  • Not only is solution one perfect, solution two is the most sneaky solution one could have come up with to mark certain pages. Invisible, yet easily parseable by even the untrained eye. You are the God of LaTeX. And my personal hero of the week (if not month). Again, Thank You! – Christian Nov 15 '12 at 13:34
  • Sorry for the potentially stupid question, but does this also work with beamer? Will it print there the watermark on every slide/frame? Or do I need to do something special to bring it on every slide? – bonanza Nov 19 '18 at 7:46

This seems to me to be similar to a QR code. You could then set the size and contrast to be as visible as you want. Obviously the more visible the better it is going to print and reproduce.

  • I was contemplating about using some sort of barcode, but in the end I decided against using something "easily decodable". Also, I would like this to be as "light", ie. as invisible as possible and QR-Codes are very visible, down to the point where the eye still sees it but no camera/software can still decode it, sadly. Being a ham radio operator I'd wish for something like WSJT on print ;) – Christian Oct 4 '12 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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