【问题标题】:Get rid of the white space around matlab figure's pdf output摆脱matlab图形的pdf输出周围的空白
【发布时间】:2011-04-17 15:13:51
【问题描述】:

我想在 LaTeX 文档中使用我的 matlab 绘图的 PDF 版本。我正在使用带有 PDF 选项的“saveas”命令保存数字,但我在 pdf 文件中的绘图周围出现了巨大的空白。这是正常的吗?我怎样才能摆脱它?当然,自动,因为我有“很多”的情节。

【问题讨论】:

  • 我的工作流程中有pdfcrop,以便在事后摆脱空白。帮助许多其他程序以及将 PDF 输出为整张纸。
  • 您是否致电客户支持?毕竟,Matlab 是昂贵的商业软件。

标签: pdf matlab


【解决方案1】:

Exporting Figures for Publication 是一个很好的起点。代替-deps 使用-dpdf 输出pdf。

您可以使用以下代码修复边界框问题。

set(gcf, 'PaperSize', [6.25 7.5]);
set(gcf, 'PaperPositionMode', 'manual');
set(gcf, 'PaperPosition', [0 0 6.25 7.5]);

set(gcf, 'PaperUnits', 'inches');
set(gcf, 'PaperSize', [6.25 7.5]);
set(gcf, 'PaperPositionMode', 'manual');
set(gcf, 'PaperPosition', [0 0 6.25 7.5]);

set(gcf, 'renderer', 'painters');
print(gcf, '-dpdf', 'my-figure.pdf');
print(gcf, '-dpng', 'my-figure.png');
print(gcf, '-depsc2', 'my-figure.eps');

您可以在Tobin's 文章中阅读更多相关信息。

【讨论】:

【解决方案2】:

上面的答案似乎太复杂了。此函数使用图形句柄和字符串来打印 pdf 文件中的内容,而没有大的边距。

function printpdf(h,outfilename)

set(h, 'PaperUnits','centimeters');
set(h, 'Units','centimeters');
pos=get(h,'Position');
set(h, 'PaperSize', [pos(3) pos(4)]);
set(h, 'PaperPositionMode', 'manual');
set(h, 'PaperPosition',[0 0 pos(3) pos(4)]);
print('-dpdf',outfilename);

例如,要打印当前图形,您可以调用它:

printpdf(gcf,'trash')

但是,如果你真的想要一个像 Matlab 生成的 eps 那样的 pdf 图形,也就是说,只有图形的矩形凸包(或子图集),这里是更复杂的版本:

function printpdf(h,outfilename)

% first use the same non-relative unit system for paper and screen (see
% below)
set(h,'PaperUnits','centimeters');

% now get all existing plots/subplots
a=get(h,'Children');
nfigs=length(a);

% bounds will contain lower-left and upper-right corners of plots plus one
% line to make sure single plots work
bounds=zeros(nfigs+1,4);
bounds(end,1:2)=inf;
bounds(end,3:4)=-inf;

% generate all coordinates of corners of graphs and store them in
% bounds as [lower-left-x lower-left-y upper-right-x upper-right-y] in
% the same unit system as paper (centimeters here)
for i=1:nfigs
    set(a(i),'Unit','centimeters');
    pos=get(a(i),'Position');
    inset=get(a(i),'TightInset');
    bounds(i,:)=[pos(1)-inset(1) pos(2)-inset(2) ...
        pos(1)+pos(3)+inset(3) pos(2)+pos(4)+inset(4)];
end

% compute the rectangular convex hull of all plots and store that info
% in mypos as [lower-left-x lower-left-y width height] in centimeters
auxmin=min(bounds(:,1:2));
auxmax=max(bounds(:,3:4));
mypos=[auxmin auxmax-auxmin];

% set the paper to the exact size of the on-screen figure using
% figure property PaperSize [width height]
set(h,'PaperSize',[mypos(3) mypos(4)]);

% ensure that paper position mode is in manual in order for the
% printer driver to honor the figure properties
set(h,'PaperPositionMode', 'manual');

% use the PaperPosition four-element vector [left, bottom, width, height]
% to control the location on printed page; place it using horizontal and
% vertical negative offsets equal to the lower-left coordinates of the
% rectangular convex hull of the plot, and increase the size of the figure
% accordingly
set(h,'PaperPosition',[-mypos(1) -mypos(2) ...
    mypos(3)+mypos(1) mypos(4)+mypos(2)]);

