## Copyright (C) 2016 Pantxo Diribarne
##
## This program is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see .
## -*- texinfo -*-
## @deftypefn {Function File} {@var{retval} =} impixelinfoval (@var{input1}, @var{input2})
##
## @seealso{}
## @end deftypefn
## Author: Pantxo Diribarne
## Created: 2016-09-07
function hc = impixelinfoval (hp = [], him = [])
tk = graphics_toolkit ();
if (! strcmp (tk, "qt"))
error ("impixelinfoval: not implemented for %s toolkit", tk)
endif
if (isempty (hp) || isempty (him))
print_usage ();
elseif (! ishandle (hp) || ! all (ishandle (him)))
error ("impixelinfoval: expect HP and HIM to be valid graphics handles")
elseif (! isfigure (hp) && ! strcmp (get (hp, "type"), "uipanel"))
error ("impixelinfoval: expect parent to be a figure or a uipanel")
elseif (! all (strcmp (get (him, "type"), "image")))
error ("impixelinfoval: expect HIM to be an (array of) image handle(s)");
endif
hf = ancestor (him(1), "figure");
update_data (hf, [], him);
handle_listeners ("add", him);
hc = uicontrol (hp, "style", "text", "units", "normalized", ...
"position", [0 0 1 0.05], "horizontalalignment", "left", ...
"deletefcn", {@hcdelete, him});
set (hf, "windowbuttonmotionfcn", {@motionfcn, hc});
endfunction
function update_data (h, d, him = [])
hf = ancestor (h, "figure");
if (isempty (him))
data = getappdata (hf, "__impixelinfodata__");
him = [data.him];
data = [];
endif
him(! ishandle (him)) = [];
nim = numel (him);
## Cache image informations into the appdata of the figure
for ii = 1:nim
data(ii).him = him(ii);
data(ii).coordfcn = get_coord_fcn (him(ii));
endfor
setappdata (hf, "__impixelinfodata__", data);
endfunction
function handle_listeners (action, him)
persistent lsn = @update_data;
persistent oldhax = [];
persistent hf = ancestor (him(1), "figure");
fcn = ifelse (strcmp (action, "add"), @addlistener, @dellistener);
## Figure
hf = ancestor (him(1), "figure");
feval (fcn, hf, "position", lsn);
## Images
him(! ishandle (him)) = [];
for ii = 1:numel (him)
## Store axes
oldhax = [oldhax ancestor(him(ii), "axes")];
feval (fcn, him(ii), "xdata", lsn);
feval (fcn, him(ii), "ydata", lsn);
feval (fcn, him(ii), "cdata", lsn);
feval (fcn, him(ii), "cdatamapping", lsn);
endfor
oldhax = unique (oldhax(ishandle (oldhax)));
for hax = oldhax
feval (fcn, hax, "position", lsn);
endfor
endfunction
function hcdelete (h, d, him)
set (gcbf (), "windowbuttonmotionfcn", []);
handle_listeners ("remove", him);
endfunction
function motionfcn (h,d, hc)
hasna = 1;
data = getappdata (h, "__impixelinfodata__");
pt = get (h, "currentpoint");
for ii = 1:numel (data)
[str, hasnan] = data(ii).coordfcn (pt);
if (! hasnan)
break
endif
endfor
set (hc, "string", str)
endfunction
function fcn = get_coord_fcn (him)
xdata = get (him, "xdata");
ydata = get (him, "ydata");
cdata = get (him, "cdata");
if (xdata(1) > xdata(2))
cdata = fliplr (cdata);
xdata = xdata(end:-1:1);
endif
if (ydata(1) > ydata(2))
cdata = flipud (cdata);
ydata = ydata(end:-1:1);
endif
mapping = get (him, "cdatamapping");
hax = ancestor (him, "axes");
xl = get (hax, "xlim");
yl = get (hax, "ylim");
cmap = colormap (hax);
unwind_protect
units = get (hax, "units");
set (hax, "units", "pixels");
axpos = get (hax, "position");
unwind_protect_cleanup
set (hax, "units", units);
end_unwind_protect
## We assume "ydir" is "reverse"
axpos(2) += axpos(4);
axpos(4) *= -1;
tmp = @(xy) (xy(:)'-axpos(1:2)) ./ axpos(3:4) .* [diff(xl) diff(yl)] + ...
[xl(1) yl(1)];
pxy = __image_pixel_size__ (him);
xdata(1) -= pxy(1);
xdata(2) += pxy(1);
ydata(1) -= pxy(2);
ydata(2) += pxy(2);
fcn = @(xy) pixinfo (xy, tmp, xdata, ydata, cdata, pxy, mapping, cmap);
endfunction
function [str, hasna] = pixinfo (xy, fig2axfcn, xd, yd, cdata, pxy,...
mapping, cmap)
str = "";
xy = fig2axfcn (xy);
nx = columns (cdata);
ny = rows (cdata);
z = NA;
hasna = true;
if (all ((xy > [xd(1) yd(1)]) & (xy < [xd(2) yd(2)])))
hasna = false;
idx(1) = sum (xy(1) > [linspace(xd(1), xd(2)-pxy(1)*2, nx)]);
idx(2) = sum (xy(2) > [linspace(yd(1), yd(2)-pxy(2)*2, ny)]);
z = cdata(idx(2), idx(1), :);
if (ndims (cdata) == 3)
## True color
str = sprintf ("(%d, %d) [%3.2f, %3.2f, %3.2f])", ...
round (xy(1)), round (xy(2)), z(1), z(2), z(3));
elseif (strcmp (mapping, "direct"))
ncol = rows (cmap);
idx = round (z);
idx(z<1) = 1;
idx(z>ncol) = ncol;
rgb = cmap (idx,:);
if (ismember (class (cdata), {"double", "single"}))
str = sprintf ("(%d, %d) %3.2f <%d> [%3.2f, %3.2f, %3.2f]",...
round (xy(1)), round (xy(2)), z, idx, ...
rgb(1), rgb(2), rgb(3));
else
str = sprintf ("(%d, %d) <%d> [%3.2f, %3.2f, %3.2f]",
round (xy(1)), round (xy(2)), z, ...
rgb(1), rgb(2), rgb(3));
endif
else
str = sprintf ("(%d, %d) %g", round (xy(1)), round (xy(2)), z);
endif
endif
if (isempty (str))
str = "(X, Y) Pixel Value";
endif
endfunction