Save a plot to a JPEG file in Matlab - user-interface

I have designed the following GUI in which there are an axes. I want to save the plot drawn inside them to a jpeg file. However, the file obtained is an image of the overall figure window. This is my code:
X = 0:pi/100:2*pi;
Y = sin(X);
fh = figure;
Pan1 = uipanel(fh,'Units','normalized','Position',[0 0 0.5 1],'title',...
'Panel1');
Pan2 = uipanel(fh,'Units','normalized','Position',[0.5 0 0.5 1],'title',...
'Panel2');
haxes = axes('Parent',Pan2,'Units', 'normalized','Position',...
[0.25 0.25 0.5 0.5]);
hplot = plot(haxes,X,Y);
xlabel(haxes,'Time (second)');
ylabel(haxes,'Amplitude (meter)');
title(haxes,'Sine function');
FileName = uiputfile('*.jpg','Save as');
saveas(hplot,FileName);

saveas only saves figures, not individual plots.
If you have a subplot, or a plot within a uicontrol like you have, you can make a temporary copy of the plot, save it, then delete the temporary copy:
ftmp = figure; atmp = axes;
copyobj(hplot, atmp);
saveas(ftmp, FileName);
delete(ftmp);
If you don't want the temporary copy to flash up on the screen during the copying step, you can use the 'Position' property of the figure to create it off-screen.
Hope that helps!

#Sam's answer is spot on, I just want to add that Matlab is smart enough to know what kind of file you want to save by inspecting the FileName string variable. If you set FileName to something that ends in .jpg, you can save a jpeg. Check out the saves docs to see all the other possible filetypes.

When using the saveas function to create jpeg the resolution is different as when manually saving the figure with File-->Save As..., It's more recommended to use hgexport instead, as follows:
hgexport(gcf, 'figure1.jpg', hgexport('factorystyle'), 'Format', 'jpeg');
This will do exactly as manually saving the figure.
source:
http://www.mathworks.com/support/solutions/en/data/1-1PT49C/index.html?product=SL&solution=1-1PT49C

