Code covered by the BSD License  

Highlights from
PNG Maker

image thumbnail

PNG Maker

by

 

Capture figures as print-read PNG files

saveprintpng(varargin)
function saveprintpng(varargin)
%saveprintpng Save a figure as a print-ready PNG file.
%   saveprintpng filename saves the current active figure window's contents
%   in a 300 dpi PNG file, 'filename.png'. The image is sized to display
%   with a width of 8.88 cm and an aspect ratio of [4 3], and is intended
%   to fit gracefully in one column of an IEEE conference or journal paper.
%   The fonts are set to 8pt Times New Roman. After the file has been
%   created, the figure's original properties are reinstated.
%
%   See also: savepptpng.

% Constants.
FONT_NAME = 'Times New Roman';
FONT_SIZE = 8;
RES = '-r300';
PAPER_UNITS = 'centimeters';
PAPER_SIZE = 8.88 * [1 0.75];
PAPER_UNITS_TO_PIXELS = get(0, 'ScreenPixelsPerInch')/2.54;


try
    [hFigure, fileName] = parseInputArguments(varargin{:});
    
    % Get the figure's initial properties and set up a callback to
    % reinstate them.
    Figdata = storeFigureData(hFigure);    
    cleanupCallback = onCleanup(@()restoreFigureData(Figdata));
    
    % Position the figure on screen appropriately
    if strcmpi(Figdata.windowStyle, 'normal')
        screenImageSize = round(PAPER_SIZE * PAPER_UNITS_TO_PIXELS);
        screenTotalSize = get(0, 'ScreenSize');
        leftMargin = round((screenTotalSize(3)-screenImageSize(1))/2);
        rightMargin = round((screenTotalSize(4)-screenImageSize(2))/2);
    
        newPosition = [leftMargin rightMargin screenImageSize(1) ...
            screenImageSize(2)];
            
        set(hFigure, 'Position', newPosition);            
    end
    
    % Set the paper units and size.
    set(hFigure, 'PaperUnits', PAPER_UNITS);
    set(hFigure, 'PaperPosition', [0 0 PAPER_SIZE]);
    
    % Set the font faces and size.
    set(Figdata.textHandles, 'FontName', FONT_NAME)
    set(Figdata.textHandles, 'FontSize', FONT_SIZE)
    
    % Print the file, ensuring that the modified image is shown briefly.
    drawnow();
    stopTime = now() + 1 * 1/(24*3600);
    print('-dpng', RES, fileName);    
    intervalFcn = @()(now() - stopTime)*24*3600;
    while intervalFcn() < 0
    end    
    
catch ME        
    % Custom error handler.
    rethrowIfNotLocal(ME);
    throwAsCaller(ME);
end

end



function [hFigure, fileName] = parseInputArguments(varargin)
%parseInputArguments Parse the variable input argument string.
%   [hFigure, fileName] = parseInputArguments(arg1, ...) parses the input
%   arguments to the function, returning a figure handle and a filename.

% Allocate arguments.
switch nargin
    case 0
        handledError('notEnoughInputArgs', 'Not enough input arguments.');
    case 1
        hFigure = [];
        fileName = varargin{1};
    case 2
        hFigure = varargin{1};
        fileName = varargin{2};
    otherwise
        handledError('tooManyInputArgs', 'Too many input arguments.');
end        
        
% Check the file name and make sure it has the .png extension.
if ~ischar(fileName)
   handledError('nonCharFileName', 'File name must be of type ''char''.');
end
[pathStr, shortName, extWillBeIgnored] = fileparts(fileName); %#ok<NASGU>
if isempty(fileName)
   handledError('couldNotParseFileName', ...
       'Could not parse file name: ''%s''.', fileName);
end
fileName = fullfile(pathStr, [shortName, '.png']);

% Check the figure window.
if isempty(hFigure)
    CURRENT_FIGURE = get(0, 'CurrentFigure');
    if isempty(CURRENT_FIGURE)
        handledError('noOpenFigure', 'No figure windows are open.');
    else        
        hFigure = CURRENT_FIGURE;
    end
