14

I have a rectangular image that I can not change.

I'd like to clip the image with a Bézier path so I get one that is rectangular at the top and the sides but has a curve at the bottom, preferable without using additional packages.

5
  • 1
    No package needed if you clip the image using an image editor in advance. As far as I know, graphicx can only clip images in a rectangular form. Therefore you need additional packages such as PSTricks to clip it in a curved form. Jun 5, 2011 at 12:15
  • Using an editor in advance is not an option, unfortunatelly. Additional packages are acceptable (thou a solution without them would be preferable). Jun 5, 2011 at 12:17
  • Your image in what format? eps, jpeg, png, or pdf? Jun 5, 2011 at 12:24
  • can be converted during the compile-process. let us assume it is png. Jun 5, 2011 at 13:10
  • 1
    Herbert's solution that is compiled by xelatex can import png, pdf, jpg, eps. Jun 5, 2011 at 13:13

5 Answers 5

21

I don't know of a way to clip an image without using additional packages (apart from graphicx, I assume). There is a way of doing it with TikZ, which is probably better than no solution.

This is based on the answers to the question Drawing on an image with TikZ. I've written a macro that takes an image name with the accompanying \includegraphics options and a TikZ path as arguments to either display the image overlaid with a grid and the path, or to use the path to clip the image. The behaviour is toggled using \tikzset{develop clipping path=true} to switch on the grid and the path display, and \tikzset{develop clipping path=false} to perform the actual clipping once the path has been developed.

    \documentclass{article}

    \usepackage{tikz}
    \usepackage{graphicx}

    \newif\ifdeveloppath
    \tikzset{/tikz/develop clipping path/.is if=developpath,
      /tikz/develop clipping path=true}

    \newcommand{\clippicture}[2]{
      \begin{tikzpicture}
    % Include the image to determine the size and set up the relative coordinate system. Enclose the \includegraphics in \phantom{} once the clipping path has been set up
    \ifdeveloppath
      \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics#1};
    \else
      \node[anchor=south west,inner sep=0] (image) at (0,0) {\phantom{\includegraphics#1}};
    \fi
    \pgfresetboundingbox
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
      % Draw grid while developing clipping path
      \ifdeveloppath
        \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
        \foreach \x in {0,1,...,9} { \node [anchor=north] at (\x/10,0) {0.\x}; }
        \foreach \y in {0,1,...,9} { \node [anchor=east] at (0,\y/10) {0.\y}; }
        \draw[red, ultra thick] #2 -- cycle;
      \else
        % Use the path to clip, include the image
        \path[clip] #2 -- cycle;
        \node[anchor=south west,inner sep=0pt] {\includegraphics#1};
      \fi
    \end{scope}
    \end{tikzpicture}
    }

    \begin{document}
Show the image with a grid to help in finding the coordinates for the path.

    \clippicture{[width=0.8\textwidth]{some-image}}{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)}

    \tikzset{develop clipping path=false}
Done with developing the path. Do the actual clipping.

    \clippicture{[width=0.8\textwidth]{some-image}}{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)}
    \end{document}

clipping an image with a bezier

0
15

run with xelatex, then a pdf image can be clipped

\listfiles
\documentclass{article}
\usepackage{graphicx,pstricks}
\newsavebox\IBox
\begin{document}

\savebox\IBox{\includegraphics{/tmp/two.pdf}}

\begin{pspicture}(\wd\IBox,\ht\IBox)
\psclip{\pscustom[linestyle=none]{%
  \psline(0,0.2\ht\IBox)(0,\ht\IBox)(\wd\IBox,\ht\IBox)(\wd\IBox,0.3\ht\IBox)
  \psbezier(0.75\wd\IBox,0)(0.25\wd\IBox,0.5\ht\IBox)(0,0.2\ht\IBox)}}
  \rput[lb](0,0){\usebox\IBox}
\endpsclip
\end{pspicture}

\end{document}

enter image description here

3
  • 1
    It is a compact solution with a nice photograph. Jun 5, 2011 at 13:09
  • You can use \pst@boxg as a temporary box. Jun 22, 2011 at 7:39
  • 1
    @xport: I know, but it requires makeatletter ....\makeatother and it is defined for internal use of PSTricks
    – user2478
    Jun 22, 2011 at 7:45
10

I take some ideas from Drawing on an image with Tikz but with another method and I complete the code with Jack's method for the clip image.

\documentclass{scrartcl}
\usepackage{tikz,fullpage}
\usetikzlibrary{fit,calc,spy} 

\tikzset{number/.style={fixed,fixed zerofill,precision=1}} 
\makeatletter  
\tikzset{spy style/.style={spy using outlines={magnification=8, size=4cm}}}
\newenvironment{IncludeGH}[2][\textwidth]{%
\def\GHClipImage{#2}
\begin{scope}[spy style] 
\node[anchor=south west,inner sep=0](GHimage){\includegraphics[width=#1]{#2}}; 
\begin{scope}[x={(GHimage.south east)},y={(GHimage.north west)}]}{% 
\end{scope}\end{scope}
}

\newenvironment{IncludeClipGH}[2][\textwidth]{%
\def\GHClipImage{#2}
\begin{scope}
\node[anchor=south west,inner sep=0](GHimage){\phantom{\includegraphics[width=#1]{#2}}}; 
\begin{scope}[x={(GHimage.south east)},y={(GHimage.north west)}]}{% 
\end{scope}\end{scope}
}   

\pgfkeys{GHShowDetail/.cd,
width/.code                    = \def\GH@width{#1},
height/.code                   = \def\GH@height{#1}, 
/GHShowDetail/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                  \pgfkeysalso{\searchname/.try=#1,
                                  /tikz/\searchname/.retry=#1}}}

\def\GHShowDetail{\pgfutil@ifnextchar[{\GH@ShowDetail}{\GH@ShowDetail[]}}
\def\GH@ShowDetail[#1] at (#2,#3)#4{
\pgfkeys{GHShowDetail/.cd,
         width   = 0.1,
         height  = 0.1}
\pgfqkeys{/GHShowDetail}{#1}
    \path (#2,#3)--++(\GH@width/2,\GH@height/2) coordinate (rightnode)
          (#2,#3)--++(-\GH@width/2,-\GH@height/2) coordinate (leftnode);
    \node [fit=(leftnode) (rightnode),
           ultra thick,draw,
           color= lightgray,
           ](#4)  {};}

\pgfkeys{GHShowPath/.cd,
/GHShowPath/.unknown/.code   = {\let\searchname=\pgfkeyscurrentname
                                  \pgfkeysalso{\searchname/.try=#1,
                                  /tikz/\searchname/.retry=#1}}}

\def\GHShowPath{\pgfutil@ifnextchar[{\GH@ShowPath}{\GH@ShowPath[]}}
\def\GH@ShowPath[#1]#2{
\pgfqkeys{/GHShowPath}{#1}
        \draw[#1] #2 -- cycle; 
}

\def\GHShowClipPath{\pgfutil@ifnextchar[{\GH@ShowClipPath}{%
                                         \GH@ShowClipPath[]}}
\def\GH@ShowClipPath[#1]#2{
\pgfqkeys{/GHShowPath}{#1}
\clip  #2 -- cycle;
\node[anchor    = south west,
      inner sep = 0](GHimage){%
      \includegraphics[width=12cm]{\GHClipImage}};
}  

\newif\ifanchor@show\anchor@showfalse
\pgfkeys{GHAnchor/.cd,
color/.code         = \def\GH@anchor@col{#1},
radius/.code        = \def\GH@anchor@rad{#1},
show/.is if         = anchor@show,
show/.default       = true}

\def\GHAnchor{\pgfutil@ifnextchar[{\GH@Anchor}{\GH@Anchor[]}} 
\def\GH@Anchor[#1] at (#2,#3)#4{%
\pgfkeys{/GHAnchor/.cd,
color  = gray,
radius = 2pt,
show   = false}  
\pgfqkeys{/GHAnchor}{#1}  
\coordinate (#4) at (#2,#3);
\ifanchor@show\fill[\GH@anchor@col] (#4) circle [radius=\GH@anchor@rad];\fi
}%

\pgfkeys{GHShowGrid/.cd,
color/.code         = \def\GH@grid@col{#1},
space/.code         = \def\GH@grid@space{#1},
step/.code          = \def\GH@grid@step{#1},
precision/.code     = \def\GH@grid@precision{#1}, 
}%

\def\GHShowGrid{\pgfutil@ifnextchar[{\GH@ShowGrid}{\GH@ShowGrid[]}} 
\def\GH@ShowGrid[#1]{%
\pgfkeys{/GHShowGrid/.cd,
color  = lightgray,
space = 0.04,
step=0.1,
precision = 1}
\pgfqkeys{/GHShowGrid}{#1}
\foreach \x in {0,\GH@grid@step,...,1.001}{%
    \draw[\GH@grid@col] (0,\x) ++(-\GH@grid@space,0) node[left]{%
    \pgfmathprintnumber[fixed,fixed zerofill,precision=\GH@grid@precision]
                       {\x}} -- (1,\x);
    \draw[\GH@grid@col] (\x,0) ++(0,-\GH@grid@space)node[rotate=90,left]{%
    \pgfmathprintnumber[fixed,fixed zerofill,precision=\GH@grid@precision]
                       {\x}} -- (\x,1);}}

\pgfkeys{GHspy/.cd,
color/.code         = \def\GH@anchor@col{#1},
}

\def\GHspy#1#2(#3,#4){%
  \spy  on (#1) in node at ([shift={(#3,#4)}]GHimage.#2); 
}
\makeatother

\begin{document}

\begin{tikzpicture}
\tikzset{spy style/.style={spy using outlines={circle, magnification=4, size=3cm, connect spies}}}

\begin{IncludeGH}[12cm]{champignon.jpeg}  
   \GHShowGrid[color=lightgray,step=.1,precision=1]
   \GHAnchor[color=red,radius=2pt,show] at (0.5,0.5){milieu}   
   \GHShowDetail[shape=circle,color=red,width=.2] at (0.25,0.5){cercle}
   \GHShowDetail[shape=rectangle,width=.1,height=.1] at (0.7,0.7){rec}
   \GHspy{cercle}{south}(-4,-3)  
   \GHShowPath[ultra thick,red]{(0.5,0.75) -- (0.90,0.75) -- (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)} 
\end{IncludeGH}
\end{tikzpicture}

\begin{tikzpicture}
\begin{IncludeClipGH}[12cm]{champignon.jpeg}  
\GHShowClipPath[red]{(0.5,0.75) -- (0.90,0.75) -- 
    (0.90,0.5) .. controls (0.8,-0.2) and (0.65,0.2) .. (0.5,0.3)} 
\end{IncludeClipGH}
\end{tikzpicture}  
\end{document}

enter image description here

7

I am not using Bezier. It is just for fun.

\documentclass{article}
\usepackage{graphicx,pstricks,pst-func}

\newsavebox\IBox
\savebox\IBox{\includegraphics[width=\linewidth]{Images/food}}

\newdimen\width
\newdimen\height
\width=\wd\IBox
\height=\ht\IBox

\def\function
{
        \psparametricplot{0}{2.5 .25 exp}{t^2  | 0.8*(sqrt(2.5-t^4)+t)}
        \psparametricplot{2.5 .25 exp}{0}{t^2  | 0.8*(-sqrt(2.5-t^4)+t)}
        \psparametricplot{0}{2.5 .25 exp}{-t^2 | 0.8*(-sqrt(2.5-t^4)+t)}
        \psparametricplot{2.5 .25 exp}{0}{-t^2 | 0.8*(sqrt(2.5-t^4)+t)}
}

\pagestyle{empty}

\begin{document}
\centering
\begin{pspicture}(\width,\height)
    \rput[lb](0,0){\usebox\IBox}
    \pscustom[unit=2.3cm, origin={0.5\width,0.4\height}, linecolor=cyan, dimen=middle, linewidth=3pt, algebraic]{\function}
    \psgrid[gridwidth=0.2pt, gridcolor=white, subgriddiv=1]
\end{pspicture}

\vspace{1cm}
\begin{pspicture}(\width,\height)
    \psclip{\pscustom[unit=2.3cm, origin={0.5\width,0.4\height}, linestyle=none, algebraic]{\function}}
    \rput[lb](0,0){\usebox\IBox}
    \endpsclip
    \psgrid[gridwidth=0.2pt, gridcolor=white, subgriddiv=1]
\end{pspicture}
\end{document}

enter image description here

4

This is a clipper with bezier curves.

enter image description here

\documentclass[pstricks,border={-8.5mm -5.5mm -8.5mm -5.0mm}]{standalone}
\usepackage{pst-eucl,graphicx}


\psset
{
    runit=\psunit,
    fillstyle=solid,
    PointName=none,
    PointSymbol=none,
}

\pstVerb
{
    /theta 72 def
    /Major 6.0 def
    /Minor 3.3 def
    % b a t p2c ---> x y
    % where b (semi-minor), a (semi-major), t (theta)
    /p2c {dup 3 1 roll cos mul 3 1 roll sin mul} bind def
}

\def\DeclareNodes
{
    \pstGeonode
        (0,-8){Bottom}
        (0,8){Top}
        (0,0){center}
        (0,2.7){A}
        (0.5,2.7){B}
        (1,3.25){C}
        (1.2,1.3){D}
        (1.3,1.0){E}
        (2.0,1.0){F}
        (3.0,1.0){G}
        (3.0,2.2){H}
        (!Minor Major theta p2c){I}
        (!Minor Major theta neg p2c){J}
        (4,-2){K}
        (4,0){L}
        (2.2,-1.8){M}
        (1.5,-1){N}
        (1,-1){O}
        (0,-3.2){P}
    \pstOrtSym{Bottom}{Top}{B,C,D,E,F,G,H,I,J,K,L,M,N,O}
}

\def\RightPart
{
    \psline(A)(B)(C)
    \psbezier(D)(E)(F)
    \psbezier(G)(H)(I)
    \psellipticarcn[dimen=middle](center)(!Major Minor){(I)}{(J)}
    \psbezier(K)(L)(M)
    \psbezier(N)(O)(P)
}


\def\LeftPart
{
    \psbezier(O')(N')(M')
    \psbezier(L')(K')(J')
    \psellipticarcn[dimen=middle](center)(!Major Minor){(J')}{(I')}
    \psbezier(H')(G')(F')
    \psbezier(E')(D')(C')
    \psline(B')
}


\begin{document}


%\begin{pspicture}[showgrid=top](-7,-4)(7,4)
%    \DeclareNodes
%    \pscustom*{\RightPart\LeftPart\closepath}
%\end{pspicture}


\begin{pspicture}[showgrid=false](-7,-4)(7,4)
    \begin{psclip}{\DeclareNodes\pscustom[linewidth=2mm,linecolor=red]{\RightPart\LeftPart\closepath}}
       \rput(0,0){\includegraphics[width=14\psunit]{herbert}}
    \end{psclip}
\end{pspicture}


\end{document}

Edit:

Another similar method can be seen here.

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.