File Exchange

image thumbnail

vecrast

version 1.3.0.0 (3.38 KB) by Theodoros Michelis
vecrast is a function that allows to save a figure with mixed vector and raster content

10 Downloads

Updated 29 May 2019

View License

vecrast is a function that allows to automatically save a figure with mixed vector and raster content. More specifically, two copies of the figure of interest are created, rasterFigure and vectorFigure. Patches, surfaces, contours, images, and lights are kept in rasterFigure but removed from vectorFigure. rasterFigure is then saved as a temporary .png image with the required resolution. The .png file is subsequently inserted into the vectorFigure, and the result is saved in a single vector file.

Cite As

Theodoros Michelis (2019). vecrast (https://www.mathworks.com/matlabcentral/fileexchange/64650-vecrast), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (14)

Great submission! First of all, I would like to advocate for svg support which is enabled by adding
' + strcmp(exportType, 'svg')' to the right side of the if clause in line 66 and by replacing line 206 by
elseif strcmp(exportType, 'svg')
print(vectorFigure, filename, '-dsvg', '-painters')
end

Further, I've had issues with the colorbars of plots where 'CLim' has been adjusted. In investigating this issue I've noticed that replacing the lines 180 to 186 by
origAxes = findall(figureHandle, 'type', 'Axes');
hcbOriginal = findall(figureHandle, 'type', 'colorbar');
if ~isempty(hcbOriginal)
for k = 1:length(hcbOriginal)
colorlims = get(origAxes(k), 'CLim'); % fix clim in case it has been tinkered with it
set(axesHandle(k), 'CLim', colorlims);
end
end

seems to be a viable solution. Actually, this approach restores the colorbar in all cases I've tested, whether 'CLim' has been modified or not.

Regarding colorbar ticks, I found that I had to remove the workaround suggested by Bob DA in order for the tick labels to show up.

Note that the bitmap may be rendered the wrong size if, like me, you have set(0, 'defaultAxesNextPlot', 'add') in a startup file, which avoids having to always specify hold on. To avoid the bad sizing, set defaultAxesNextPlot back to 'replace' before calling vecrast

Hi Theodorus,

I found a minor bug that can occur when there are multiple axes in the figure:

set(axesHandle,'position',axesPosition); % Fix: restore original axes size

change to:

for i = 1:length(axesHandle)
set(axesHandle(i),'position',axesPosition{i}); % Fix: restore original axes size
end

Thanks for your excellent work,
Bryan

sgreess

Worked really well; my only comment is that for my image I had to make the line 82 color change to 'w' and comment out the axes setting fix on line 126. Thanks for making this!

I fixed my problem by commenting lines 115 and 146, so that patches are considered vectors, rather than rasters. This script is a great tool - saves me a lot of headache when plotting surfaces over maps.

So this exports the raster portion of my figure to PDF beautifully. However, I've got a complex figure on map axes, and I seem to lose any objects plotted using geoshow(). Plotm() objects look okay. I'm seeing if there's a workaround for me (using plotm() or patchem() instead of geoshow()), and will post again if I find it. Otherwise, Matlab crashes when trying to print() a PDF of this figure.

Bob DA

Great submission! Similar to Kerry, I had to change the 'color' option on Line 82 to 'w'. The image I was trying to save was generated using 'pcolor', with 'edgecolor' set to 'none'. Without Kerry's suggestion, the saved image was a big black square over the raster area.

One suggestion: I noticed that the colorbar in my saved figure did not reproduce the ticks (or tick labels) that are in my original figure. I traced this behavior back to line 152, where the patch/surface/contour/image visibility is set to 'off'. Apparently when the visibility is turned off, the color axis (and hence the colorbar) is reset to a range of [0, 1]. My simple workaround is as follows, starting at line 165:

% Ensure that all colorbar ticks match the original figure
hcbOriginal = findall(figureHandle, 'type', 'colorbar');
hcbVector = findall(vectorFigure, 'type', 'colorbar');
if ~isempty(hcbOriginal)
cbLimits = hcbOriginal.Limits;
hcbVector.Ticks = (hcbOriginal.Ticks - cbLimits(1))/diff(cbLimits);
hcbVector.TickLabels = hcbOriginal.TickLabels;
end

Kerry

This is a great solution to two problems: (1) large vector graphic file sizes for densely gridded pcolor or surface plot figures and (2) the super lame white lines that recent versions of MATLAB unintentionally create in PDF and eps files for surface plots when using 'painters' rendering (which is required if you want to later edit the figure annotations in Illustrator).

I had made a code like this years ago but it just output the two image files with the figure's annotations and lines saved to a .ps file and the pcolor/surf image data alone to a bitmap file, then I had to combine them manually in Adobe Illustrator. I did that to save memory since my surface plots were in the 10's to 100's of MB when saved to a vector graphics format. vecrast.m does the recombination automatically. The second problem arose in recent versions of MATLAB, which introduced the heinous white lines problem for PDF files made of surface plots. vecrast is a great solution to both of these issues.

I had to modify the code to work for my images in the following ways:
---
(1) changed color to 'w' otherwise my surface (plotted with 'shading flat') had black edge lines everywhere:
set(rasterFigure, 'GraphicsSmoothing', 'on', 'color', 'w');
---
(2) made sure the axes didn't autoresize in the raster section. My figures had titles taking up two lines and the raster axes resized so it no longer matched the vector axes dimensions when reinserting. The fix is to restore the position after the loop removing the annotations.

% Raster Figure ----------------------------------------------------------
% Select what to remove from raster figure
axesHandle = findall(rasterFigure, 'type', 'axes');
axesPosition = get(axesHandle,'position'); % Fix: get axes size
...
for i = 1:length(axesHandle)
..
end
set(axesHandle,'position',axesPosition); % % Fix: restore original axes size
---
(3) The eps output worked fine, but to get the PDF output to work, I had to resize the figure position to something less than US letter width before calling vecrast.

Robert

This is amazing, I often had to do whole thing manually...

When using the function I encountered two problems. First, print ignores interpolations. For that reason I would thus suggest to use hgexport instead, i.e. replace

% print(rasterFigure, [filename 'Temp.png'], '-dpng', ['-r' num2str(resolution) ], '-loose', '-opengl');

by

style.Format = 'png';
style.Renderer = 'opengl';
style.Resolution = resolution;
hgexport(rasterFigure, [filename 'Temp.png'], style)

The second issue is that when hiding the plot for the vector image, Matlab automatically sets to colorbar limits to [0, 1]. I haven't yet found a solution to that...

I modified your example to illustrate both issues.

%% E X A M P L E 2:
clear all; close all; clc;
[X,Y] = meshgrid(1:0.4:10, 1:0.4:20);
Z = sin(X) + cos(Y);
surf(X,Y,Z)
shading interp
colorbar
vecrast(gcf, 'example2', 300, 'top', 'pdf');

I sorted it out. For me, I had to change lines 80-81 to 'copyobj(figureHandle, groot);'. Also, the file name for the temporary raster image has inconsistent capitalization, which fails on non-Windows systems. Otherwise it works beautifully.

I do have a couple suggested improvements. The element I'm wanting to raster is a 'Scatter' plot of thousands of points with transparency. I modified the list of 'toKeep' and 'toRemove' objects to include this type, but realized this could easily be turned into either a list of graphics types or handles passed into the function, for greater flexibility. The other challenge with the transparency, is I have some objects in front of and some objects behind the transparent data, so would be interested to maintain that order, rather than put the raster image at the front or back. But already this is a huge benefit to me.

This function addresses a significant problem I've struggled with when making and publishing figures in the past. However I can't get it to work, because of a missing dependency on a 'copyfig' function. Can you point to where this might be available?

Updates

1.3.0.0

Integrated the comment of Bryan Lougheed.

1.2.0.0

Integrated the suggestions of Kerry and Bob DA.

1.1.0.0

Code simplification and minor updates based on the comments of Jonathan Kohler.

1.0.0.0

Snapshot

MATLAB Release Compatibility
Created with R2017a
Compatible with any release
Platform Compatibility
Windows macOS Linux
Tags Add Tags