end
if ~isscalar(hFigure)
    handledError('vector', 'hFigure must be a scalar, not a vector.');
end
try
    theType = get(hFigure, 'Type');
    assert(strcmp(theType, 'figure'));
catch
    handledError('invalidFigureHandle', 'Invalid figure handle: %d.', ...
        hFigure);
end
   
end



function Figdata = storeFigureData(hFigure)
%storeFigureData Store the figure's data in a structure.
%   Figdata = storeFigureData(hFigure) stores the figure's data in a
%   structure.

Figdata.handle = hFigure;
Figdata.paperUnits = get(hFigure, 'PaperUnits');
Figdata.paperPosition = get(hFigure, 'PaperPosition');
Figdata.screenPosition = get(hFigure, 'Position');
Figdata.textHandles = findall(hFigure, '-property', 'FontName');
Figdata.fontNames = get(Figdata.textHandles, 'FontName');
Figdata.fontSizes = get(Figdata.textHandles, 'FontSize');
Figdata.windowStyle = get(hFigure, 'WindowStyle');

end



function restoreFigureData(Figdata)
%restoreFigureData Restore the original figure data.
%    restoreFigureData(Figdata) restores the original figure data.

hFigure = Figdata.handle;
set(hFigure, 'PaperUnits', Figdata.paperUnits);
set(hFigure, 'PaperPosition', Figdata.paperPosition);
if strcmpi(Figdata.windowStyle, 'normal')
    set(hFigure, 'Position', Figdata.screenPosition);
end
nTextHandles = numel(Figdata.textHandles);
for iTextHandle = 1:nTextHandles
    This.handle = Figdata.textHandles(iTextHandle);
    This.fontName = Figdata.fontNames{iTextHandle};
    This.fontSize = Figdata.fontSizes{iTextHandle};
    set(This.handle, 'FontName', This.fontName);
    set(This.handle, 'FontSize', This.fontSize);
end
set(hFigure, 'WindowStyle', Figdata.windowStyle);
drawnow()

end



%%% Error Management Functions
%
% The functions below are used to manage local exceptions and throw them
% gracefully: if we trap known issues, e.g. with input data, and report
% them gracefully, it's more helpful to the user.
%

function [thePrefix, nCharsInPrefix] = localExceptionPrefix()
%localException Return the prefix denoting a locally-handled exception.
%   [thePrefix,nCharsInPrefix] = localExceptionPrefix() returns the prefix
%   denoting a locally-handled exception and the number of characters in
%   that prefix.

thePrefix = [mfilename, ':'];
if nargout > 1
    nCharsInPrefix = numel(thePrefix);
end

end



function ME = handledException(partialId, varargin)
%handledException Make an MException for a locally-handled error.
%   ME = handledException(partialId, arg1, ...) makes an MException object
%   representing a locally-handled error.

narginchk(2, inf);
thePrefix = localExceptionPrefix();
id = [thePrefix partialId];
ME = MException(id, varargin{:});

end


    
function handledError(partialId, varargin)
%handledError Raise an error for a locally-handled exception.
%   handledError(partialId, arg1, ...) raises an error representing a
%   locally-handled exception.

narginchk(2, inf);
ME = handledException(partialId, varargin{:});
throwAsCaller(ME);

end



function success = isLocalException(ME)
%isLocalException True if an exception should be handled locally.
%   isLocalException(ME) returns 1 (true) if the MException object ME has
%   an identifier that indicates it is to be handled locally, and 0 (false)
%   otherwise.

assert(isa(ME, 'MException'), 'ME must be an MException object.');
[thePrefix, nCharsInPrefix] = localExceptionPrefix();
success = strncmp(ME.identifier, thePrefix, nCharsInPrefix);

end



function rethrowIfNotLocal(ME)
%rethrowIfNotLocal Rethrow exception unless it should be handled locally.
%   rethrowIfNotLocal(ME) rethrows an exception unless it determines from
%   the identifier that it is handled locally.

assert(isa(ME, 'MException'), 'ME must be an MException object.');
exceptionIsThrowable = ~isLocalException(ME);
if exceptionIsThrowable
    rethrow(ME);
end

end

Contact us