This is my solution based on Sam Roberts and eykanal's answer:
X = 0:pi/100:2*pi;
Y = sin(X);
fh = figure('toolbar','none','menubar','none');
Pan1 = uipanel(fh,'Units','normalized','Position',[0 0 0.5 1],'title',...
'Panel1');
Pan2 = uipanel(fh,'Units','normalized','Position',[0.5 0 0.5 1],'title',...
'Panel2');
haxes = axes('Parent',Pan2,'Units', 'normalized','Position',...
[0.125 0.1 0.75 0.75]);
hplot = plot(haxes,X,Y);
xlabel(haxes,'Time (second)');
ylabel(haxes,'Amplitude (meter)');
title(haxes,'Sine function');
FileName = uiputfile('*.bmp;*.png;*.jpg;*.tif','Save as');
ftmp = figure('Menu','none','Toolbar','none','Units','normalized',...
'Position',[-1000 -1000 1 1]);
new_axes = copyobj(haxes, ftmp);
set(new_axes,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
saveas(ftmp, FileName);
delete(ftmp);
delete(fh);

Related

Writing Macro in ImageJ to open, change color, adjust brightness and resave microscope images

I'm trying to write a code in Image J that will:
Open all images in separate windows that contains "488" within a folder
Use look up tables to convert images to green and RGB color From ImageJ, the commands are: run("Green"); and run("RGB Color");
Adjust the brightness and contrast with defined values for Min and Max (same values for each image).
I know that the code for that is:
//run("Brightness/Contrast..."); setMinAndMax(value min, value max); run("Apply LUT");
Save each image in the same, original folder , in Tiff and with the same name but finishing with "processed".
I have no experience with Java and am very bad with coding. I tried to piece something together using code I found on stackoverflow and on the ImageJ website, but kept getting error codes. Any help is much appreciated!
I don't know if you still need it, but here is an example.
output_dir = "C:/Users/test/"
input_dir = "C:/Users/test/"
list = getFileList(input_dir);
listlength = list.length;
setBatchMode(true);
for (z = 0; z < listlength; z++){
if(endsWith(list[z], 'tif')==true ){
if(list[z].contains("488")){
title = list[z];
end = lengthOf(title)-4;
out_path = output_dir + substring(title,0,end) + "_processed.tif";
open(input_dir + title);
//add all the functions you want
run("Brightness/Contrast...");
setMinAndMax(1, 15);
run("Apply LUT");
saveAs("tif", "" + out_path + "");
close();
};
run("Close All");
}
}
setBatchMode(false);
I think it contains all the things you need. It opens all the images (in specific folder) that ends with tif and contains 488. I didn't completely understand what you want to do with each photo, so I just added your functions. But you probably won't have problems with adding more/different since you can get them with macro recorder.
And the code is written to open tif files. If you have tiff just be cerful that you change that and also change -4 to -5.

matlab imwrite new image instead of overriding it

I have function that checks for bottle cap. If there is no cap detected, it writes it as an image into folder. My problem is that if I pass different image, the old one get overridden with new one, is there a way to make new image instead of overwriting old one such as nocap0,jpg, then new one nocap1.jpg etc?
Code:
function [ ] = CHECK_FOR_CAP( image )
%crop loaction of cap
imageCROP = imcrop(image,[130 0 100 50]);
%turn to BW
imageBW=im2bw(imageCROP);
%count black pixels
answer = sum(sum(imageBW==0));
%if <250 black, save it to folder NOCAP
if answer<250
imwrite(image, 'TESTINGFOLDERS/NOCAP/nocap.jpg', 'jpg');
disp('NO CAP DETECTED');
end
UPDATE
I changed the code a bit now. Everytime I give a different image it now writes new one, BUT it overwrites the previous one aswell like so: http://imgur.com/a/KIuvg
My new code:
function [ ] = CHECK_FOR_CAP( image )
folder = 'TESTINGFOLDERS/NOCAP';
filePattern = fullfile(folder, '/*.*');
ImageFiles = dir(filePattern);
%crop loaction of cap
imageCROP = imcrop(image,[130 0 100 50]);
%turn to BW
imageBW=im2bw(imageCROP);
%count black pixels
answer = sum(sum(imageBW==0));
%if <250 black, save it to folder NOCAP
if answer<250
a = length(ImageFiles)-1;
for j = 1:a
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if exist(filename,'file')
imwrite(image,filename);
end
imwrite(image, fullfile(filename));
end
disp('NO CAP DETECTED');
end
You write
for j = 1:a
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if exist(filename,'file')
imwrite(image,filename);
end
imwrite(image, fullfile(filename));
end
This means that whenever you find a file, you overwrite it. Then you overwrite it again. You do this for as many files as exist (a comes from some dir you do on your folder). What you want is the opposite: find one that does not exist. Something like this:
j = 0;
while true
j = j + 1;
baseFileName = [num2str(j),'.jpg'];
filename = fullfile(folder,baseFileName);
if ~exist(filename,'file')
break
end
end
imwrite(image, fullfile(filename));
This could be further shortened (e.g., by looping while exist(...)) but it conveys the idea...

Using MATLAB to save a montage of many images as one large image file at full resolution

I am trying to save a montage of many (~500, 2MB each) images using MATLAB function imwrite, however I keep getting this error:
Error using imwrite>validateSizes (line 632)
Images must contain fewer than 2^32 - 1 bytes of data.
Error in imwrite (line 463)
validateSizes(data);
here is the code I am working with:
close all
clear all
clc
tic
file = 'ImageRegistrations.txt';
info = importdata(file);
ImageNames = info.textdata(:,1);
xoffset = info.data(:,1);
yoffset = info.data(:,2);
for i = 1:length(ImageNames);
ImageNames{i,1} = imread(ImageNames{i,1});
ImageNames{i,1} = flipud(ImageNames{i,1});
end
ImageNames = flipud(ImageNames);
for i=1:length(ImageNames)
diffx(i) = xoffset(length(ImageNames),1) - xoffset(i,1);
end
diffx = (diffx)';
diffx = flipud(diffx);
for j=1:length(ImageNames)
diffy(j) = yoffset(length(ImageNames),1) - yoffset(j,1);
end
diffy = (diffy)';
diffy = flipud(diffy);
matrix = zeros(max(diffy)+abs(min(diffy))+(2*1004),max(diffx)+abs(min(diffx))+(2*1002));
%matrix(1:size(ImageNames{1,1},1),1:size(ImageNames{1,1},2)) = ImageNames{1,1};
for q=1:length(ImageNames)
matrix((diffy(q)+abs(min(diffy))+1):(diffy(q)+abs(min(diffy))+size(ImageNames{q,1},1)),(diffx(q)+abs(min(diffx))+1):((diffx(q)+abs(min(diffx))+size(ImageNames{q,1},2)))) = ImageNames{q,1};
end
graymatrix = mat2gray(matrix);
graymatrix = flipud(graymatrix);
figure(2)
imshow(graymatrix)
imwrite(graymatrix, 'montage.tif')
toc
I use imwrite because it perserves the final montage in a full resolution file, whereas if I simply click save on the figure file it saves it as a low resolution file.
thanks!
Error does what it says on the tin, really. There is some sort of inbuilt limitation to input variable size in imwrite, and you're going over it.
Note that most images are stored as uint8 but I would guess that you end up with doubles as a result of your processing. That increases the memory usage.
It may be, therefore, that casting to another type would help. Try using im2uint8 (presuming your variable graymatrix is double, scaled between 0 and 1), before calling imwrite.

Wand equivalent of ImageMagick "convert -append"

I would like to write the equivalent of
convert left.jpg right.jpg +append ouput.jpg
I found something like it in another post:
files = glob('*.jpg')
with Image() as orig: # create empty Image object
for f in files:
page = Image(filename=f)
orig.sequence.append(page)
orig.save(filename='result.pdf')
and changed it to
with Image() as orig: # create empty Image object
page = Image(filename='left.jpg'); orig.sequence.append(page)
page = Image(filename='right.jpg'); orig.sequence.append(page)
orig.save(filename='output.jpg')
but the output file just shows the first file, rather than a file with the images side-by-side.
My first attempt was completely wrong, it probably makes an animated image. Provided the two images are the same size, this will do it:
with Image() as blankimage:
with Image(filename = 'imageA.tif') as imageA:
w = imageA.width; h = imageA.height
with Image(filename = 'imageB.tif') as imageB:
blankimage.blank(w*2, h)
blankimage.composite(imageA, 0, 0)
blankimage.composite(imageB, w, 0)
blankimage.save(filename = 'output.tif')

Making a gif from images

I have a load of data in 100 .sdf files (labelled 0000.sdf to 0099.sdf), each of which contain a still image, and I'm trying to produce a .gif from these images.
The code I use to plot the figure are (in the same directory as the sdf files):
q = GetDataSDF('0000.sdf');
imagesc(q.data');
I've attempted to write a for loop that would plot the figure and then save it with the same filename as the sdf file but to no avail, using:
for a = 1:100
q=GetDataSDF('0000.sdf');
fh = imagesc(q.dist_fn.x_px.Left.data');
frm = getframe( fh );
% save as png image
saveas(fh, 'current_frame_%02d.jpg');
end
EDIT: I received the following errors when trying to run this code:
Error using hg.image/get
The name 'Units' is not an accessible property for an instance of class 'image'.
Error in getframe>Local_getRectanglesOfInterest (line 138)
if ~strcmpi(get(h, 'Units'), 'Pixels')
Error in getframe (line 56)
[offsetRect, absoluteRect, figPos, figOuterPos] = ...
Error in loop_code (line 4)
frm = getframe( fh );
How do I save these files using a for loop, and how do I then use those files to produce a movie?
The reason for the error is that you pass an image handle to getframe, but this function excpects a figure handle.
Another problem is that you always load the same file, and that you saveas will not work for gifs. (For saving figures as static images, maybe print is the better option?)
I tried to modify my own gif-writing loop so that it works with your data. I'll try to be extra explicit in the comments, since you seem to be starting out. Remember, you can always use help name_of_command to display a short Matlab help.
% Define a variable that holds the frames per second your "movie" should have
gif_fps = 24;
% Define string variable that holds the filename of your movie
video_filename = 'video.gif';
% Create figure 1, store the handle in a variable, you'll need it later
fh = figure(1);
for a = 0:99
% Prepare file name so that you loop over the data
q = GetDataSDF(['00' num2str(a,'%02d') 'sdf']);
% Plot image
imagesc(q.dist_fn.x_px.Left.data');
% Force Matlab to actually do the plot (it sometimes gets lazy in loops)
drawnow;
% Take a "screenshot" of the figure fh
frame = getframe(fh);
% Turn screenshot into image
im = frame2im(frame);
% Turn image into indexed image (the gif format needs this)
[imind,cm] = rgb2ind(im,256);
% If first loop iteration: Create the file, else append to it
if a == 0;
imwrite(imind,cm,video_filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,video_filename,'gif','WriteMode','append','DelayTime',1/gif_fps);
end
end
One more note: When the size of the data is the same for each plot, it makes sense to only use the plot(or in this case, imagesc) command once, and in later loop iterations replace it with a set(ah,'Ydata',new_y_data) (or in this case set(ah,'CData',q.dist_fn.x_px.Left.data'), where ah is a handle of the plot axes (not the plot figure!). This is orders of magnitude faster than creating a whole new plot in each loop iteration. The downside is that the scaling (here, the color-scaling) will be the same for each plot. But in every case that I have worked on so far, that was actually desirable.

Resources