Breaking pictures across multiple pages

Unfortunately this doesn't work. Picture environments (picture, tikzpicture, ...) are (horizontal) boxes on their own and LaTeX doesn't break these. You would need to do this by yourself.

If you are able to detect it once your picture is too long (longer than max. \textheight or calculate the rest of the current page) you could insert some code like <global save settings>\end{picture}\begin{picture}<restore settings> to close the current picture and open a new one. I do similar things with TikZ's \path in tikz-timing where I have to start a new path to change the colour and style but want to keep certain settings and the position. It's, however, a little tricky, especially for whole pictures, I guess.

Another possibility would be to draw the whole picture as long it turns out to be, but inside a savebox, i.e. you store it first but don't typeset it directly. Then you can measure its height (\ht\yourboxmacro) and if it is too high you can clip it using my adjustbox package. The idea would be to insert it twice: once clipped to the size of the first page and then again on the next page with the first part clipped. Using a loop you could, of course, support more than two pages.

Here some example code. I used tikzpicture here because I know its syntax but not the one of picture very well. It will work with that as well of course. (Note that there is a bug in the current version of adjustbox. I fixed it for the example image below, but the top is still clipped incorrectly. I have to have a closer look at it. However, the basic idea is sound and works.)

\documentclass{article}

\usepackage{tikz}
\usepackage{adjustbox}

\newsavebox{\mysavebox}
\newlength{\myrest}
\begin{document}

\begin{lrbox}{\mysavebox}%
\begin{tikzpicture}[red,thick]
 \draw (0,0) rectangle (-.9\textwidth,-2.8\textheight);
 \draw (0,0) -- (-.9\textwidth,-2.8\textheight);
 \draw (-.9\textwidth,0) -- (0,-2.8\textheight);
 \path (-1mm,-1mm);
 \path (current bounding box.north east) +(1mm,1mm);
\end{tikzpicture}%
\end{lrbox}%
%
\ifdim\ht\mysavebox>\textheight
    \setlength{\myrest}{\ht\mysavebox}%
    \loop\ifdim\myrest>\textheight
        \newpage\par\noindent
        \clipbox{0 {\myrest-\textheight} 0 {\ht\mysavebox-\myrest}}{\usebox{\mysavebox}}%
        \addtolength{\myrest}{-\textheight}%
    \repeat
    \newpage\par\noindent
    \clipbox{0 0 0 {\ht\mysavebox-\myrest}}{\usebox{\mysavebox}}%
\else
    \usebox{\mysavebox}%
\fi

\end{document}

Result


I know this is a place for TeX, but I ran into the problem and wrote a bit of Python to solve it for me. It requires Python and PIL (the Python Imaging Library)

Say you have a really long picture like this, and you want to slice it up into smaller bits, because it is so long.

Picture

Here is a Python script that will do that.

from __future__ import division
import Image
import math
import os

def long_slice(image_path, out_name, outdir, slice_size):
    """slice an image into parts slice_size tall"""
    img = Image.open(image_path)
    width, height = img.size
    upper = 0
    left = 0
    slices = int(math.ceil(height/slice_size))

    count = 1
    for slice in range(slices):
        #if we are at the end, set the lower bound to be the bottom of the image
        if count == slices:
            lower = height
        else:
            lower = int(count * slice_size)  

        bbox = (left, upper, width, lower)
        working_slice = img.crop(bbox)
        upper += slice_size
        #save the slice
        working_slice.save(os.path.join(outdir, "slice_" + out_name + "_" + str(count)+".png"))
        count +=1

if __name__ == '__main__':

    long_slice("longcat.jpg", #image filename 
               "longcat", #slice names
                os.getcwd(), #output dir
                300 #height in px
               )

This is is the output

Picture


Picture


Picture


I really liked Martin Scharrer's answer (from July 12, 2011) and his example works. However, when I tried modifying Martin's answer to use for my purposes I found the code clipped \mysavebox in a strange way (Perhaps it was because I needed to use a minipage). It took me 2 months of experimenting and searching online to find the reason why. The total vertical length of \mysavebox includes not only the height, but also the depth (i.e., \ht\mysavebox + \dp\mysavebox). Now the clipping for each page works great. If you are finding similar difficulties, maybe the following solution will help you. I use the new variable I create, \mytotallen, like Martin uses \ht\mysavebox.

\documentclass{article}

\usepackage{tikz}
\usepackage{adjustbox}

\newsavebox{\mysavebox}
\newlength{\myrest}
\begin{document}

\begin{lrbox}{\mysavebox}
  \begin{minipage}{\textwidth}
    \begin{footnotesize} %change font size
      \begin{spacing}{0.5}
        Lots and lots and lots of text... (3 pages worth)
      \end{spacing}
    \end{footnotesize}
  \end{minipage}
\end{lrbox}

\newlength{\mytotallen} %create a new length variable \mytotallen
\setlength{\mytotallen}{\ht\mysavebox + \dp\mysavebox} %add together the height (\ht) and depth (\dp) of \mysavebox
\ifdim\mytotallen>\textheight
    \setlength{\myrest}{\mytotallen} %initialize \myrest
    \loop\ifdim\myrest>\textheight
        \newpage\par\noindent
        \clipbox{0 {\myrest-\textheight} 0 {\mytotallen-\myrest}}{\usebox{\mysavebox}}
        \addtolength{\myrest}{-\textheight}%subtract one page's length each loop from \myrest
    \repeat
    \newpage\par\noindent
    \clipbox{0 0 0 {\mytotallen-\myrest}}{\usebox{\mysavebox}}
\else
    \usebox{\mysavebox}
\fi
\end{document}