2017-05-31 4 views
0

J'ai une fonction assez complexe que je tracer en utilisant fsurf avec un MeshDensity raisonnablement élevé (je ne peux pas aller beaucoup plus bas que la valeur par défaut, qui est de 35). L'exportation de ce chiffre (saveas(gcf, 'file.pdf', 'pdf');) aboutit à un fichier pdf de 20 méga-octets de très belle qualité, qui reste néanmoins terriblement lent. Je voudrais réduire la taille du fichier et, surtout, la complexité de ce fichier pdf, sans exporter l'ensemble de l'intrigue (par laquelle je veux dire l'ensemble de la figure MATLAB) comme une image bitmap. Comment puis je faire ça? La réponse parfaite expliquerait comment je peux convertir le tracé de surface (par lequel je veux dire, juste la surface de fonction colorée sur le fond blanc) dans un bitmap tout en maintenant le caractère vectorisé des axes et des étiquettes.Bitmap rendre une partie de l'intrigue lors de l'exportation de graphiques vectoriels dans MATLAB

Mise à jour: Voici un exemple d'un tel tracé.

enter image description here

+0

"Je veux un vecteur et un bitmap, * en même temps *". Hmmmmmm. –

+0

@AnderBiguri dans mon monde, c'est ce qu'on appelle "embedding", et pas une grande source de confusion pour quiconque a déjà vu une photo dans un fichier pdf. – bers

+0

Une photographie dans un fichier pdf est juste un bitmap, il n'a pas de graphiques vectoriels. Afficher votre image, il peut être possible, juste peut –

Répondre

0

C'est ma fonction BitmapRender, ce qui rend Bitmap-partie de la figure:

%% 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'); 

La fonction elle-même est assez simple, à l'exception de la (re) traitement de la visibilité, comme En appuyant sur la touche espace (après avoir pivoté, zoomé, etc.), la figure redevient.

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 

De toute évidence, la solution est parfaite en pixels en termes de pixels d'écran. Deux fichiers pdf (pre et post) ressemblent à ceci. Notez que la surface, l'image et certaines lignes de tracé sont rendues en mode point, mais certaines autres lignes de tracé, ainsi que les axes et les étiquettes sont toujours vectorisés.

enter image description here enter image description here