% print stuff
print('-dpdf',outfilename);

【讨论】:

  • 有关这两个函数渲染的 pdf 有何不同的示例,请参阅这两个屏幕截图。 First code blockSecond code block(仅限矩形凸包)。请注意,在第二张图片中,情节是如何正好靠在左下角的。另请注意,这些似乎是真正的矢量图像(不是光栅),这对我来说是我需要的,尽管我想要更少的空白。无论如何,谢谢安东尼奥!
【解决方案3】:

除了此处的其他建议外,您还可以尝试使用 http://UndocumentedMatlab.com/blog/axes-looseinset-property/ 中所述的 LooseInset 属性来移除绘图轴周围的额外空间。

【讨论】:

  • 该选项只会收紧图形窗口中绘图周围的空间。当您执行诸如 print('trash','-dpdf') 之类的操作时,您会将图形打印在 A4/Letter 纸上...
【解决方案4】:

对于这个 b4 找到一个简单的答案,我有点受苦。另存为 .eps,然后将 .eps 转换为 .pdf。在 Mac OS 中,这可以在 Preview 中完成。

【讨论】:

    【解决方案5】:

    我只是花了一些时间尝试了这些选项中的大多数,但我的朋友 Espen 指出了最简单的方法:如果您在 LaTeX 中使用 graphicsx 包,请使用标准 Matlab pdf 输出并使用 \includegraphics 中的 trim 选项。 Beamer 幻灯片中的示例:

    \includegraphics[trim = 0.1in 2.5in 0.1in 2.5in, clip, scale=0.5]{matlabgraphic.pdf}

    这里修剪参数的顺序是左、下、右、上。关键是要大量修剪顶部和底部以摆脱多余的空间。更多信息请访问Wikibooks

    【讨论】:

    • 我偶尔会这样做,但如果您知道您的 pdf 图形不包含白边距,您可以省去很多麻烦。然后,您可以执行 \includegraphics[width=1.0\textwidth]{matlabgraphic.pdf} 之类的操作,而无需担心裁剪和修剪图形。我最近和合著者写的一篇论文有不少于 30 张图,因为它们是由其他人制作的,所以我不得不使用你的方法;真的很痛苦。
    【解决方案6】:

    对于光栅图像输出(例如 png),我的 Makefile 中有以下内容:

    convert -trim input.png input-trimmed.png
    

    这需要 imagemagick。

    更新:对于我最近发表的所有文章,我使用了https://github.com/altmany/export_fig,这是迄今为止我发现的最佳解决方案(以及针对单个软件包中其他问题的许多其他解决方案)。我觉得一个至少和它一样强大的工具应该已经是 Matlab 的官方部分了。我把它用作:

    export_fig -transparent fig.pdf
    

    导出当前图,默认裁剪输出。

    需要鬼脚本

    【讨论】:

    • 这个功能比 printpdf.m 好太多了,虽然有点复杂。
    【解决方案7】:

    我也遇到过这个问题。最后,我用下面的方法解决了这个问题,可以自动将一个matlab图形保存为合适的pdf大小。

    您可以通过以下方式在 MATLAB 中完成:

    h = figure; % For example, h = openfig('sub_fig.fig'); Or you just ploted one figure: plot(1:10);
    set(h,'Units','Inches');
    pos = get(h,'Position');
    set(h,'PaperPositionMode','Auto','PaperUnits','Inches','PaperSize',[pos(3),pos(4)]);
    print(h,'your_filename','-dpdf','-r0');
    

    希望对你有帮助。

    【讨论】:

      【解决方案8】:

      我最喜欢@Antonio 的方法,但它仍然留下太多空白,我正在寻找一种可以导出为矢量 pdf 以在 LaTeX 中使用的单一绘图解决方案。

      • 我根据他的脚本做了一些东西,并添加了仅导出绘图框的选项(省略轴)。

      • 请注意,与 Antonio 的脚本不同,这仅适用于没有子情节的人物。

      • 下面的代码会将任何单个绘图图形句柄导出为矢量 PDF,无论是否带有轴。


      function SaveFigureAsVectorPDF(InputFigureHandle, OutFileName, ShouldPrintAxes)
          %% Check input parameters
          [NumberOfFigures, ~] = size(InputFigureHandle);    
      
          if(NumberOfFigures ~= 1)
              error('This function only supports one figure handle.');
      
          end
      
          if(isempty(OutFileName))
              error('No file path provided to save the figure to.');
      
          end
      
          cUnit = 'centimeters';
      
          %% Copy the input figure so we can mess with it    
          %Make a copy of the figure so we don't modify the properties of the
          %original.
          FigureHandleCopy = copy(InputFigureHandle);
      
          %NOTE:  Do not set this figure to be invisible, for some bizarre reason
          %       it must be visible otherwise Matlab will just ignore attempts 
          %       to set its properties.
          % 
          %       I would prefer it if the figure did not briefly flicker into
          %       view but I am not sure how to prevent that.
      
          %% Find the axis handle
          ChildAxisHandles     = get(FigureHandleCopy, 'Children');
          NumberOfChildFigures = length(ChildAxisHandles);
      
          if(NumberOfChildFigures ~= 1)
             %note that every plot has at least one child figure
             error('This function currently only supports plots with one child figure.');
      
          end
      
          AxisHandle = ChildAxisHandles(1);
      
          %% Set Units
          % It doesn't matter what unit you choose as long as it's the same for
          % the figure, axis, and paper. Note that 'PaperUnits' unfortunately
          % does not support 'pixels' units.
      
          set(FigureHandleCopy,   'PaperUnits',   cUnit);
          set(FigureHandleCopy,   'Unit',         cUnit);
          set(AxisHandle,         'Unit',         cUnit); 
      
          %% Get old axis position and inset offsets 
          %Note that the axes and title are contained in the inset
          OldAxisPosition = get(AxisHandle,   'Position');
          OldAxisInset    = get(AxisHandle,   'TightInset');
      
          OldAxisWidth    = OldAxisPosition(3);
          OldAxisHeight   = OldAxisPosition(4);
      
          OldAxisInsetLeft    = OldAxisInset(1);
          OldAxisInsetBottom  = OldAxisInset(2);
          OldAxisInsetRight   = OldAxisInset(3);
          OldAxisInsetTop     = OldAxisInset(4);
      
          %% Set positions and size of the figure and the Axis 
          if(~ShouldPrintAxes)
      
              FigurePosition = [0.0, 0.0, OldAxisWidth, OldAxisHeight];
      
              PaperSize = [OldAxisWidth, OldAxisHeight];
      
              AxisPosition = FigurePosition;      
      
          else
              WidthWithInset  = OldAxisWidth   + OldAxisInsetLeft + OldAxisInsetRight;
              HeightWithInset = OldAxisHeight  + OldAxisInsetTop  + OldAxisInsetBottom;
      
              FigurePosition = [0.0, 0.0, WidthWithInset,  HeightWithInset];
      
              PaperSize = [WidthWithInset, HeightWithInset];
      
              AxisPosition = [OldAxisInsetLeft, OldAxisInsetBottom, OldAxisWidth, OldAxisHeight];
      
          end
      
          set(FigureHandleCopy,   'Position', FigurePosition);
          set(AxisHandle,         'Position', AxisPosition);
      
          %Note:  these properties do not effect the preview but they are
          %       absolutely necessary for the pdf!!
          set(FigureHandleCopy,   'PaperSize',        PaperSize);
          set(FigureHandleCopy,   'PaperPosition',    FigurePosition);
      
          %% Write the figure to the PDF file
          print('-dpdf', OutFileName);
      
          set(FigureHandleCopy, 'name', 'PDF Figure Preview', 'numbertitle', 'off');
      
          %If you want to see the figure (e.g., for debugging purposes), comment
          %the line below out.
          close(FigureHandleCopy);
      
      end
      

      示例图片:

      带轴:

      没有轴:

      测试代码:

      %% Generates a graph and saves it to pdf
      
      FigureHandle = figure;
      
      plot(1:100);
      
      title('testing');
      
      %with axes
      SaveFigureAsVectorPDF(FigureHandle, 'withaxes.pdf', true);
      
      %without axes
      SaveFigureAsVectorPDF(FigureHandle, 'withoutaxes.pdf', false);
      

      【讨论】:

      • 请注意,人物图例算作人物的“孩子”。
      【解决方案9】:

      在 MATLAB file exchange 上,我发现了 Jürg Schwizer 提供的一个非常有用的函数:

      plot2svg( filename, figHandle );
      

      将图形输出为矢量图形 (.svg),将单个图形组件输出为像素图形(默认为 .png)。这使您可以对您的图形执行各种操作(删除标签、移动颜色条等),但如果您有兴趣删除白色背景,只需打开 .svg 文件,例如inkscape,取消组合项目并将您感兴趣的项目导出为新图形。

      【讨论】:

        【解决方案10】:

        对于那些使用 linux 的人来说,一个非常简单的解决方案是在 shell 中编写: ps2pdf14 -dPDFSETTINGS=/prepress -dEPSCrop image.eps

        【讨论】:

          【解决方案11】:

          你也可以在乳胶本身中做到这一点。

          1. 用记事本打开eps文件
          2. 转到第一行 (%!PS-Adobe-3.1 EPSF-3.0)

          如果最后一个数字是 3, 搜索“rf”,然后在行首输入% 注释该行

          否则,如果最后一个数字是 2, 搜索“pr”,然后在行首输入% 注释该行

          【讨论】:

          • 这看起来像是在编辑原始图像文件,而不是与乳胶有关?您可能还想指出 % 是 PS (AFAIR) 中的评论
          【解决方案12】:

          以下两步方法对我有用(使用 pdfcrop)。假设您已安装所有 pdf-tools 和 PDFcrop (http://pdfcrop.sourceforge.net/)

          在 MATLAB 中,键入

          print -deps -r600 figure.eps
          

          然后在命令行中

          ./cropEpsFigure.sh figure
          

          使用以下文件:cropEpsFigure.sh

          #!/bin/bash
          /usr/texbin/epstopdf "$1.eps"
          /usr/texbin/pdfcrop "$1.pdf"
          /usr/local/bin/pdftops -eps "$1-crop.pdf"`
          

          【讨论】:

            【解决方案13】:

            对于 Linux 用户,以下命令可能会有所帮助

            ps2epsi <input.eps> <output.eps>

            如建议here

            如果您打算在乳胶中使用,请使用乳胶命令\includegraphics* 而不是\includegraphics

            【讨论】:

            • 这对 PDF 有什么帮助?
            【解决方案14】:

            这适用于显示目的:

            set(gca, 'LooseInset', get(gca, 'TightInset'));
            

            也应该适用于打印。

            【讨论】:

            • 不,不走运:>> set(gca, 'LooseInset', get(gca, 'TightInset')); >> 打印(gcf, '-dpdf', 'my-figure.pdf'); >> 打印(gcf, '-dpng', 'my-figure.png');不工作
            【解决方案15】:

            在 Matlab 中将绘图保存为 .eps 格式,然后在 Linux 下执行 esptopdf 命令。这不需要任何额外的编码。只需要一台 Linux 机器。

            【讨论】:

              【解决方案16】:

              使用pdfcrop 是另一种解决方案。只需 cd 到保存并运行所有 pdf 的文件夹

              for i in *;do pdfcrop "$i";done

              唯一的问题是pdfcrop 不适用于 Windows。所以我从 Windows Subsystem for Linux (WSL) 运行它。

              【讨论】:

                【解决方案17】:

                如果您有带有额外空格的现有 pdf,则可以将此命令与 Inkscape 一起使用。

                Inkscape.exe --file SomePDFWithWhitespace.pdf --export-pdf=SomePDFWithWhitespaceRemoved.pdf --export-area-drawing
                

                但请注意,此方法仍会留下一些空白,因为导出图形的“绘图区域”本身包含一些空白。

                使用Inkscape的效果如下图:

                之前:(使用文件保存的图形 -> 另存为)

                之后:(使用 Inkscape)

                【讨论】:

                • 您可能希望在回答问题时包含实际所需的命令。
                • 我非常感谢这个解决方案,但找不到它。如果有人知道它,请发布它。
                • @Lisa 这个命令会做,但请注意它会留下一些不必要的空格:Inkscape.exe --file SomePDFWithWhitespace.pdf --export-pdf=SomePDFWithWhitespaceRemoved.pdf --export-area-drawing
                猜你喜欢
                • 2016-12-21
                • 1970-01-01
                • 2014-08-17
                • 2021-08-10
                • 1970-01-01
                • 2014-08-15
                • 1970-01-01
                • 2010-09-26
                • 1970-01-01
                相关资源
                最近更新 更多