function adjGamma(hObject,event)
% ADJGAMMA Interface for adjusting image gamma values.
% Copyright 2010 The MathWorks, Inc.
data = guidata(hObject);
% Color channel
k = data.k;
% Axes bounds
ax = data.ax;
xlim(ax,[0 1]);
ylim(ax,[0 1]);
% Create gamma line and end points
P = data.P;
xPts = P{k}(:,1);
yPts = P{k}(:,2);
[hl,hp] = createPlots(ax,xPts,yPts);
data.hl = hl;
data.hp = hp;
% Save to GUIDATA
guidata(hObject,data);
% Set up callbacks
set(hl, 'ButtonDownFcn', @lineBtnDown);
end
% ADJGAMMA specific utility and callback functions
% ------------------------------------------------
function ptButtonDown(h,e)
% PTBUTTONDOWN responds to gamma point mouse clicks.
data = guidata(h);
hf = data.fig;
% Set the figure motion function accordingly
f = @(hh,ee)figMotionFcn(hh,ee,h);
set(hf,'WindowButtonMotionFcn',f);
set(hf,'WindowButtonUpFcn',@figButtonUp);
end
function lineBtnDown(h,e)
% LINEBTNDOWN responds to mouse clicks on the line.
data = guidata(h);
ax = data.ax;
hl = data.hl;
hp = data.hp;
[x,y,b] = tools.currentPoint(ax);
% Bail if out of bounds
if ~b, return, end
% Add a new gamma point, and link to line.
hpNew = addPoint(ax,x,y);
hp(end+1) = hpNew;
data.hp = hp;
guidata(h,data);
link(hl,hp);
% Trigger the gamma point callback immediately
ptButtonDown(hpNew,[]);
end
function figButtonUp(h,e)
% FIGBUTTONUP stops dragging a gamma point.
set(h,'WindowButtonMotionFcn',{});
set(h,'WindowButtonUpFcn',{});
end
function figMotionFcn(h,e,hUpdate)
% FIGMOTIONFCN drags a gamma marker.
data = guidata(h);
ax = data.ax;
hl = data.hl;
hp = data.hp;
% Update gamma marker and line
[x,y] = tools.currentPoint(ax,'snap',0.01);
set(hUpdate,'XData',x,'YData',y);
link(hl,hp);
% Update the image
setGamma(h,e);
end
function [hl,hp] = createPlots(ax,X,Y)
% CREATEPLOTS creates the gamma line and marker plots.
nPts = numel(X);
% Sort points by ascending X
M = [X(:) Y(:)];
M = sortrows(M,1);
X = M(:,1);
Y = M(:,2);
% Line connecting gamma points
hl = plot(ax,X,Y,'-b');
% Plot a separate marker for each gamma point
hp = zeros(nPts,1);
hold(ax,'on');
for i = 1:nPts
x = X(i);
y = Y(i);
hp(i) = plot(ax,x,y,'-dk');
set(hp(i), 'Markersize' , 8 , ...
'MarkerEdgeColor', 'k', ...
'MarkerFaceColor', 'k' );
% If this is not an endpoint, set callback
if i > 1 && i < nPts
set(hp(i),'ButtonDownFcn',@ptButtonDown);
end
end
hold(ax,'off');
% Apply curvature to the line
link(hl,hp);
end
function link(hl,hp)
% LINK syncs the line data with gamma points.
[x,y] = getPoints(hp);
% Color adjustment curve
% NOTE: This curve is an approximation of
% the full gamma curve. The actual gamma curve
% has 2^N elements, where N is the bit depth
% of each pixel.
[c,xi] = tools.gamma.curve(x,y,100);
% Set gamma line
set(hl,'XData',xi,'YData',c);
end
function hp = addPoint(ax,x,y)
% ADDPOINT adds a gamma control point.
% HP = ADD(AX,X,Y,FUN) adds a gamma control point
% to axes AX at [X,Y]. FUN is the handle of the
% function to call when the point is clicked.
hold(ax,'on');
hp = plot(ax,x,y,'-dk');
set(hp, 'Markersize' , 8 , ...
'MarkerEdgeColor', 'k', ...
'MarkerFaceColor', 'k', ...
'ButtonDownFcn' , @ptButtonDown);
hold(ax,'off');
end
function hp = deletePoints(hp,h)
% DELETE removes the markers H from the gamma points.
hp(hp == h) = [];
end
function [x,y] = getPoints(hp)
% GETPOINTS Returns X and Y gamma curve coordinates.
% Gamma points
x = get(hp,'XData'); x = cell2mat(x);
y = get(hp,'YData'); y = cell2mat(y);
% Ensure X and Y are column vectors
x = x(:);
y = y(:);
% Sort in order of increasing X
M = [x y];
M = sortrows(M,1);
x = M(:,1);
y = M(:,2);
end
function setGamma(h,e)
% SETGAMMA adjusts a color channel
data = guidata(h);
hi = data.hi;
hp = data.hp;
k = data.k;
[x,y] = getPoints(hp);
% Image to work with. Use the adjusted data
% for inactive channels, unadjusted data for
% active channel.
I = get(hi,'CData');
% Replace active channel with unmodified data
I(:,:,k) = data.I(:,:,k);
I(:,:,k) = tools.gamma.apply(x,y,I(:,:,k));
% Update image
set(hi,'CData',I);
% Update point list
data.P{k} = [x(:) y(:)];
guidata(h,data);
end