blob: 408ce2ecd4ef54d02e91288020a83d343c24e5f3 [file] [log] [blame]
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% H H IIIII SSSSS TTTTT OOO GGGG RRRR AAA M M %
% H H I SS T O O G R R A A MM MM %
% HHHHH I SSS T O O G GG RRRR AAAAA M M M %
% H H I SS T O O G G R R A A M M %
% H H IIIII SSSSS T OOO GGG R R A A M M %
% %
% %
% MagickCore Histogram Methods %
% %
% Software Design %
% Anthony Thyssen %
% Fred Weinhaus %
% August 2009 %
% %
% %
% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% http://www.imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "magick/studio.h"
#include "magick/cache-view.h"
#include "magick/enhance.h"
#include "magick/exception.h"
#include "magick/exception-private.h"
#include "magick/hashmap.h"
#include "magick/histogram.h"
#include "magick/image.h"
#include "magick/list.h"
#include "magick/memory_.h"
#include "magick/prepress.h"
#include "magick/registry.h"
#include "magick/semaphore.h"
#include "magick/splay-tree.h"
#include "magick/statistic.h"
#include "magick/string_.h"
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M i n M a x S t r e t c h I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MinMaxStretchImage() uses the exact minimum and maximum values found in
% each of the channels given, as the BlackPoint and WhitePoint to linearly
% stretch the colors (and histogram) of the image. The stretch points are
% also moved further inward by the adjustment values given.
%
% If the adjustment values are both zero this function is equivelent to a
% perfect normalization (or autolevel) of the image.
%
% Each channel is stretched independantally of each other (producing color
% distortion) unless the special 'SyncChannels' flag is also provided in the
% channels setting. If this flag is present the minimum and maximum point
% will be extracted from all the given channels, and those channels will be
% stretched by exactly the same amount (preventing color distortion).
%
% The 'SyncChannels' is turned on in the 'DefaultChannels' setting by
% default.
%
% The format of the MinMaxStretchImage method is:
%
% MagickBooleanType MinMaxStretchImage(Image *image,
% const ChannelType channel, const double black_adjust,
% const double white_adjust)
%
% A description of each parameter follows:
%
% o image: The image to auto-level
%
% o channel: The channels to auto-level. If the special 'SyncChannels'
% flag is set, all the given channels are stretched by the same amount.
%
% o black_adjust, white_adjust: Move the Black/White Point inward
% from the minimum and maximum points by this color value.
%
*/
MagickExport MagickBooleanType MinMaxStretchImage(Image *image,
const ChannelType channel, const double black_value,
const double white_value)
{
double
min,max;
MagickStatusType
status;
if ((channel & SyncChannels) != 0 )
{
/*
autolevel all channels equally
*/
GetImageChannelRange(image, channel, &min, &max, &image->exception);
min += black_value; max -= white_value;
return LevelImageChannel(image, channel, min, max, 1.0);
}
/*
autolevel each channel separateally
*/
status = MagickTrue;
if ((channel & RedChannel) != 0)
{
GetImageChannelRange(image, RedChannel, &min, &max, &image->exception);
min += black_value; max -= white_value;
status = status && LevelImageChannel(image, RedChannel, min, max, 1.0);
}
if ((channel & GreenChannel) != 0)
{
GetImageChannelRange(image, GreenChannel, &min, &max, &image->exception);
min += black_value; max -= white_value;
status = status && LevelImageChannel(image, GreenChannel, min, max, 1.0);
}
if ((channel & BlueChannel) != 0)
{
GetImageChannelRange(image, BlueChannel, &min, &max, &image->exception);
min += black_value; max -= white_value;
status = status && LevelImageChannel(image, BlueChannel, min, max, 1.0);
}
if (((channel & OpacityChannel) != 0) &&
(image->matte == MagickTrue))
{
GetImageChannelRange(image, OpacityChannel, &min, &max, &image->exception);
min += black_value; max -= white_value;
status = status && LevelImageChannel(image, OpacityChannel, min, max, 1.0);
}
if (((channel & IndexChannel) != 0) &&
(image->colorspace == CMYKColorspace))
{
GetImageChannelRange(image, IndexChannel, &min, &max, &image->exception);
min += black_value; max -= white_value;
status = status && LevelImageChannel(image, IndexChannel, min, max, 1.0);
}
return(status != 0 ? MagickTrue : MagickFalse);
}