diff --git a/Graph/checkMooringPlannedDepths.m b/Graph/checkMooringPlannedDepths.m index 434c517d0..df83faddd 100644 --- a/Graph/checkMooringPlannedDepths.m +++ b/Graph/checkMooringPlannedDepths.m @@ -191,16 +191,17 @@ function checkMooringPlannedDepths(sample_data, isQC, saveToFile, exportDir) %now plot all the calculated depths on one plot to choose region for comparison: %plot fileName = genIMOSFileName(sample_data{1}, 'png'); -visible = 'on'; -if saveToFile, visible = 'off'; end hFigPress = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); -hAxPress = subplot(2,1,1,'Parent', hFigPress); -hAxDepthDiff = subplot(2,1,2,'Parent', hFigPress); +% create uipanel within figure so that screencapture can be +% used on the plot only and without capturing all of the figure +% (including buttons, menus...) +hPanelMooringVar = uipanel('Parent', hFigPress); +hAxPress = subplot(2,1,1,'Parent', hPanelMooringVar); +hAxDepthDiff = subplot(2,1,2,'Parent', hPanelMooringVar); %depth plot for selecting region to compare depth to planned depth set(hAxPress, 'YDir', 'reverse') @@ -313,21 +314,11 @@ function checkMooringPlannedDepths(sample_data, isQC, saveToFile, exportDir) if isPlottable if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigPress, 'PaperPositionMode', 'manual'); - set(hFigPress, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigPress, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_LINE_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigPress, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigPress, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigPress); end end diff --git a/Graph/checkMooringPresDiffs.m b/Graph/checkMooringPresDiffs.m index fbd381bdb..802d0dc57 100644 --- a/Graph/checkMooringPresDiffs.m +++ b/Graph/checkMooringPresDiffs.m @@ -140,16 +140,18 @@ function checkMooringPresDiffs(sample_data, iSampleMenu, isQC, saveToFile, expor %plot fileName = genIMOSFileName(sample_data{iCurrSam}, 'png'); -visible = 'on'; -if saveToFile, visible = 'off'; end hFigPressDiff = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); +% create uipanel within figure so that screencapture can be +% used on the plot only and without capturing all of the figure +% (including buttons, menus...) +hPanelMooringVar = uipanel('Parent', hFigPressDiff); + %pressure plot -hAxPress = subplot(2,1,1,'Parent', hFigPressDiff); +hAxPress = subplot(2,1,1,'Parent', hPanelMooringVar); set(hAxPress, 'YDir', 'reverse') set(get(hAxPress, 'XLabel'), 'String', 'Time'); set(get(hAxPress, 'YLabel'), 'String', [presRelCode ' (' varUnit ')'], 'Interpreter', 'none'); @@ -159,7 +161,7 @@ function checkMooringPresDiffs(sample_data, iSampleMenu, isQC, saveToFile, expor hold(hAxPress, 'on'); %Pressure diff plot -hAxPressDiff = subplot(2,1,2,'Parent', hFigPressDiff); +hAxPressDiff = subplot(2,1,2,'Parent', hPanelMooringVar); set(get(hAxPressDiff, 'XLabel'), 'String', 'Time'); set(get(hAxPressDiff, 'YLabel'), 'String', [presRelCode ' (' varUnit ')'], 'Interpreter', 'none'); set(get(hAxPressDiff, 'Title'), 'String', ... @@ -329,21 +331,11 @@ function checkMooringPresDiffs(sample_data, iSampleMenu, isQC, saveToFile, expor set(hAxPress, 'Position', posAx); if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigPressDiff, 'PaperPositionMode', 'manual'); - set(hFigPressDiff, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigPressDiff, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_LINE_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigPressDiff, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigPressDiff, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigPressDiff); end end diff --git a/Graph/lineCastVar.m b/Graph/lineCastVar.m index d90d676fc..fae12ed2a 100644 --- a/Graph/lineCastVar.m +++ b/Graph/lineCastVar.m @@ -127,19 +127,21 @@ function lineCastVar(sample_data, varNames, isQC, saveToFile, exportDir) if iVar > 0 if initiateFigure fileName = genIMOSFileName(sample_data{i}, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigCastVar = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelCastVar = uipanel('Parent', hFigCastVar); + initiateFigure = false; end if i==1 - hAxCastVar = subplot(1, lenVarNames, k); + hAxCastVar = subplot(1, lenVarNames, k, 'Parent', hPanelCastVar); set(hAxCastVar, 'YDir', 'reverse'); set(get(hAxCastVar, 'Title'), 'String', title, 'Interpreter', 'none'); set(get(hAxCastVar, 'XLabel'), 'String', varName, 'Interpreter', 'none'); @@ -303,20 +305,9 @@ function lineCastVar(sample_data, varNames, isQC, saveToFile, exportDir) end if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigCastVar, 'PaperPositionMode', 'manual'); - set(hFigCastVar, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigCastVar, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PLOT-TYPE_', '_LINE_'); % IMOS_[sub-facility_code]_[platform_code]_FV01_[time_coverage_start]_[PLOT-TYPE]_C-[creation_date].png - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigCastVar, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigCastVar, hPanelCastVar, fullfile(exportDir, fileName)); close(hFigCastVar); end diff --git a/Graph/lineMooring1DVar.m b/Graph/lineMooring1DVar.m index d6332e9bc..e9f8f0015 100644 --- a/Graph/lineMooring1DVar.m +++ b/Graph/lineMooring1DVar.m @@ -145,15 +145,17 @@ function lineMooring1DVar(sample_data, varName, isQC, saveToFile, exportDir) all(~strncmpi(sample_data{iSort(i)}.variables{iVar}.name, {'UCUR', 'VCUR', 'WCUR', 'CDIR', 'CSPD', 'VEL1', 'VEL2', 'VEL3'}, 4)) if initiateFigure fileName = genIMOSFileName(sample_data{iSort(i)}, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigMooringVar = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); - hAxMooringVar = axes('Parent', hFigMooringVar); + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelMooringVar = uipanel('Parent', hFigMooringVar); + hAxMooringVar = axes('Parent', hPanelMooringVar); + if any(strcmpi(varName, {'DEPTH', 'PRES', 'PRES_REL'})), set(hAxMooringVar, 'YDir', 'reverse'); end set(get(hAxMooringVar, 'XLabel'), 'String', 'Time'); set(get(hAxMooringVar, 'YLabel'), 'String', [varName ' (' varUnit ')'], 'Interpreter', 'none'); @@ -288,21 +290,11 @@ function lineMooring1DVar(sample_data, varName, isQC, saveToFile, exportDir) end if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigMooringVar, 'PaperPositionMode', 'manual'); - set(hFigMooringVar, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigMooringVar, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_LINE_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigMooringVar, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigMooringVar, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigMooringVar); end end diff --git a/Graph/lineMooring2DVarSection.m b/Graph/lineMooring2DVarSection.m index 632710c2d..5f65bd3af 100644 --- a/Graph/lineMooring2DVarSection.m +++ b/Graph/lineMooring2DVarSection.m @@ -117,23 +117,25 @@ function lineMooring2DVarSection(sample_data, varName, timeValue, isQC, saveToFi if iVar > 0 if initiateFigure fileName = genIMOSFileName(sample_data, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigVarSection = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelVarSection = uipanel('Parent', hFigVarSection); + initiateFigure = false; end - hAxCastVar = axes; - set(get(hAxCastVar, 'Title'), 'String', title, 'Interpreter', 'none'); - set(get(hAxCastVar, 'XLabel'), 'String', [varTitle ' (' varUnit ')'], 'Interpreter', 'none'); - set(get(hAxCastVar, 'YLabel'), 'String', [dimTitle ' (' dimUnit ')'], 'Interpreter', 'none'); + hAxVarSection = axes('Parent', hPanelVarSection); + set(get(hAxVarSection, 'Title'), 'String', title, 'Interpreter', 'none'); + set(get(hAxVarSection, 'XLabel'), 'String', [varTitle ' (' varUnit ')'], 'Interpreter', 'none'); + set(get(hAxVarSection, 'YLabel'), 'String', [dimTitle ' (' dimUnit ')'], 'Interpreter', 'none'); - hold(hAxCastVar, 'on'); + hold(hAxVarSection, 'on'); % dummy entry for first entry in legend hLineVar(1) = plot(0, 0, 'o', 'color', backgroundColor, 'Visible', 'off'); % color grey same as background (invisible) @@ -145,8 +147,8 @@ function lineMooring2DVarSection(sample_data, varName, timeValue, isQC, saveToFi yLine, ... 'LineStyle', '-'); - xLim = get(hAxCastVar, 'XLim'); - yLim = get(hAxCastVar, 'YLim'); + xLim = get(hAxVarSection, 'XLim'); + yLim = get(hAxVarSection, 'YLim'); %get var QC information varFlags = sample_data.variables{iVar}.flags(iX); @@ -238,13 +240,13 @@ function lineMooring2DVarSection(sample_data, varName, timeValue, isQC, saveToFi % Let's redefine properties after line to make sure grid lines appear % above color data and XTick and XTickLabel haven't changed - set(hAxCastVar, ... + set(hAxVarSection, ... 'XGrid', 'on', ... 'YGrid', 'on', ... 'Layer', 'top'); % set background to be grey - set(hAxCastVar, 'Color', backgroundColor) + set(hAxVarSection, 'Color', backgroundColor) end if ~initiateFigure @@ -258,7 +260,7 @@ function lineMooring2DVarSection(sample_data, varName, timeValue, isQC, saveToFi instrumentDesc = [instrumentDesc; flagDesc]; % Matlab >R2015 legend entries for data which are not plotted % will be shown with reduced opacity - hLegend = legend(hAxCastVar, ... + hLegend = legend(hAxVarSection, ... hLineVar, regexprep(instrumentDesc,'_','\_'), ... 'Interpreter', 'none', ... 'Location', 'SouthOutside'); @@ -266,20 +268,9 @@ function lineMooring2DVarSection(sample_data, varName, timeValue, isQC, saveToFi end if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigVarSection, 'PaperPositionMode', 'manual'); - set(hFigVarSection, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigVarSection, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PLOT-TYPE_', '_LINE_'); % IMOS_[sub-facility_code]_[platform_code]_FV01_[time_coverage_start]_[PLOT-TYPE]_C-[creation_date].png - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigVarSection, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigVarSection, hPanelVarSection, fullfile(exportDir, fileName)); close(hFigVarSection); end diff --git a/Graph/pcolorMooring2DVar.m b/Graph/pcolorMooring2DVar.m index 762e174d3..b717b2550 100644 --- a/Graph/pcolorMooring2DVar.m +++ b/Graph/pcolorMooring2DVar.m @@ -144,28 +144,17 @@ function pcolorMooring2DVar(sample_data, varName, isQC, saveToFile, exportDir) size(sample_data{iSort(i)}.variables{iVar}.data, 3) == 1 % we're only plotting ADCP 2D variables if initiateFigure fileName = genIMOSFileName(sample_data{iSort(i)}, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigMooringVar = figure(... 'Name', title, ... 'NumberTitle', 'off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); - if saveToFile - % the default renderer under windows is opengl; for some reason, - % printing pcolor plots fails when using opengl as the renderer - set(hFigMooringVar, 'Renderer', 'zbuffer'); - - % ensure the printed version is the same whatever the screen used. - set(hFigMooringVar, 'PaperPositionMode', 'manual'); - set(hFigMooringVar, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigMooringVar, 'InvertHardcopy', 'off'); - end + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelMooringVar = uipanel('Parent', hFigMooringVar); + hAxMooringVar = axes('Parent', hPanelMooringVar); - hAxMooringVar = axes('Parent', hFigMooringVar); set(get(hAxMooringVar, 'XLabel'), 'String', 'Time'); set(get(hAxMooringVar, 'YLabel'), 'String', [nameHeight ' (m)'], 'Interpreter', 'none'); set(get(hAxMooringVar, 'Title'), 'String', sprintf('%s\n%s', title, instrumentDesc{i}), 'Interpreter', 'none'); @@ -261,11 +250,8 @@ function pcolorMooring2DVar(sample_data, varName, isQC, saveToFile, exportDir) fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_PCOLOR_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigMooringVar, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigMooringVar, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigMooringVar); end end diff --git a/Graph/scatterMooring1DVarAgainstDepth.m b/Graph/scatterMooring1DVarAgainstDepth.m index 34d3f95e7..9337545e6 100644 --- a/Graph/scatterMooring1DVarAgainstDepth.m +++ b/Graph/scatterMooring1DVarAgainstDepth.m @@ -190,15 +190,17 @@ function scatterMooring1DVarAgainstDepth(sample_data, varName, isQC, saveToFile, if isPlottable(i) if initiateFigure fileName = genIMOSFileName(sample_data{iSort(i)}, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigMooringVar = figure(... 'Name', title, ... 'NumberTitle','off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); - hAxMooringVar = axes('Parent', hFigMooringVar); + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelMooringVar = uipanel('Parent', hFigMooringVar); + hAxMooringVar = axes('Parent', hPanelMooringVar); + set(hAxMooringVar, 'YDir', 'reverse'); set(get(hAxMooringVar, 'XLabel'), 'String', 'Time'); set(get(hAxMooringVar, 'YLabel'), 'String', 'DEPTH (m)', 'Interpreter', 'none'); @@ -415,21 +417,11 @@ function scatterMooring1DVarAgainstDepth(sample_data, varName, isQC, saveToFile, % set(hLegend, 'Box', 'off', 'Color', 'none'); if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigMooringVar, 'PaperPositionMode', 'manual'); - set(hFigMooringVar, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigMooringVar, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_SCATTER_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigMooringVar, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigMooringVar, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigMooringVar); end end diff --git a/Graph/scatterMooring2DVarAgainstDepth.m b/Graph/scatterMooring2DVarAgainstDepth.m index 92b180f83..836ae4e2e 100644 --- a/Graph/scatterMooring2DVarAgainstDepth.m +++ b/Graph/scatterMooring2DVarAgainstDepth.m @@ -259,15 +259,17 @@ function scatterMooring2DVarAgainstDepth(sample_data, varName, isQC, saveToFile, if isPlottable(i) if initiateFigure fileName = genIMOSFileName(sample_data{iSort(i)}, 'png'); - visible = 'on'; - if saveToFile, visible = 'off'; end hFigMooringVar = figure(... 'Name', title, ... 'NumberTitle', 'off', ... - 'Visible', visible, ... 'OuterPosition', monitorRect(iBigMonitor, :)); - hAxMooringVar = axes('Parent', hFigMooringVar); + % create uipanel within figure so that screencapture can be + % used on the plot only and without capturing all of the figure + % (including buttons, menus...) + hPanelMooringVar = uipanel('Parent', hFigMooringVar); + hAxMooringVar = axes('Parent', hPanelMooringVar); + set(hAxMooringVar, 'YDir', 'reverse'); set(get(hAxMooringVar, 'XLabel'), 'String', 'Time'); set(get(hAxMooringVar, 'YLabel'), 'String', 'DEPTH (m)', 'Interpreter', 'none'); @@ -489,21 +491,11 @@ function scatterMooring2DVarAgainstDepth(sample_data, varName, isQC, saveToFile, % set(hLegend, 'Box', 'off', 'Color', 'none'); if saveToFile - % ensure the printed version is the same whatever the screen used. - set(hFigMooringVar, 'PaperPositionMode', 'manual'); - set(hFigMooringVar, 'PaperType', 'A4', 'PaperOrientation', 'landscape', 'PaperUnits', 'normalized', 'PaperPosition', [0, 0, 1, 1]); - - % preserve the color scheme - set(hFigMooringVar, 'InvertHardcopy', 'off'); - fileName = strrep(fileName, '_PARAM_', ['_', varName, '_']); % IMOS_[sub-facility_code]_[site_code]_FV01_[deployment_code]_[PLOT-TYPE]_[PARAM]_C-[creation_date].png fileName = strrep(fileName, '_PLOT-TYPE_', '_SCATTER_'); - % use hardcopy as a trick to go faster than print. - % opengl (hardware or software) should be supported by any platform and go at least just as - % fast as zbuffer. With hardware accelaration supported, could even go a - % lot faster. - imwrite(hardcopy(hFigMooringVar, '-dopengl'), fullfile(exportDir, fileName), 'png'); + fastSaveas(hFigMooringVar, hPanelMooringVar, fullfile(exportDir, fileName)); + close(hFigMooringVar); end end diff --git a/Parser/infinitySDLoggerParse.m b/Parser/infinitySDLoggerParse.m index a8f894806..5d15f5b85 100644 --- a/Parser/infinitySDLoggerParse.m +++ b/Parser/infinitySDLoggerParse.m @@ -58,7 +58,7 @@ fclose(fid); [header, iData] = readHeader(rawText{1}); - data = readData(filename, iData); + data = readData(rawText{1}(iData:end)); catch e if fid ~= -1, fclose(fid); end rethrow(e); @@ -134,39 +134,41 @@ nFields = length(headerCell); for i=1:nFields tuple = textscan(headerCell{i}, fmtHeader, 'Delimiter', delimHeader); - header.(tuple{1}{1}) = tuple{2}{1}; + if ~isempty(tuple{2}) + header.(tuple{1}{1}) = tuple{2}{1}; + end end end -function data = readData(filename, iData) +function data = readData(rawTextData) %READDATA Reads the sample data from the file. data = struct; dataDelim = ','; - fid = fopen(filename, 'rt'); - params = textscan(fid, '%s', 1, 'HeaderLines', iData, 'Delimiter', ''); - params = params{1}; + params = rawTextData{2}; iParams = strfind(params, ','); - nParams = length(iParams{1}); + nParams = length(iParams); paramsFmt = repmat('%s', 1, nParams); - params = textscan(params{1}, paramsFmt, 'Delimiter', dataDelim); + params = textscan(params, paramsFmt, 'Delimiter', dataDelim); dataFmt = ['%s', repmat('%f', 1, nParams-1)]; - values = textscan(fid, dataFmt, 'Delimiter', dataDelim); - fclose(fid); + + nData = length(rawTextData(3:end)); + values = cellfun(@textscan, rawTextData(3:end), repmat({dataFmt}, nData, 1), repmat({'Delimiter'}, nData, 1), repmat({dataDelim}, nData, 1), 'UniformOutput', false); + values = vertcat(values{:}); for i=1:nParams switch params{i}{1} - case 'Date' - data.TIME.values = datenum(values{i}, 'yyyy/mm/dd HH:MM:SS'); + case {'Date', 'Meas date'} + data.TIME.values = datenum(vertcat(values{:,i}), 'yyyy/mm/dd HH:MM:SS'); data.TIME.comment = ''; - case 'Temp.[deg C]' - data.TEMP.values = values{i}; + case {'Temp.[deg C]', 'Temp.[degC]'} + data.TEMP.values = vertcat(values{:,i}); data.TEMP.comment = ''; case 'Chl-a[ug/l]' - data.CPHL.values = values{i}; + data.CPHL.values = vertcat(values{:,i}); data.CPHL.comment = ['Artificial chlorophyll data '... 'computed from bio-optical sensor raw counts measurements. The '... 'fluorometre is equipped with a 470nm peak wavelength LED to irradiate and a '... @@ -174,8 +176,8 @@ 'that fluoresces in the region of 650nm to 1000nm. '... 'Originally expressed in ug/l, 1l = 0.001m3 was assumed.']; - case 'Turb. -M[FTU]' - data.TURBF.values = values{i}; + case {'Turb. -M[FTU]', 'Turb.-M[FTU]'} + data.TURBF.values = vertcat(values{:,i}); data.TURBF.comment = ['Turbidity data '... 'computed from bio-optical sensor raw counts measurements. The '... 'turbidity sensor is equipped with a 880nm peak wavelength LED to irradiate and a '... @@ -183,7 +185,7 @@ 'that backscatters in the region of 650nm to 1000nm.']; case 'Batt.[V]' - data.VOLT.values = values{i}; + data.VOLT.values = vertcat(values{:,i}); data.VOLT.comment = ''; end diff --git a/ScreenCapture/ImageSelection.class b/ScreenCapture/ImageSelection.class new file mode 100644 index 000000000..cfac41d4d Binary files /dev/null and b/ScreenCapture/ImageSelection.class differ diff --git a/ScreenCapture/ImageSelection.java b/ScreenCapture/ImageSelection.java new file mode 100644 index 000000000..7ec32fd34 --- /dev/null +++ b/ScreenCapture/ImageSelection.java @@ -0,0 +1,38 @@ +/* + * Based on code snippet from + * http://java.sun.com/developer/technicalArticles/releases/data/ + * + * Copyright © 2008, 2010 Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. + */ + +import java.awt.image.BufferedImage; +import java.awt.datatransfer.*; + +public class ImageSelection implements Transferable { + + private static final DataFlavor flavors[] = + {DataFlavor.imageFlavor}; + + private BufferedImage image; + + public ImageSelection(BufferedImage image) { + this.image = image; + } + + // Transferable + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { + if (flavor.equals(flavors[0]) == false) { + throw new UnsupportedFlavorException(flavor); + } + return image; + } + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor + flavor) { + return flavor.equals(flavors[0]); + } +} \ No newline at end of file diff --git a/ScreenCapture/ScreenCapture.png b/ScreenCapture/ScreenCapture.png new file mode 100644 index 000000000..6326e7669 Binary files /dev/null and b/ScreenCapture/ScreenCapture.png differ diff --git a/ScreenCapture/license.txt b/ScreenCapture/license.txt new file mode 100644 index 000000000..8c25c7845 --- /dev/null +++ b/ScreenCapture/license.txt @@ -0,0 +1,24 @@ +Copyright (c) 2016, Yair Altman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/ScreenCapture/screencapture.m b/ScreenCapture/screencapture.m new file mode 100644 index 000000000..9ee657c26 --- /dev/null +++ b/ScreenCapture/screencapture.m @@ -0,0 +1,820 @@ +function imageData = screencapture(varargin) +% screencapture - get a screen-capture of a figure frame, component handle, or screen area rectangle +% +% ScreenCapture gets a screen-capture of any Matlab GUI handle (including desktop, +% figure, axes, image or uicontrol), or a specified area rectangle located relative to +% the specified handle. Screen area capture is possible by specifying the root (desktop) +% handle (=0). The output can be either to an image file or to a Matlab matrix (useful +% for displaying via imshow() or for further processing) or to the system clipboard. +% This utility also enables adding a toolbar button for easy interactive screen-capture. +% +% Syntax: +% imageData = screencapture(handle, position, target, 'PropName',PropValue, ...) +% +% Input Parameters: +% handle - optional handle to be used for screen-capture origin. +% If empty/unsupplied then current figure (gcf) will be used. +% position - optional position array in pixels: [x,y,width,height]. +% If empty/unsupplied then the handle's position vector will be used. +% If both handle and position are empty/unsupplied then the position +% will be retrieved via interactive mouse-selection. +% If handle is an image, then position is in data (not pixel) units, so the +% captured region remains the same after figure/axes resize (like imcrop) +% target - optional filename for storing the screen-capture, or the +% 'clipboard'/'printer' strings. +% If empty/unsupplied then no output to file will be done. +% The file format will be determined from the extension (JPG/PNG/...). +% Supported formats are those supported by the imwrite function. +% 'PropName',PropValue - +% optional list of property pairs (e.g., 'target','myImage.png','pos',[10,20,30,40],'handle',gca) +% PropNames may be abbreviated and are case-insensitive. +% PropNames may also be given in whichever order. +% Supported PropNames are: +% - 'handle' (default: gcf handle) +% - 'position' (default: gcf position array) +% - 'target' (default: '') +% - 'toolbar' (figure handle; default: gcf) +% this adds a screen-capture button to the figure's toolbar +% If this parameter is specified, then no screen-capture +% will take place and the returned imageData will be []. +% +% Output parameters: +% imageData - image data in a format acceptable by the imshow function +% If neither target nor imageData were specified, the user will be +% asked to interactively specify the output file. +% +% Examples: +% imageData = screencapture; % interactively select screen-capture rectangle +% imageData = screencapture(hListbox); % capture image of a uicontrol +% imageData = screencapture(0, [20,30,40,50]); % capture a small desktop region +% imageData = screencapture(gcf,[20,30,40,50]); % capture a small figure region +% imageData = screencapture(gca,[10,20,30,40]); % capture a small axes region +% imshow(imageData); % display the captured image in a matlab figure +% imwrite(imageData,'myImage.png'); % save the captured image to file +% img = imread('cameraman.tif'); +% hImg = imshow(img); +% screencapture(hImg,[60,35,140,80]); % capture a region of an image +% screencapture(gcf,[],'myFigure.jpg'); % capture the entire figure into file +% screencapture(gcf,[],'clipboard'); % capture the entire figure into clipboard +% screencapture(gcf,[],'printer'); % print the entire figure +% screencapture('handle',gcf,'target','myFigure.jpg'); % same as previous, save to file +% screencapture('handle',gcf,'target','clipboard'); % same as previous, copy to clipboard +% screencapture('handle',gcf,'target','printer'); % same as previous, send to printer +% screencapture('toolbar',gcf); % adds a screen-capture button to gcf's toolbar +% screencapture('toolbar',[],'target','sc.bmp'); % same with default output filename +% +% Technical description: +% http://UndocumentedMatlab.com/blog/screencapture-utility/ +% +% Bugs and suggestions: +% Please send to Yair Altman (altmany at gmail dot com) +% +% See also: +% imshow, imwrite, print +% +% Release history: +% 1.17 2016-05-16: Fix annoying warning about JavaFrame property becoming obsolete someday (yes, we know...) +% 1.16 2016-04-19: Fix for deployed application suggested by Dwight Bartholomew +% 1.10 2014-11-25: Added the 'print' target +% 1.9 2014-11-25: Fix for saving GIF files +% 1.8 2014-11-16: Fixes for R2014b +% 1.7 2014-04-28: Fixed bug when capturing interactive selection +% 1.6 2014-04-22: Only enable image formats when saving to an unspecified file via uiputfile +% 1.5 2013-04-18: Fixed bug in capture of non-square image; fixes for Win64 +% 1.4 2013-01-27: Fixed capture of Desktop (root); enabled rbbox anywhere on desktop (not necesarily in a Matlab figure); enabled output to clipboard (based on Jiro Doke's imclipboard utility); edge-case fixes; added Java compatibility check +% 1.3 2012-07-23: Capture current object (uicontrol/axes/figure) if w=h=0 (e.g., by clicking a single point); extra input args sanity checks; fix for docked windows and image axes; include axes labels & ticks by default when capturing axes; use data-units position vector when capturing images; many edge-case fixes +% 1.2 2011-01-16: another performance boost (thanks to Jan Simon); some compatibility fixes for Matlab 6.5 (untested) +% 1.1 2009-06-03: Handle missing output format; performance boost (thanks to Urs); fix minor root-handle bug; added toolbar button option +% 1.0 2009-06-02: First version posted on MathWorks File Exchange + +% License to use and modify this code is granted freely to all interested, as long as the original author is +% referenced and attributed as such. The original author maintains the right to be solely associated with this work. + +% Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com +% $Revision: 1.17 $ $Date: 2016/05/16 17:59:36 $ + + % Ensure that java awt is enabled... + if ~usejava('awt') + error('YMA:screencapture:NeedAwt','ScreenCapture requires Java to run.'); + end + + % Ensure that our Java version supports the Robot class (requires JVM 1.3+) + try + robot = java.awt.Robot; %#ok + catch + uiwait(msgbox({['Your Matlab installation is so old that its Java engine (' version('-java') ... + ') does not have a java.awt.Robot class. '], ' ', ... + 'Without this class, taking a screen-capture is impossible.', ' ', ... + 'So, either install JVM 1.3 or higher, or use a newer Matlab release.'}, ... + 'ScreenCapture', 'warn')); + if nargout, imageData = []; end + return; + end + + % Process optional arguments + paramsStruct = processArgs(varargin{:}); + + % If toolbar button requested, add it and exit + if ~isempty(paramsStruct.toolbar) + + % Add the toolbar button + addToolbarButton(paramsStruct); + + % Return the figure to its pre-undocked state (when relevant) + redockFigureIfRelevant(paramsStruct); + + % Exit immediately (do NOT take a screen-capture) + if nargout, imageData = []; end + return; + end + + % Convert position from handle-relative to desktop Java-based pixels + [paramsStruct, msgStr] = convertPos(paramsStruct); + + % Capture the requested screen rectangle using java.awt.Robot + imgData = getScreenCaptureImageData(paramsStruct.position); + + % Return the figure to its pre-undocked state (when relevant) + redockFigureIfRelevant(paramsStruct); + + % Save image data in file or clipboard, if specified + if ~isempty(paramsStruct.target) + if strcmpi(paramsStruct.target,'clipboard') + if ~isempty(imgData) + imclipboard(imgData); + else + msgbox('No image area selected - not copying image to clipboard','ScreenCapture','warn'); + end + elseif strncmpi(paramsStruct.target,'print',5) % 'print' or 'printer' + if ~isempty(imgData) + hNewFig = figure('visible','off'); + imshow(imgData); + print(hNewFig); + delete(hNewFig); + else + msgbox('No image area selected - not printing screenshot','ScreenCapture','warn'); + end + else % real filename + if ~isempty(imgData) + imwrite(imgData,paramsStruct.target); + else + msgbox(['No image area selected - not saving image file ' paramsStruct.target],'ScreenCapture','warn'); + end + end + end + + % Return image raster data to user, if requested + if nargout + imageData = imgData; + + % If neither output formats was specified (neither target nor output data) + elseif isempty(paramsStruct.target) & ~isempty(imgData) %#ok ML6 + % Ask the user to specify a file + %error('YMA:screencapture:noOutput','No output specified for ScreenCapture: specify the output filename and/or output data'); + %format = '*.*'; + formats = imformats; + for idx = 1 : numel(formats) + ext = sprintf('*.%s;',formats(idx).ext{:}); + format(idx,1:2) = {ext(1:end-1), formats(idx).description}; %#ok + end + [filename,pathname] = uiputfile(format,'Save screen capture as'); + if ~isequal(filename,0) & ~isequal(pathname,0) %#ok Matlab6 compatibility + try + filename = fullfile(pathname,filename); + imwrite(imgData,filename); + catch % possibly a GIF file that requires indexed colors + [imgData,map] = rgb2ind(imgData,256); + imwrite(imgData,map,filename); + end + else + % TODO - copy to clipboard + end + end + + % Display msgStr, if relevant + if ~isempty(msgStr) + uiwait(msgbox(msgStr,'ScreenCapture')); + drawnow; pause(0.05); % time for the msgbox to disappear + end + + return; % debug breakpoint + +%% Process optional arguments +function paramsStruct = processArgs(varargin) + + % Get the properties in either direct or P-V format + [regParams, pvPairs] = parseparams(varargin); + + % Now process the optional P-V params + try + % Initialize + paramName = []; + paramsStruct = []; + paramsStruct.handle = []; + paramsStruct.position = []; + paramsStruct.target = ''; + paramsStruct.toolbar = []; + paramsStruct.wasDocked = 0; % no false available in ML6 + paramsStruct.wasInteractive = 0; % no false available in ML6 + + % Parse the regular (non-named) params in recption order + if ~isempty(regParams) & (isempty(regParams{1}) | ishandle(regParams{1}(1))) %#ok ML6 + paramsStruct.handle = regParams{1}; + regParams(1) = []; + end + if ~isempty(regParams) & isnumeric(regParams{1}) & (length(regParams{1}) == 4) %#ok ML6 + paramsStruct.position = regParams{1}; + regParams(1) = []; + end + if ~isempty(regParams) & ischar(regParams{1}) %#ok ML6 + paramsStruct.target = regParams{1}; + end + + % Parse the optional param PV pairs + supportedArgs = {'handle','position','target','toolbar'}; + while ~isempty(pvPairs) + + % Disregard empty propNames (may be due to users mis-interpretting the syntax help) + while ~isempty(pvPairs) & isempty(pvPairs{1}) %#ok ML6 + pvPairs(1) = []; + end + if isempty(pvPairs) + break; + end + + % Ensure basic format is valid + paramName = ''; + if ~ischar(pvPairs{1}) + error('YMA:screencapture:invalidProperty','Invalid property passed to ScreenCapture'); + elseif length(pvPairs) == 1 + if isempty(paramsStruct.target) + paramsStruct.target = pvPairs{1}; + break; + else + error('YMA:screencapture:noPropertyValue',['No value specified for property ''' pvPairs{1} '''']); + end + end + + % Process parameter values + paramName = pvPairs{1}; + if strcmpi(paramName,'filename') % backward compatibility + paramName = 'target'; + end + paramValue = pvPairs{2}; + pvPairs(1:2) = []; + idx = find(strncmpi(paramName,supportedArgs,length(paramName))); + if ~isempty(idx) + %paramsStruct.(lower(supportedArgs{idx(1)})) = paramValue; % incompatible with ML6 + paramsStruct = setfield(paramsStruct, lower(supportedArgs{idx(1)}), paramValue); %#ok ML6 + + % If 'toolbar' param specified, then it cannot be left empty - use gcf + if strncmpi(paramName,'toolbar',length(paramName)) & isempty(paramsStruct.toolbar) %#ok ML6 + paramsStruct.toolbar = getCurrentFig; + end + + elseif isempty(paramsStruct.target) + paramsStruct.target = paramName; + pvPairs = {paramValue, pvPairs{:}}; %#ok (more readable this way, although a bit less efficient...) + + else + supportedArgsStr = sprintf('''%s'',',supportedArgs{:}); + error('YMA:screencapture:invalidProperty','%s \n%s', ... + 'Invalid property passed to ScreenCapture', ... + ['Supported property names are: ' supportedArgsStr(1:end-1)]); + end + end % loop pvPairs + + catch + if ~isempty(paramName), paramName = [' ''' paramName '''']; end + error('YMA:screencapture:invalidProperty','Error setting ScreenCapture property %s:\n%s',paramName,lasterr); %#ok + end +%end % processArgs + +%% Convert position from handle-relative to desktop Java-based pixels +function [paramsStruct, msgStr] = convertPos(paramsStruct) + msgStr = ''; + try + % Get the screen-size for later use + screenSize = get(0,'ScreenSize'); + + % Get the containing figure's handle + hParent = paramsStruct.handle; + if isempty(paramsStruct.handle) + paramsStruct.hFigure = getCurrentFig; + hParent = paramsStruct.hFigure; + else + paramsStruct.hFigure = ancestor(paramsStruct.handle,'figure'); + end + + % To get the acurate pixel position, the figure window must be undocked + try + if strcmpi(get(paramsStruct.hFigure,'WindowStyle'),'docked') + set(paramsStruct.hFigure,'WindowStyle','normal'); + drawnow; pause(0.25); + paramsStruct.wasDocked = 1; % no true available in ML6 + end + catch + % never mind - ignore... + end + + % The figure (if specified) must be in focus + if ~isempty(paramsStruct.hFigure) & ishandle(paramsStruct.hFigure) %#ok ML6 + isFigureValid = 1; % no true available in ML6 + figure(paramsStruct.hFigure); + else + isFigureValid = 0; % no false available in ML6 + end + + % Flush all graphic events to ensure correct rendering + drawnow; pause(0.01); + + % No handle specified + wasPositionGiven = 1; % no true available in ML6 + if isempty(paramsStruct.handle) + + % Set default handle, if not supplied + paramsStruct.handle = paramsStruct.hFigure; + + % If position was not specified, get it interactively using RBBOX + if isempty(paramsStruct.position) + [paramsStruct.position, jFrameUsed, msgStr] = getInteractivePosition(paramsStruct.hFigure); %#ok jFrameUsed is unused + paramsStruct.wasInteractive = 1; % no true available in ML6 + wasPositionGiven = 0; % no false available in ML6 + end + + elseif ~ishandle(paramsStruct.handle) + % Handle was supplied - ensure it is a valid handle + error('YMA:screencapture:invalidHandle','Invalid handle passed to ScreenCapture'); + + elseif isempty(paramsStruct.position) + % Handle was supplied but position was not, so use the handle's position + paramsStruct.position = getPixelPos(paramsStruct.handle); + paramsStruct.position(1:2) = 0; + wasPositionGiven = 0; % no false available in ML6 + + elseif ~isnumeric(paramsStruct.position) | (length(paramsStruct.position) ~= 4) %#ok ML6 + % Both handle & position were supplied - ensure a valid pixel position vector + error('YMA:screencapture:invalidPosition','Invalid position vector passed to ScreenCapture: \nMust be a [x,y,w,h] numeric pixel array'); + end + + % Capture current object (uicontrol/axes/figure) if w=h=0 (single-click in interactive mode) + if paramsStruct.position(3)<=0 | paramsStruct.position(4)<=0 %#ok ML6 + %TODO - find a way to single-click another Matlab figure (the following does not work) + %paramsStruct.position = getPixelPos(ancestor(hittest,'figure')); + paramsStruct.position = getPixelPos(paramsStruct.handle); + paramsStruct.position(1:2) = 0; + paramsStruct.wasInteractive = 0; % no false available in ML6 + wasPositionGiven = 0; % no false available in ML6 + end + + % First get the parent handle's desktop-based Matlab pixel position + parentPos = [0,0,0,0]; + dX = 0; + dY = 0; + dW = 0; + dH = 0; + if ~isFigure(hParent) + % Get the reguested component's pixel position + parentPos = getPixelPos(hParent, 1); % no true available in ML6 + + % Axes position inaccuracy estimation + deltaX = 3; + deltaY = -1; + + % Fix for images + if isImage(hParent) % | (isAxes(hParent) & strcmpi(get(hParent,'YDir'),'reverse')) %#ok ML6 + + % Compensate for resized image axes + hAxes = get(hParent,'Parent'); + if all(get(hAxes,'DataAspectRatio')==1) % sanity check: this is the normal behavior + % Note 18/4/2013: the following fails for non-square images + %actualImgSize = min(parentPos(3:4)); + %dX = (parentPos(3) - actualImgSize) / 2; + %dY = (parentPos(4) - actualImgSize) / 2; + %parentPos(3:4) = actualImgSize; + + % The following should work for all types of images + actualImgSize = size(get(hParent,'CData')); + dX = (parentPos(3) - min(parentPos(3),actualImgSize(2))) / 2; + dY = (parentPos(4) - min(parentPos(4),actualImgSize(1))) / 2; + parentPos(3:4) = actualImgSize([2,1]); + %parentPos(3) = max(parentPos(3),actualImgSize(2)); + %parentPos(4) = max(parentPos(4),actualImgSize(1)); + end + + % Fix user-specified img positions (but not auto-inferred ones) + if wasPositionGiven + + % In images, use data units rather than pixel units + % Reverse the YDir + ymax = max(get(hParent,'YData')); + paramsStruct.position(2) = ymax - paramsStruct.position(2) - paramsStruct.position(4); + + % Note: it would be best to use hgconvertunits, but: + % ^^^^ (1) it fails on Matlab 6, and (2) it doesn't accept Data units + %paramsStruct.position = hgconvertunits(hFig, paramsStruct.position, 'Data', 'pixel', hParent); % fails! + xLims = get(hParent,'XData'); + yLims = get(hParent,'YData'); + xPixelsPerData = parentPos(3) / (diff(xLims) + 1); + yPixelsPerData = parentPos(4) / (diff(yLims) + 1); + paramsStruct.position(1) = round((paramsStruct.position(1)-xLims(1)) * xPixelsPerData); + paramsStruct.position(2) = round((paramsStruct.position(2)-yLims(1)) * yPixelsPerData + 2*dY); + paramsStruct.position(3) = round( paramsStruct.position(3) * xPixelsPerData); + paramsStruct.position(4) = round( paramsStruct.position(4) * yPixelsPerData); + + % Axes position inaccuracy estimation + if strcmpi(computer('arch'),'win64') + deltaX = 7; + deltaY = -7; + else + deltaX = 3; + deltaY = -3; + end + + else % axes/image position was auto-infered (entire image) + % Axes position inaccuracy estimation + if strcmpi(computer('arch'),'win64') + deltaX = 6; + deltaY = -6; + else + deltaX = 2; + deltaY = -2; + end + dW = -2*dX; + dH = -2*dY; + end + end + + %hFig = ancestor(hParent,'figure'); + hParent = paramsStruct.hFigure; + + elseif paramsStruct.wasInteractive % interactive figure rectangle + + % Compensate for 1px rbbox inaccuracies + deltaX = 2; + deltaY = -2; + + else % non-interactive figure + + % Compensate 4px figure boundaries = difference betweeen OuterPosition and Position + deltaX = -1; + deltaY = 1; + end + %disp(paramsStruct.position) % for debugging + + % Now get the pixel position relative to the monitor + figurePos = getPixelPos(hParent); + desktopPos = figurePos + parentPos; + + % Now convert to Java-based pixels based on screen size + % Note: multiple monitors are automatically handled correctly, since all + % ^^^^ Java positions are relative to the main monitor's top-left corner + javaX = desktopPos(1) + paramsStruct.position(1) + deltaX + dX; + javaY = screenSize(4) - desktopPos(2) - paramsStruct.position(2) - paramsStruct.position(4) + deltaY + dY; + width = paramsStruct.position(3) + dW; + height = paramsStruct.position(4) + dH; + paramsStruct.position = round([javaX, javaY, width, height]); + %paramsStruct.position + + % Ensure the figure is at the front so it can be screen-captured + if isFigureValid + figure(hParent); + drawnow; + pause(0.02); + end + catch + % Maybe root/desktop handle (root does not have a 'Position' prop so getPixelPos croaks + if isequal(double(hParent),0) % =root/desktop handle; handles case of hParent=[] + javaX = paramsStruct.position(1) - 1; + javaY = screenSize(4) - paramsStruct.position(2) - paramsStruct.position(4) - 1; + paramsStruct.position = [javaX, javaY, paramsStruct.position(3:4)]; + end + end +%end % convertPos + +%% Interactively get the requested capture rectangle +function [positionRect, jFrameUsed, msgStr] = getInteractivePosition(hFig) + msgStr = ''; + try + % First try the invisible-figure approach, in order to + % enable rbbox outside any existing figure boundaries + f = figure('units','pixel','pos',[-100,-100,10,10],'HitTest','off'); + drawnow; pause(0.01); + oldWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); + jf = get(handle(f),'JavaFrame'); + warning(oldWarn); + try + jWindow = jf.fFigureClient.getWindow; + catch + try + jWindow = jf.fHG1Client.getWindow; + catch + jWindow = jf.getFigurePanelContainer.getParent.getTopLevelAncestor; + end + end + com.sun.awt.AWTUtilities.setWindowOpacity(jWindow,0.05); %=nearly transparent (not fully so that mouse clicks are captured) + jWindow.setMaximized(1); % no true available in ML6 + jFrameUsed = 1; % no true available in ML6 + msg = {'Mouse-click and drag a bounding rectangle for screen-capture ' ... + ... %'or single-click any Matlab figure to capture the entire figure.' ... + }; + catch + % Something failed, so revert to a simple rbbox on a visible figure + try delete(f); drawnow; catch, end %Cleanup... + jFrameUsed = 0; % no false available in ML6 + msg = {'Mouse-click within any Matlab figure and then', ... + 'drag a bounding rectangle for screen-capture,', ... + 'or single-click to capture the entire figure'}; + end + uiwait(msgbox(msg,'ScreenCapture')); + + k = waitforbuttonpress; %#ok k is unused + %hFig = getCurrentFig; + %p1 = get(hFig,'CurrentPoint'); + positionRect = rbbox; + %p2 = get(hFig,'CurrentPoint'); + + if jFrameUsed + jFrameOrigin = getPixelPos(f); + delete(f); drawnow; + try + figOrigin = getPixelPos(hFig); + catch % empty/invalid hFig handle + figOrigin = [0,0,0,0]; + end + else + if isempty(hFig) + jFrameOrigin = getPixelPos(gcf); + else + jFrameOrigin = [0,0,0,0]; + end + figOrigin = [0,0,0,0]; + end + positionRect(1:2) = positionRect(1:2) + jFrameOrigin(1:2) - figOrigin(1:2); + + if prod(positionRect(3:4)) > 0 + msgStr = sprintf('%dx%d area captured',positionRect(3),positionRect(4)); + end +%end % getInteractivePosition + +%% Get current figure (even if its handle is hidden) +function hFig = getCurrentFig + oldState = get(0,'showHiddenHandles'); + set(0,'showHiddenHandles','on'); + hFig = get(0,'CurrentFigure'); + set(0,'showHiddenHandles',oldState); +%end % getCurrentFig + +%% Get ancestor figure - used for old Matlab versions that don't have a built-in ancestor() +function hObj = ancestor(hObj,type) + if ~isempty(hObj) & ishandle(hObj) %#ok for Matlab 6 compatibility + try + hObj = get(hObj,'Ancestor'); + catch + % never mind... + end + try + %if ~isa(handle(hObj),type) % this is best but always returns 0 in Matlab 6! + %if ~isprop(hObj,'type') | ~strcmpi(get(hObj,'type'),type) % no isprop() in ML6! + try + objType = get(hObj,'type'); + catch + objType = ''; + end + if ~strcmpi(objType,type) + try + parent = get(handle(hObj),'parent'); + catch + parent = hObj.getParent; % some objs have no 'Parent' prop, just this method... + end + if ~isempty(parent) % empty parent means root ancestor, so exit + hObj = ancestor(parent,type); + end + end + catch + % never mind... + end + end +%end % ancestor + +%% Get position of an HG object in specified units +function pos = getPos(hObj,field,units) + % Matlab 6 did not have hgconvertunits so use the old way... + oldUnits = get(hObj,'units'); + if strcmpi(oldUnits,units) % don't modify units unless we must! + pos = get(hObj,field); + else + set(hObj,'units',units); + pos = get(hObj,field); + set(hObj,'units',oldUnits); + end +%end % getPos + +%% Get pixel position of an HG object - for Matlab 6 compatibility +function pos = getPixelPos(hObj,varargin) + persistent originalObj + try + stk = dbstack; + if ~strcmp(stk(2).name,'getPixelPos') + originalObj = hObj; + end + + if isFigure(hObj) %| isAxes(hObj) + %try + pos = getPos(hObj,'OuterPosition','pixels'); + else %catch + % getpixelposition is unvectorized unfortunately! + pos = getpixelposition(hObj,varargin{:}); + + % add the axes labels/ticks if relevant (plus a tiny margin to fix 2px label/title inconsistencies) + if isAxes(hObj) & ~isImage(originalObj) %#ok ML6 + tightInsets = getPos(hObj,'TightInset','pixel'); + pos = pos + tightInsets.*[-1,-1,1,1] + [-1,1,1+tightInsets(1:2)]; + end + end + catch + try + % Matlab 6 did not have getpixelposition nor hgconvertunits so use the old way... + pos = getPos(hObj,'Position','pixels'); + catch + % Maybe the handle does not have a 'Position' prop (e.g., text/line/plot) - use its parent + pos = getPixelPos(get(hObj,'parent'),varargin{:}); + end + end + + % Handle the case of missing/invalid/empty HG handle + if isempty(pos) + pos = [0,0,0,0]; + end +%end % getPixelPos + +%% Adds a ScreenCapture toolbar button +function addToolbarButton(paramsStruct) + % Ensure we have a valid toolbar handle + hFig = ancestor(paramsStruct.toolbar,'figure'); + if isempty(hFig) + error('YMA:screencapture:badToolbar','the ''Toolbar'' parameter must contain a valid GUI handle'); + end + set(hFig,'ToolBar','figure'); + hToolbar = findall(hFig,'type','uitoolbar'); + if isempty(hToolbar) + error('YMA:screencapture:noToolbar','the ''Toolbar'' parameter must contain a figure handle possessing a valid toolbar'); + end + hToolbar = hToolbar(1); % just in case there are several toolbars... - use only the first + + % Prepare the camera icon + icon = ['3333333333333333'; ... + '3333333333333333'; ... + '3333300000333333'; ... + '3333065556033333'; ... + '3000000000000033'; ... + '3022222222222033'; ... + '3022220002222033'; ... + '3022203110222033'; ... + '3022201110222033'; ... + '3022204440222033'; ... + '3022220002222033'; ... + '3022222222222033'; ... + '3000000000000033'; ... + '3333333333333333'; ... + '3333333333333333'; ... + '3333333333333333']; + cm = [ 0 0 0; ... % black + 0 0.60 1; ... % light blue + 0.53 0.53 0.53; ... % light gray + NaN NaN NaN; ... % transparent + 0 0.73 0; ... % light green + 0.27 0.27 0.27; ... % gray + 0.13 0.13 0.13]; % dark gray + cdata = ind2rgb(uint8(icon-'0'),cm); + + % If the button does not already exit + hButton = findall(hToolbar,'Tag','ScreenCaptureButton'); + tooltip = 'Screen capture'; + if ~isempty(paramsStruct.target) + tooltip = [tooltip ' to ' paramsStruct.target]; + end + if isempty(hButton) + % Add the button with the icon to the figure's toolbar + hButton = uipushtool(hToolbar, 'CData',cdata, 'Tag','ScreenCaptureButton', 'TooltipString',tooltip, 'ClickedCallback',['screencapture(''' paramsStruct.target ''')']); %#ok unused + else + % Otherwise, simply update the existing button + set(hButton, 'CData',cdata, 'Tag','ScreenCaptureButton', 'TooltipString',tooltip, 'ClickedCallback',['screencapture(''' paramsStruct.target ''')']); + end +%end % addToolbarButton + +%% Java-get the actual screen-capture image data +function imgData = getScreenCaptureImageData(positionRect) + if isempty(positionRect) | all(positionRect==0) | positionRect(3)<=0 | positionRect(4)<=0 %#ok ML6 + imgData = []; + else + % Use java.awt.Robot to take a screen-capture of the specified screen area + rect = java.awt.Rectangle(positionRect(1), positionRect(2), positionRect(3), positionRect(4)); + robot = java.awt.Robot; + jImage = robot.createScreenCapture(rect); + + % Convert the resulting Java image to a Matlab image + % Adapted for a much-improved performance from: + % http://www.mathworks.com/support/solutions/data/1-2WPAYR.html + h = jImage.getHeight; + w = jImage.getWidth; + %imgData = zeros([h,w,3],'uint8'); + %pixelsData = uint8(jImage.getData.getPixels(0,0,w,h,[])); + %for i = 1 : h + % base = (i-1)*w*3+1; + % imgData(i,1:w,:) = deal(reshape(pixelsData(base:(base+3*w-1)),3,w)'); + %end + + % Performance further improved based on feedback from Urs Schwartz: + %pixelsData = reshape(typecast(jImage.getData.getDataStorage,'uint32'),w,h).'; + %imgData(:,:,3) = bitshift(bitand(pixelsData,256^1-1),-8*0); + %imgData(:,:,2) = bitshift(bitand(pixelsData,256^2-1),-8*1); + %imgData(:,:,1) = bitshift(bitand(pixelsData,256^3-1),-8*2); + + % Performance even further improved based on feedback from Jan Simon: + pixelsData = reshape(typecast(jImage.getData.getDataStorage, 'uint8'), 4, w, h); + imgData = cat(3, ... + transpose(reshape(pixelsData(3, :, :), w, h)), ... + transpose(reshape(pixelsData(2, :, :), w, h)), ... + transpose(reshape(pixelsData(1, :, :), w, h))); + end +%end % getInteractivePosition + +%% Return the figure to its pre-undocked state (when relevant) +function redockFigureIfRelevant(paramsStruct) + if paramsStruct.wasDocked + try + set(paramsStruct.hFigure,'WindowStyle','docked'); + %drawnow; + catch + % never mind - ignore... + end + end +%end % redockFigureIfRelevant + +%% Copy screen-capture to the system clipboard +% Adapted from http://www.mathworks.com/matlabcentral/fileexchange/28708-imclipboard/content/imclipboard.m +function imclipboard(imgData) + % Import necessary Java classes + import java.awt.Toolkit.* + import java.awt.image.BufferedImage + import java.awt.datatransfer.DataFlavor + + % Add the necessary Java class (ImageSelection) to the Java classpath + if ~exist('ImageSelection', 'class') + % Obtain the directory of the executable (or of the M-file if not deployed) + %javaaddpath(fileparts(which(mfilename)), '-end'); + if isdeployed % Stand-alone mode. + [status, result] = system('path'); %#ok + MatLabFilePath = char(regexpi(result, 'Path=(.*?);', 'tokens', 'once')); + else % MATLAB mode. + MatLabFilePath = fileparts(mfilename('fullpath')); + end + javaaddpath(MatLabFilePath, '-end'); + end + + % Get System Clipboard object (java.awt.Toolkit) + cb = getDefaultToolkit.getSystemClipboard; % can't use () in ML6! + + % Get image size + ht = size(imgData, 1); + wd = size(imgData, 2); + + % Convert to Blue-Green-Red format + imgData = imgData(:, :, [3 2 1]); + + % Convert to 3xWxH format + imgData = permute(imgData, [3, 2, 1]); + + % Append Alpha data (not used) + imgData = cat(1, imgData, 255*ones(1, wd, ht, 'uint8')); + + % Create image buffer + imBuffer = BufferedImage(wd, ht, BufferedImage.TYPE_INT_RGB); + imBuffer.setRGB(0, 0, wd, ht, typecast(imgData(:), 'int32'), 0, wd); + + % Create ImageSelection object + % % custom java class + imSelection = ImageSelection(imBuffer); + + % Set clipboard content to the image + cb.setContents(imSelection, []); +%end %imclipboard + +%% Is the provided handle a figure? +function flag = isFigure(hObj) + flag = isa(handle(hObj),'figure') | isa(hObj,'matlab.ui.Figure'); +%end %isFigure + +%% Is the provided handle an axes? +function flag = isAxes(hObj) + flag = isa(handle(hObj),'axes') | isa(hObj,'matlab.graphics.axis.Axes'); +%end %isFigure + +%% Is the provided handle an image? +function flag = isImage(hObj) + flag = isa(handle(hObj),'image') | isa(hObj,'matlab.graphics.primitive.Image'); +%end %isFigure + +%%%%%%%%%%%%%%%%%%%%%%%%%% TODO %%%%%%%%%%%%%%%%%%%%%%%%% +% find a way in interactive-mode to single-click another Matlab figure for screen-capture \ No newline at end of file diff --git a/Util/fastSaveas.m b/Util/fastSaveas.m new file mode 100644 index 000000000..5d28025ba --- /dev/null +++ b/Util/fastSaveas.m @@ -0,0 +1,19 @@ +function fastSaveas( hFig, hPanel, fileDestination ) +%FASTSAVEAS is a faster alternative to saveas. +% It is used to save diagnostic plots when exporting netCDF files. + +drawnow; + +% preserve the color scheme +set(hFig, 'InvertHardcopy', 'off'); + +% force figure full screen +frame_h = get(handle(hFig), 'JavaFrame'); +set(frame_h, 'Maximized', 1); + +% screencapture creates an image of what is really displayed on +% screen. +imwrite(screencapture(hPanel), fileDestination); + +end + diff --git a/imosToolbox.m b/imosToolbox.m index 47b747a8e..de2cacd5b 100644 --- a/imosToolbox.m +++ b/imosToolbox.m @@ -73,7 +73,7 @@ function imosToolbox(auto, varargin) end % Set current toolbox version -toolboxVersion = ['2.5.16 - ' computer]; +toolboxVersion = ['2.5.17 - ' computer]; switch auto case 'auto', autoIMOSToolbox(toolboxVersion, varargin{:}); diff --git a/imosToolbox_Linux64.bin b/imosToolbox_Linux64.bin index 70a242210..9ef711468 100755 Binary files a/imosToolbox_Linux64.bin and b/imosToolbox_Linux64.bin differ diff --git a/imosToolbox_Win32.exe b/imosToolbox_Win32.exe index 71ba6e7ee..f059c13dc 100644 Binary files a/imosToolbox_Win32.exe and b/imosToolbox_Win32.exe differ diff --git a/imosToolbox_Win64.exe b/imosToolbox_Win64.exe index 07b3ef46d..fa2bb50b7 100644 Binary files a/imosToolbox_Win64.exe and b/imosToolbox_Win64.exe differ