No BSD License  

Highlights from
Rudimental compression algorithms for 2D matlab plots

from Rudimental compression algorithms for 2D matlab plots by Francesco Pozzi
Rudimental compression algorithms for 2D matlab plots (make eps images small for your LaTeX docs!)

compress2Dh(x, y, width, height, alpha)
function [xval, yval] = compress2Dh(x, y, width, height, alpha)

% COMPRESS2DH: Rudimental compression algorithm for 2D matlab plots
%
%
% It is a variant of compress2D(x, y, width, height, alpha). compress2Dh is
% MUCH slower and A BIT more accurate than compress2D.
% Use them if you need to plot highly populated vectors when you expect
% high density of points per pixel.
%
%
% [XVAL, YVAL] = COMPRESS2DH(x, y, width, height) reduces the number of
% points (x, y) which is necessary to represent in a figure, eliminating
% the redundancies. It returns two new vectors xval and yval which can be
% plotted instead of inputs x and y.
%
% It is necessary to specify the width and the height of the desired figure
% and a resolution parameter alpha. The plane is initially fragmented in a
% number of cells which is a function of width, height and alpha:
% ceil(alpha * width) * ceil(height / width * ceil(alpha * width))
%
% alpha must be a positive number such that width * alpha < 3000: the
% smaller alpha, the higher the compression will be, the lower quality the
% final image will have. A suitable value for alpha, when the figure is at
% its maximizum size, is 0.27.
%
% ATTENTION: alpha, width and height all contribute to the quality of the
% final, compressed image. Try different combinations in order to obtain
% the desired compression at the desired quality.
%
%
% If uncertain on how to specify width and height, these lines may help:
% h = figure;                   % open a new figure (manually choose the desired size) 
% set(h, 'Units', 'pixel');     % unit must be pixels
% pos = get(h, 'Position');     % get the Position
% close;                        % close figure
% pos(1:2) = [];                % keep only the last two
% width = pos(1);               % find the desired value of width
% height = pos(2);              % find the desired value of height
% clear h pos;                  % clear unnecessary variables
%
% I found this function useful because I needed to save my matlab figures
% in eps format. Since my vectors were big, I obtained very heavy images
% which could not be easily imported in my LaTeX documents. I have been
% looking around for a function that could help me to compress the images
% but I could not find it. So I wrote functions compress2D and compress2Dh
% which are very rudimental and probably need important implementation, but
% they did their job well enough for my purposes. I'm happy to share them:
% suggestions on how to implement them more efficiently are all welcome.
%
% % -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%
% % EXAMPLE1: how to use the function
% N = 1000000;                                     % A big number
% x = rand(N, 1);                                  % random x values
% y = x .^ 2 + rand(N, 1) / 10;                    % y values along the square of x, plus small random noise
% h = plot(x, y, '.');                             % heavy, uncompressed image ...
% saveas(h, 'heavyuncompressedimage.eps');         % ... heavy, uncompressed file
% h1 = dir('heavyuncompressedimage.eps');          % retrieve file size and display the result
%
% disp(sprintf('The file size, for the uncompressed image, is equal to %0.2f KB', h1.bytes / 1024));
%
% h = figure;                                      % open a new figure (manually choose the desired size) 
% set(h, 'Units', 'pixel');                        % unit must be pixels
% pos = get(h, 'Position');                        % get the Position
% pos(1:2) = [];                                   % keep only the last two
% width = pos(1);                                  % find the desired value of width
% height = pos(2);                                 % find the desired value of height
% clear pos;                                       % clear unnecessary variables
% alpha = 0.27;                                    % a resolution coefficient
% [xind, yind] = compress2Dh(x, y, width, height, alpha);   % new vectors for compressed image
% h = plot(xind, yind, '.');                       % compressed image ...
% saveas(h, 'compressedimage.eps');                % ... small file
% h2 = dir('compressedimage.eps');                 % retrieve file size and display the result
%
% disp(sprintf('The file size, for the compressed image, is equal to %0.2f KB', h2.bytes / 1024));
% disp(sprintf('Congratulations! You have saved %0.2f%% of space', 100 - h2.bytes / h1.bytes * 100));
%
% % -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%
% % EXAMPLE2: an extremely lucky case
% N = 1000000;                                     % A big number
% x = randsample(50, N, 1);                        % random x values, integers from 1 to 50
% y = x .^ 2 + rand(N, 1);                         % y values along the square of x, plus small random noise
% h = plot(x, y, '.');                             % heavy, uncompressed image ...
% saveas(h, 'heavyuncompressedimage.eps');         % ... heavy, uncompressed file
% h1 = dir('heavyuncompressedimage.eps');          % retrieve file size and display the result
%
% disp(sprintf('The file size, for the uncompressed image, is equal to %0.2f KB', h1.bytes / 1024));
%
% h = figure;                                      % open a new figure (manually choose the desired size) 
% set(h, 'Units', 'pixel');                        % unit must be pixels
% pos = get(h, 'Position');                        % get the Position
% pos(1:2) = [];                                   % keep only the last two
% width = pos(1);                                  % find the desired value of width
% height = pos(2);                                 % find the desired value of height
% clear pos;                                       % clear unnecessary variables
% alpha = 3000 / width;                            % a resolution coefficient
% [xind, yind] = compress2Dh(x, y, width, height, alpha);   % new vectors for compressed image
% h = plot(xind, yind, '.');                       % compressed image ...
% saveas(h, 'compressedimage.eps');                % ... small file
% h2 = dir('compressedimage.eps');                 % retrieve file size and display the result
%
% disp(sprintf('The file size, for the compressed image, is equal to %0.2f KB', h2.bytes / 1024));
% disp(sprintf('Congratulations! You have saved %0.2f%% of space', 100 - h2.bytes / h1.bytes * 100));
%
% % -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%
% % EXAMPLE3: an unlucky case
% N = 1000000;                                     % A big number
% x = rand(N, 1);                                  % random x values
% y = rand(N, 1);                                  % random y values
% h = plot(x, y, '.');                             % heavy, uncompressed image ...
% saveas(h, 'heavyuncompressedimage.eps');         % ... heavy, uncompressed file
% h1 = dir('heavyuncompressedimage.eps');          % retrieve file size and display the result
%
% disp(sprintf('The file size, for the uncompressed image, is equal to %0.2f KB', h1.bytes / 1024));
%
% h = figure;                                      % open a new figure (manually choose the desired size) 
% set(h, 'Units', 'pixel');                        % unit must be pixels
% pos = get(h, 'Position');                        % get the Position
% pos(1:2) = [];                                   % keep only the last two
% width = pos(1);                                  % find the desired value of width
% height = pos(2);                                 % find the desired value of height
% clear pos;                                       % clear unnecessary variables
% alpha = 0.4;                                     % a resolution coefficient
% [xind, yind] = compress2Dh(x, y, width, height, alpha);   % new vectors for compressed image
% h = plot(xind, yind, '.');                       % compressed image ...
% saveas(h, 'compressedimage.eps');                % ... small file
% h2 = dir('compressedimage.eps');                 % retrieve file size and display the result
%
% disp(sprintf('The file size, for the compressed image, is equal to %0.2f KB', h2.bytes / 1024));
% disp(sprintf('Congratulations! You have saved %0.2f%% of space', 100 - h2.bytes / h1.bytes * 100));
%
% % -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%
% % EXAMPLE4: lucky (obvious case)
% N = 1000000;                                     % A big number
% x1 = rand(N, 1);                                 % random x1 values
% y1 = 0.5 * ones(N, 1);                           % horizontal line
% x2 = 0.5 * ones(N, 1);                           % vertical line
% y2 = rand(N, 1);                                 % random y2 values
% h = plot(x1, y1, '.');                           % heavy, uncompressed image ...
% hold on
% plot(x2, y2, '.r');
% saveas(h, 'heavyuncompressedimage.eps');         % ... heavy, uncompressed file
% h1 = dir('heavyuncompressedimage.eps');          % retrieve file size and display the result
% 
% disp(sprintf('The file size, for the uncompressed image, is equal to %0.2f KB', h1.bytes / 1024));
% 
% h = figure;                                      % open a new figure (manually choose the desired size) 
% set(h, 'Units', 'pixel');                        % unit must be pixels
% pos = get(h, 'Position');                        % get the Position
% pos(1:2) = [];                                   % keep only the last two
% width = pos(1);                                  % find the desired value of width
% height = pos(2);                                 % find the desired value of height
% clear pos;                                       % clear unnecessary variables
% alpha = 1.50;                                    % a resolution coefficient
% [xind1, yind1] = compress2Dh(x1, y1, width, height, alpha); % find indexes for compressed image
% [xind2, yind2] = compress2Dh(x2, y2, width, height, alpha); % find indexes for compressed image
% h = plot(xind1, yind1, '.');                     % compressed image ...
% hold on
% plot(xind2, yind2, '.r');
% saveas(h, 'compressedimage.eps');                % ... small file
% h2 = dir('compressedimage.eps');                 % retrieve file size and display the result
% 
% disp(sprintf('The file size, for the compressed image, is equal to %0.2f KB', h2.bytes / 1024));
% disp(sprintf('Congratulations! You have saved %0.2f%% of space', 100 - h2.bytes / h1.bytes * 100));
%
% % -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%
%   Author: Francesco Pozzi
%   E-Mail: francesco.pozzi@anu.edu.au
%   Date: 08-07-2008
%

