MATLAB中矢量图形导出时位图渲染部分绘图

MATLAB中矢量图形导出时位图渲染部分绘图,matlab,graphics,vector-graphics,bitmapimage,Matlab,Graphics,Vector Graphics,Bitmapimage,我有一个非常复杂的函数,我使用fsurf绘制,具有相当高的网格密度(我不能比默认值低很多,即35)。导出此图形(saveas(gcf,'file.pdf,'pdf');)会生成一个20多MB的pdf文件,质量非常好,但渲染速度非常慢。我想减少文件大小,最重要的是,减少这个pdf文件的复杂性,而不将整个绘图(我指的是整个MATLAB图形)导出为位图。我该怎么做 完美的答案将解释如何将曲面图(我的意思是,白色背景上的彩色函数曲面)转换为位图,同时保持轴和标签的矢量化性质 更新:下面是这样一个图的示例

我有一个非常复杂的函数,我使用
fsurf
绘制,具有相当高的
网格密度(我不能比默认值低很多,即35)。导出此图形(
saveas(gcf,'file.pdf,'pdf');
)会生成一个20多MB的pdf文件,质量非常好,但渲染速度非常慢。我想减少文件大小,最重要的是,减少这个pdf文件的复杂性,而不将整个绘图(我指的是整个MATLAB图形)导出为位图。我该怎么做

完美的答案将解释如何将曲面图(我的意思是,白色背景上的彩色函数曲面)转换为位图,同时保持轴和标签的矢量化性质

更新:下面是这样一个图的示例


这是我的函数BitmapRender,该函数通过位图渲染部分图形:

%% Test Code
clc;clf;
Objects = surf(-4-2*peaks);
hold('on');
Objects(2 : 50) = plot(peaks);
Objects(51) = imagesc([20 40], [0, 5], magic(100));
hold('off');
ylim([0 10]);
zlim([-10 15]);
Objects(1).Parent.GridLineStyle = 'none';
view(45, 45);
set(gcf, 'Color', 'white');
rotate3d on

saveas(gcf, 'pre.pdf');
BitmapRender(gca, Objects(2 : 3 : end));
% BitmapRender(gca, Objects(2 : 3 : end), [0.25 0.25 0.5 0.5], false);
saveas(gcf, 'post.pdf');
该函数本身非常简单,除了(重新)处理可见性外,按空格键(旋转、缩放等后)可重新渲染图形

function BitmapRender(Axes, KeepObjects, RelativePosition, Draft, Key)

if nargin < 2
    KeepObjects = [];
end
if nargin < 3
    RelativePosition = [0 0 1 1];
end
if nargin < 4
    Draft = false;
end
if nargin < 5
    Key = '';
end

Figure = Axes.Parent;
FigureInnerWH = Figure.InnerPosition([3 4 3 4]);
PixelPosition = round(RelativePosition .* FigureInnerWH);

if isempty(Key)
    OverlayAxes = axes(Figure, 'Units', 'Normalized', 'Position', PixelPosition ./ FigureInnerWH);
    if Draft
        OverlayAxes.Box = 'on';
        OverlayAxes.Color = 'none';
        OverlayAxes.XTick = [];
        OverlayAxes.YTick = [];
        OverlayAxes.HitTest = 'off';
    else
        uistack(OverlayAxes, 'bottom');
        OverlayAxes.Visible = 'off';
    end
    setappdata(Figure, 'BitmapRenderOriginalVisibility', get(Axes.Children, 'Visible'));

    Axes.CLimMode = 'manual';
    Axes.XLimMode = 'manual';
    Axes.YLimMode = 'manual';
    Axes.ZLimMode = 'manual';

    hManager = uigetmodemanager(Figure);
    [hManager.WindowListenerHandles.Enabled] = deal(false);
    set(Figure, 'KeyPressFcn', @(f, e) BitmapRender(gca, KeepObjects, RelativePosition, Draft, e.Key));
elseif strcmpi(Key, 'space')
    OverlayAxes = findobj(Figure, 'Tag', 'BitmapRenderOverlayAxes');
    delete(get(OverlayAxes, 'Children'));
    OriginalVisibility = getappdata(Figure, 'BitmapRenderOriginalVisibility');
    [Axes.Children.Visible] = deal(OriginalVisibility{:});
else
    return;
end

if Draft
    return;
end

Axes.Visible = 'off';

KeepObjectsVisibility = get(KeepObjects, 'Visible');
[KeepObjects.Visible] = deal('off');

drawnow;
Frame = getframe(Figure, PixelPosition);

[Axes.Children.Visible] = deal('off');
Axes.Visible = 'on';
Axes.Color = 'none';
if numel(KeepObjects) == 1
    KeepObjects.Visible = KeepObjectsVisibility;
else
    [KeepObjects.Visible] = deal(KeepObjectsVisibility{:});
end

Image = imagesc(OverlayAxes, Frame.cdata);
uistack(Image, 'bottom');
OverlayAxes.Tag = 'BitmapRenderOverlayAxes';
OverlayAxes.Visible = 'off';

end
函数位图渲染(轴、保留对象、相对位置、草图、键)
如果nargin<2
KeepObjects=[];
结束
如果nargin<3
相对位置=[001];
结束
如果nargin<4
草稿=假;
结束
如果nargin<5
键='';
结束
图=轴。父轴;
FigureInnerWH=Figure.InnerPosition([3 4]);
像素位置=圆形(相对位置。*图INNERWH);
如果为空(键)
重叠轴=轴(图“单位”、“标准化”、“位置”、“像素位置”。/FigureInnerWH);
如果草稿
Box='on';
OverlayAxes.Color='none';
OverlayAxes.XTick=[];
OverlayAxes.YTick=[];
OverlayAxes.HitTest='off';
其他的
uistack(叠加“底部”);
OverlayAxes.Visible='off';
结束
setappdata(图'BitmapRenderOriginalVisibility',get(Axes.Children,'Visible');
Axes.CLimMode='手动';
Axes.xlimode=‘手动’;
Axes.YLimMode='手动';
Axes.ZLimMode=‘手动’;
hManager=uigetmodemanager(图);
[hManager.WindowListenerHandles.Enabled]=交易(false);
设置(图,'KeyPressFcn',@(f,e)位图渲染(gca,KeepObject,RelativePosition,Draft,e.Key));
elseif strcmpi(键“空格”)
OverlayAxes=findobj(图“Tag”、“BitmapRenderOverlayAxes”);
删除(get(OverlayAxes,'Children');
OriginalVisibility=getappdata(图“BitmapRenderOriginalVisibility”);
[Axes.Children.Visible]=deal(OriginalVisibility{:});
其他的
返回;
结束
如果草稿
返回;
结束
轴可见='关闭';
KeepObjectsVisibility=get(KeepObjects,“可见”);
[KeepObjects.Visible]=交易('off');
现在抽;
Frame=getframe(图,像素位置);
[Axes.Children.Visible]=交易('off');
Axes.Visible='on';
颜色='无';
如果numel(KeepObjects)==1
KeepObjects.Visible=KeepObjectsVisibility;
其他的
[KeepObjects.Visible]=deal(KeepObjectsVisibility{:});
结束
Image=imagesc(OverlayAxes,Frame.cdata);
uistack(图像“底部”);
Tag='BitMapRenderRoverLayaxes';
OverlayAxes.Visible='off';
结束
显然,就屏幕像素而言,解决方案是像素完美的。两个pdf文件(
pre
post
)如下所示。请注意,曲面、图像和某些打印线是位图渲染的,但其他一些打印线以及轴和标签仍然是矢量化的


“我想要一个矢量和一个位图,同时”。嗯,嗯。@AnderBiguri在我的世界里,这被称为“嵌入”,对于任何看过pdf文件中照片的人来说,这并不是一个很大的困惑。pdf文件中的照片只是一个位图,它没有矢量图形。展示你的形象,这可能是可能的,只是may@AnderBiguri嗯,标准文本,除非被渲染成位图,也和我认为的矢量图形非常接近。所以我应该说,“任何人都见过pdf文件中某个文本旁边的照片”?我相信你已经明白我的意思了。我会用一些快照更新这个问题。无意冒犯,但我不明白你的意思。你不能“考虑”矢量图形。矢量图形是存储信息的一种方式,而不是视觉外观。有些东西是或不是矢量图形。您可以将位图放入PDF中,没有任何问题。我不认为你可以做一个图形,它既是位图(用于冲浪)又是向量(用于轴)。我认为没有任何文件格式允许这样做。