-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathimclipboard.m
More file actions
246 lines (204 loc) · 8.23 KB
/
imclipboard.m
File metadata and controls
246 lines (204 loc) · 8.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
function varargout = imclipboard(clipmode, varargin)
%IMCLIPBOARD Copy and paste images to and from system clipboard.
%
% IMCLIPBOARD('copy', IMDATA) sets the clipboard content to the image
% represented by IMDATA. IMDATA must be MxN grayscale (double, uint8,
% uint16), MxN black and white (logical), MxNx3 true color (double,
% uint8, uint16)
%
% IMCLIPBOARD('copy', X, MAP) sets the clipboard content to the image
% data represented by indexed image X with colormap MAP. X must be MxN
% matrix (double, uint8, uint16) and MAP must be Px3 (double).
%
% IMDATA = IMCLIPBOARD('paste') returns the current image content in the
% clipboard as a true color image (MxNx3 uint8).
%
% [X, MAP] = IMCLIPBOARD('paste') returns the current image content in
% the clipboard as an indexed color image.
%
% IMCLIPBOARD('paste') displays the image in a new figure window.
%
% [...] = IMCLIPBOARD('paste', FILENAME) saves the image as FILENAME. FILENAME
% must be a name to one of the following image formats: JPG, GIF, BMP,
% PNG, TIF.
%
% Note: IMCLIPBOARD requires Java on all platforms.
%
% Example:
% im = imread('peppers.png');
% imclipboard('copy', im);
% % paste into a paint program
%
% im2 = imclipboard('paste');
%
% See also CLIPBOARD.
% Jiro Doke
% Copyright 2010-2017 The MathWorks, Inc.
% Sept 12, 2010
%
% Updates:
% Jan 2017 - fixed java getDefaultToolkit error.
narginchk(1, 3);
error(javachk('awt', 'IMCLIPBOARD'));
% Import necessary Java classes
import java.awt.Toolkit
import java.awt.image.BufferedImage
import java.awt.datatransfer.DataFlavor
% Get System Clipboard object (java.awt.Toolkit)
cb = Toolkit.getDefaultToolkit.getSystemClipboard();
clipmode = validatestring(clipmode, {'copy', 'paste'}, mfilename, 'CLIPMODE');
switch clipmode
case 'copy'
nargoutchk(0, 0);
% Add java class (ImageSelection) to the path
if ~exist('ImageSelection', 'class')
javaaddpath(fileparts(which(mfilename)), '-end');
end
data = validateCopyInput(varargin{:});
% Get image size
ht = size(data, 1); wd = size(data, 2);
% Convert to Blue-Green-Red format
data = data(:, :, [3 2 1]);
% Convert to 3xWxH format
data = permute(data, [3, 2, 1]);
% Append Alpha data (not used)
data = cat(1, data, 255*ones(1, wd, ht, 'uint8'));
% Create image buffer
imBuffer = BufferedImage(wd, ht, BufferedImage.TYPE_INT_RGB);
imBuffer.setRGB(0, 0, wd, ht, typecast(data(:), 'int32'), 0, wd);
% Create ImageSelection object
% % custom java class
imSelection = ImageSelection(imBuffer);
% Set clipboard content to the image
cb.setContents(imSelection, []);
case 'paste'
nargoutchk(0, 2);
filename = validatePasteInput(varargin{:});
try
% Attempt to retrieve image data from system clipboard. If there is no
% image data, it will throw an exception.
imBuffer = cb.getData(DataFlavor.imageFlavor);
catch %#ok<CTCH>
disp('No image data in clipboard');
imBuffer = [];
end
if isempty(imBuffer)
im = [];
else
im = imBuffer.getRGB(0, 0, imBuffer.getWidth, imBuffer.getHeight, [], 0, imBuffer.getWidth);
% "im" is an INT32 array, where each value contains 4 bytes of information
% (Blue, Green, Red, Alpha). Alpha is not used.
% type cast INT32 to UINT8 (--> 4 times as many elements)
im = typecast(im, 'uint8');
% Reshape to 4xWxH
im = reshape(im, [4, imBuffer.getWidth, imBuffer.getHeight]);
% Remove Alpha information (4th row) because it is not used
im = im(1:3, :, :);
% Convert to HxWx3 array
im = permute(im, [3 2 1]);
% Convert color space order to R-G-B
im = im(:, :, [3 2 1]);
end
if nargout == 1
varargout{1} = im;
elseif nargout == 2
if isempty(im)
varargout{1} = [];
varargout{2} = [];
else
% Convert to indexed image (getting full possible color space)
[varargout{1}, varargout{2}] = rgb2ind(im, 65536);
end
else
if nargin == 1 && ~isempty(im)
figure;
imshow(im);
end
end
if nargin == 2 && ~isempty(im)
[~, ~, e] = fileparts(filename);
if strcmpi(e, '.gif')
% GIF files require indexed image
[x, map] = rgb2ind(im, 256);
imwrite(x, map, filename);
else
imwrite(im, filename);
end
end
end
end
%% Helper Function
function data = validateCopyInput(varargin)
if nargin == 0
error('imclipboard:NotEnoughArguments', ...
'For ''copy'', the second argument must be an image array');
end
if nargin == 2 % X and colormap
% X
validateattributes(varargin{1}, {'double', 'uint8', 'uint16'}, {'2d', 'real', 'nonnegative'}, mfilename, 'X');
if isa(varargin{1}, 'double')
validateattributes(varargin{1}, {'double'}, {'>=', 0, '<=', 1}, mfilename, 'X');
end
% MAP
validateattributes(varargin{2}, {'double'}, {'size', [nan 3], '>=', 0, '<=', 1}, mfilename, 'MAP');
data = ind2rgb(varargin{1}, varargin{2});
data = uint8(255*data);
else % nargin == 1 % Grayscale, True Color, Black and White
validateattributes(varargin{1}, ...
{'double', 'logical', 'uint8', 'uint16'}, ...
{'real', 'nonnegative'}, mfilename, 'IMDATA');
switch class(varargin{1})
case 'double'
validateattributes(varargin{1}, {'double'}, {'>=', 0, '<=', 1}, mfilename, 'IMDATA');
if ndims(varargin{1}) == 2 % grayscale
data = uint8(255*varargin{1});
data = cat(3, data, data, data);
elseif ndims(varargin{1}) == 3
validateattributes(varargin{1}, {'double'}, {'size', [nan nan 3]}, mfilename, 'IMDATA');
data = uint8(255*varargin{1});
else
error('imclipboard:InvalideDoubleImage', ...
'Double image data must be 2 or 3 dimensions');
end
case 'logical'
validateattributes(varargin{1}, {'logical'}, {'2d'}, mfilename, 'IMDATA');
data = uint8(255*varargin{1});
data = cat(3, data, data, data);
case 'uint8'
if ndims(varargin{1}) == 2
data = cat(3, varargin{1}, varargin{1}, varargin{1});
elseif ndims(varargin{1}) == 3
validateattributes(varargin{1}, {'uint8'}, {'size', [nan nan 3]}, mfilename, 'IMDATA');
data = varargin{1};
else
error('imclipboard:InvalideUINT8Image', ...
'UINT8 image data must be 2 or 3 dimensions');
end
case 'uint16'
if ndims(varargin{1}) == 2
data = uint8(varargin{1}*(double(intmax('uint8'))/double(intmax('uint16'))));
data = cat(3, data, data, data);
elseif ndims(varargin{1}) == 3
validateattributes(varargin{1}, {'uint16'}, {'size', [nan nan 3]}, mfilename, 'IMDATA');
data = uint8(varargin{1}*(double(intmax('uint8'))/double(intmax('uint16'))));
else
error('imclipboard:InvalideUINT16Image', ...
'UINT16 image data must be 2 or 3 dimensions');
end
end
end
end
function filename = validatePasteInput(varargin)
if nargin == 0
filename = '';
else
filename = varargin{1};
validateattributes(filename, {'char'}, {'row'}, mfilename, 'FILENAME');
[~, ~, e] = fileparts(filename);
if ~ismember(lower(e), ...
{'.jpg', '.jpeg', '.tif', '.tiff', '.png', '.gif', '.bmp'})
error('imclipboard:InvalidFileFormat', ...
'You must specify a valid image extension: .jpg, .tif, .png, .gif, .bmp');
end
end
end