% Check inputs
ctrl = isvector(x) & isnumeric(x) & isreal(x) & isvector(y) & isnumeric(y) & isreal(y);
if ctrl
  ctrl = ctrl & (length(x) == length(y));
  ctrl = ctrl & all(~isinf(x)) & all(~isinf(y));
end
if ctrl
  x = x(:);
  y = y(:);
else
  error('x and y must be vectors of real numbers and of the same size!')
end

ctrl = isscalar(width) & isscalar(height) & isscalar(alpha);
if ctrl
  ctrl = (width > 0) & (height > 0) & (alpha > 0) & (alpha * width <= 3000);
end

if ~ctrl
  error('Specify a valid Position and a valid value for parameter alpha!')
end

% Range of x and y:
xmin = min(x);
xmax = max(x);
ymin = min(y);
ymax = max(y);

% resol1 and resol2 are intervals between minimum and maximum for x and y
% In each area of the grid thus obtained, only one point at most will be
% represented. All others will be discarded
if (xmin == xmax) & (ymin == ymax)
  xval = xmin;
  yval = ymin;
  warning('Hey! Your entire data lie on a single 2D point! Are you sure data are correct?');
  return;
elseif ymin == ymax                                         % if horizontal line ...
  resol1 = ceil(alpha * width);                             % resolution along x-axis
  resol2 = 1;                                               % resolution along y-axis
  j = floor((x - xmin) / (xmax - xmin) * (resol1 - 1)) + 1; % discretized x
  k = ones(size(j));
