/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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); }