elseif xmin == xmax                                         % if vertical line ...
  resol1 = ceil(alpha * width);                             % resolution along x-axis
  resol2 = ceil(height / width * resol1);                   % resolution along y-axis
  resol1 = 1;                                               % resolution along x-axis
  k = floor((y - ymin) / (ymax - ymin) * (resol2 - 1)) + 1; % discretized y
  j = ones(size(k));
else
  resol1 = ceil(alpha * width);                             % resolution along x-axis
  resol2 = ceil(height / width * resol1);                   % resolution along y-axis
  j = floor((x - xmin) / (xmax - xmin) * (resol1 - 1)) + 1; % discretized x
  k = floor((y - ymin) / (ymax - ymin) * (resol2 - 1)) + 1; % discretized y
end

xval = sparse(resol1, resol2);                              % new values for x
yval = sparse(resol1, resol2);                              % new values for y
m = sparse(resol1, resol2);                                 % number of elements in each cell
for i = 1:length(x)
  xval(j(i), k(i)) = xval(j(i), k(i)) + x(i);               % for each cell, sum x
  yval(j(i), k(i)) = yval(j(i), k(i)) + y(i);               % for each cell, sum y
  m(j(i), k(i)) = m(j(i), k(i)) + 1;                        % for each cell, remember number of points
end

temp = find(m);                                             % keep only those elements where data exist
m = m(temp);
xval = xval(temp);                                          % keep only those x elements that exist
yval = yval(temp);                                          % keep only those y elements that exist

xval = xval ./ m;                                           % average values for x
yval = yval ./ m;                                           % average values for y

Contact us at files@mathworks.com