13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
6787c09caeeb16217a92190b802477636aebd55bdcristy%       H   H  IIIII  SSSSS  TTTTT   OOO    GGGG  RRRR    AAA   M   M         %
7787c09caeeb16217a92190b802477636aebd55bdcristy%       H   H    I    SS       T    O   O  G      R   R  A   A  MM MM         %
8787c09caeeb16217a92190b802477636aebd55bdcristy%       HHHHH    I     SSS     T    O   O  G  GG  RRRR   AAAAA  M M M         %
9787c09caeeb16217a92190b802477636aebd55bdcristy%       H   H    I       SS    T    O   O  G   G  R R    A   A  M   M         %
10787c09caeeb16217a92190b802477636aebd55bdcristy%       H   H  IIIII  SSSSS    T     OOO    GGG   R  R   A   A  M   M         %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
13787c09caeeb16217a92190b802477636aebd55bdcristy%                          Write A Histogram Image.                           %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
17787c09caeeb16217a92190b802477636aebd55bdcristy%                                 July 1992                                   %
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  dedicated to making software imaging solutions freely available.           %
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  You may not use this file except in compliance with the License.  You may  %
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  obtain a copy of the License at                                            %
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    http://www.imagemagick.org/script/license.php                            %
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  Unless required by applicable law or agreed to in writing, software        %
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  See the License for the specific language governing permissions and        %
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  limitations under the License.                                             %
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Include declarations.
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
4376ce6e193e5a305875173a744bbd59d27ddb3148cristy#include "MagickCore/artifact.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/constitute.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/geometry.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/histogram.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/option.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
6176ce6e193e5a305875173a744bbd59d27ddb3148cristy#include "MagickCore/property.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resource_.h"
644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/statistic.h"
664c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
674c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
68e40005d4b3d35ab5844d139731543174539453cfcristy#include "MagickCore/token.h"
694c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
74787c09caeeb16217a92190b802477636aebd55bdcristystatic MagickBooleanType
751e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WriteHISTOGRAMImage(const ImageInfo *,Image *,ExceptionInfo *);
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
82787c09caeeb16217a92190b802477636aebd55bdcristy%   R e g i s t e r H I S T O G R A M I m a g e                               %
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
88787c09caeeb16217a92190b802477636aebd55bdcristy%  RegisterHISTOGRAMImage() adds attributes for the Histogram image format
89787c09caeeb16217a92190b802477636aebd55bdcristy%  to the list of supported formats.  The attributes include the image format
90787c09caeeb16217a92190b802477636aebd55bdcristy%  tag, a method to read and/or write the format, whether the format
91787c09caeeb16217a92190b802477636aebd55bdcristy%  supports the saving of more than one frame to the same file or blob,
92787c09caeeb16217a92190b802477636aebd55bdcristy%  whether the format supports native in-memory I/O, and a brief
93787c09caeeb16217a92190b802477636aebd55bdcristy%  description of the format.
941bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy%
95787c09caeeb16217a92190b802477636aebd55bdcristy%  The format of the RegisterHISTOGRAMImage method is:
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
97bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterHISTOGRAMImage(void)
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
100bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterHISTOGRAMImage(void)
1011bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy{
102787c09caeeb16217a92190b802477636aebd55bdcristy  MagickInfo
103787c09caeeb16217a92190b802477636aebd55bdcristy    *entry;
104787c09caeeb16217a92190b802477636aebd55bdcristy
10506b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("HISTOGRAM","HISTOGRAM","Histogram of the image");
106787c09caeeb16217a92190b802477636aebd55bdcristy  entry->encoder=(EncodeImageHandler *) WriteHISTOGRAMImage;
10708e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
108009d739511cb808de2f5899fe7e06be7350838e9cristy  entry->format_type=ImplicitFormatType;
109787c09caeeb16217a92190b802477636aebd55bdcristy  (void) RegisterMagickInfo(entry);
110787c09caeeb16217a92190b802477636aebd55bdcristy  return(MagickImageCoderSignature);
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
118787c09caeeb16217a92190b802477636aebd55bdcristy%   U n r e g i s t e r H I S T O G R A M I m a g e                           %
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
124787c09caeeb16217a92190b802477636aebd55bdcristy%  UnregisterHISTOGRAMImage() removes format registrations made by the
125787c09caeeb16217a92190b802477636aebd55bdcristy%  HISTOGRAM module from the list of supported formats.
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
127787c09caeeb16217a92190b802477636aebd55bdcristy%  The format of the UnregisterHISTOGRAMImage method is:
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
129787c09caeeb16217a92190b802477636aebd55bdcristy%      UnregisterHISTOGRAMImage(void)
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
132787c09caeeb16217a92190b802477636aebd55bdcristyModuleExport void UnregisterHISTOGRAMImage(void)
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
134787c09caeeb16217a92190b802477636aebd55bdcristy  (void) UnregisterMagickInfo("HISTOGRAM");
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
142787c09caeeb16217a92190b802477636aebd55bdcristy%   W r i t e H I S T O G R A M I m a g e                                     %
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
148787c09caeeb16217a92190b802477636aebd55bdcristy%  WriteHISTOGRAMImage() writes an image to a file in Histogram format.
149787c09caeeb16217a92190b802477636aebd55bdcristy%  The image shows a histogram of the color (or gray) values in the image.  The
150787c09caeeb16217a92190b802477636aebd55bdcristy%  image consists of three overlaid histograms:  a red one for the red channel,
151787c09caeeb16217a92190b802477636aebd55bdcristy%  a green one for the green channel, and a blue one for the blue channel.  The
152787c09caeeb16217a92190b802477636aebd55bdcristy%  image comment contains a list of unique pixel values and the number of times
153787c09caeeb16217a92190b802477636aebd55bdcristy%  each occurs in the image.
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
155787c09caeeb16217a92190b802477636aebd55bdcristy%  This method is strongly based on a similar one written by
156787c09caeeb16217a92190b802477636aebd55bdcristy%  muquit@warm.semcor.com which in turn is based on ppmhistmap of netpbm.
1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
158787c09caeeb16217a92190b802477636aebd55bdcristy%  The format of the WriteHISTOGRAMImage method is:
1593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
160787c09caeeb16217a92190b802477636aebd55bdcristy%      MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
1611e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
1623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
165787c09caeeb16217a92190b802477636aebd55bdcristy%    o image_info: the image info.
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
167787c09caeeb16217a92190b802477636aebd55bdcristy%    o image:  The image.
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1691e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
1701e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
172787c09caeeb16217a92190b802477636aebd55bdcristystatic MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
1731e178e70fb3c956f9fc1e30c3ba863e882666465cristy  Image *image,ExceptionInfo *exception)
174787c09caeeb16217a92190b802477636aebd55bdcristy{
17531ac0f02045e4e34f2353d9a746b4b912987dc96cristy#define HistogramDensity  "256x200"
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
177787c09caeeb16217a92190b802477636aebd55bdcristy  char
178151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    filename[MagickPathExtent];
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1806db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy  const char
1816db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy    *option;
1826db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy
183787c09caeeb16217a92190b802477636aebd55bdcristy  Image
184787c09caeeb16217a92190b802477636aebd55bdcristy    *histogram_image;
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
186787c09caeeb16217a92190b802477636aebd55bdcristy  ImageInfo
187787c09caeeb16217a92190b802477636aebd55bdcristy    *write_info;
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
189787c09caeeb16217a92190b802477636aebd55bdcristy  MagickBooleanType
190787c09caeeb16217a92190b802477636aebd55bdcristy    status;
191787c09caeeb16217a92190b802477636aebd55bdcristy
1924c08aed51c5899665ade97263692328eea4af106cristy  PixelInfo
193787c09caeeb16217a92190b802477636aebd55bdcristy    *histogram;
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
195a19f1d70e9a9f88279c4ecafe6dfafc1f9a09599cristy  double
196787c09caeeb16217a92190b802477636aebd55bdcristy    maximum,
197787c09caeeb16217a92190b802477636aebd55bdcristy    scale;
198787c09caeeb16217a92190b802477636aebd55bdcristy
199787c09caeeb16217a92190b802477636aebd55bdcristy  RectangleInfo
200787c09caeeb16217a92190b802477636aebd55bdcristy    geometry;
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2024c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2054c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
206787c09caeeb16217a92190b802477636aebd55bdcristy    *q,
207787c09caeeb16217a92190b802477636aebd55bdcristy    *r;
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
20931ac0f02045e4e34f2353d9a746b4b912987dc96cristy  register ssize_t
21031ac0f02045e4e34f2353d9a746b4b912987dc96cristy    x;
21131ac0f02045e4e34f2353d9a746b4b912987dc96cristy
212787c09caeeb16217a92190b802477636aebd55bdcristy  size_t
213787c09caeeb16217a92190b802477636aebd55bdcristy    length;
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
21531ac0f02045e4e34f2353d9a746b4b912987dc96cristy  ssize_t
21631ac0f02045e4e34f2353d9a746b4b912987dc96cristy    y;
21731ac0f02045e4e34f2353d9a746b4b912987dc96cristy
218787c09caeeb16217a92190b802477636aebd55bdcristy  /*
219787c09caeeb16217a92190b802477636aebd55bdcristy    Allocate histogram image.
220787c09caeeb16217a92190b802477636aebd55bdcristy  */
221787c09caeeb16217a92190b802477636aebd55bdcristy  assert(image_info != (const ImageInfo *) NULL);
222e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
224e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
2253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
226787c09caeeb16217a92190b802477636aebd55bdcristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
227787c09caeeb16217a92190b802477636aebd55bdcristy      image_info->filename);
228787c09caeeb16217a92190b802477636aebd55bdcristy  SetGeometry(image,&geometry);
229787c09caeeb16217a92190b802477636aebd55bdcristy  if (image_info->density == (char *) NULL)
230787c09caeeb16217a92190b802477636aebd55bdcristy    (void) ParseAbsoluteGeometry(HistogramDensity,&geometry);
231787c09caeeb16217a92190b802477636aebd55bdcristy  else
232787c09caeeb16217a92190b802477636aebd55bdcristy    (void) ParseAbsoluteGeometry(image_info->density,&geometry);
233787c09caeeb16217a92190b802477636aebd55bdcristy  histogram_image=CloneImage(image,geometry.width,geometry.height,MagickTrue,
2341e178e70fb3c956f9fc1e30c3ba863e882666465cristy    exception);
235787c09caeeb16217a92190b802477636aebd55bdcristy  if (histogram_image == (Image *) NULL)
236787c09caeeb16217a92190b802477636aebd55bdcristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2371e178e70fb3c956f9fc1e30c3ba863e882666465cristy  (void) SetImageStorageClass(histogram_image,DirectClass,exception);
2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
239787c09caeeb16217a92190b802477636aebd55bdcristy    Allocate histogram count arrays.
2403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
2416e963d8cbd0aebba1073d7f4b61e3d17177d6fedcristy  length=MagickMax((size_t) ScaleQuantumToChar(QuantumRange)+1UL,
242787c09caeeb16217a92190b802477636aebd55bdcristy    histogram_image->columns);
2430553bd5babdbdf65b95f91ed401c98fead17ab54cristy  histogram=(PixelInfo *) AcquireQuantumMemory(length,sizeof(*histogram));
2444c08aed51c5899665ade97263692328eea4af106cristy  if (histogram == (PixelInfo *) NULL)
2453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
246787c09caeeb16217a92190b802477636aebd55bdcristy      histogram_image=DestroyImage(histogram_image);
247787c09caeeb16217a92190b802477636aebd55bdcristy      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
249787c09caeeb16217a92190b802477636aebd55bdcristy  /*
250787c09caeeb16217a92190b802477636aebd55bdcristy    Initialize histogram count arrays.
251787c09caeeb16217a92190b802477636aebd55bdcristy  */
252787c09caeeb16217a92190b802477636aebd55bdcristy  (void) ResetMagickMemory(histogram,0,length*sizeof(*histogram));
253bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2551e178e70fb3c956f9fc1e30c3ba863e882666465cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2564c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
258bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
260ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
2614c08aed51c5899665ade97263692328eea4af106cristy        histogram[ScaleQuantumToChar(GetPixelRed(image,p))].red++;
262ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
2634c08aed51c5899665ade97263692328eea4af106cristy        histogram[ScaleQuantumToChar(GetPixelGreen(image,p))].green++;
264ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
2654c08aed51c5899665ade97263692328eea4af106cristy        histogram[ScaleQuantumToChar(GetPixelBlue(image,p))].blue++;
266ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
269787c09caeeb16217a92190b802477636aebd55bdcristy  maximum=histogram[0].red;
270bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (x=0; x < (ssize_t) histogram_image->columns; x++)
271787c09caeeb16217a92190b802477636aebd55bdcristy  {
272ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
2732b9582a27910c7baaeb04b7e969638328fa70095cristy        (maximum < histogram[x].red))
274787c09caeeb16217a92190b802477636aebd55bdcristy      maximum=histogram[x].red;
275ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
2762b9582a27910c7baaeb04b7e969638328fa70095cristy        (maximum < histogram[x].green))
277787c09caeeb16217a92190b802477636aebd55bdcristy      maximum=histogram[x].green;
278ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
2792b9582a27910c7baaeb04b7e969638328fa70095cristy        (maximum < histogram[x].blue))
280787c09caeeb16217a92190b802477636aebd55bdcristy      maximum=histogram[x].blue;
281787c09caeeb16217a92190b802477636aebd55bdcristy  }
282e6133492f32b99b69eb298622d92e5eb11fd98fbcristy  scale=0.0;
283e6133492f32b99b69eb298622d92e5eb11fd98fbcristy  if (fabs(maximum) >= MagickEpsilon)
284e6133492f32b99b69eb298622d92e5eb11fd98fbcristy    scale=(double) histogram_image->rows/maximum;
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
286787c09caeeb16217a92190b802477636aebd55bdcristy    Initialize histogram image.
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
288fad60c95ffc2ea3de9e5f0eaaeaaa3d008289683cristy  (void) QueryColorCompliance("#000000",AllCompliance,
2899950d57e1124b73f684fb5946e206994cefda628cristy    &histogram_image->background_color,exception);
290ea1a8aa04a9fe1500104284407c1cc06d20da699cristy  (void) SetImageBackgroundColor(histogram_image,exception);
291bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (x=0; x < (ssize_t) histogram_image->columns; x++)
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
293fad60c95ffc2ea3de9e5f0eaaeaaa3d008289683cristy    q=GetAuthenticPixels(histogram_image,x,0,1,histogram_image->rows,exception);
294acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
296ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
298bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].red-0.5);
2996db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy        r=q+y*GetPixelChannels(histogram_image);
300bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for ( ; y < (ssize_t) histogram_image->rows; y++)
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
3024c08aed51c5899665ade97263692328eea4af106cristy          SetPixelRed(histogram_image,QuantumRange,r);
3036db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy          r+=GetPixelChannels(histogram_image);
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
306ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
308bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].green-0.5);
3096db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy        r=q+y*GetPixelChannels(histogram_image);
310bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for ( ; y < (ssize_t) histogram_image->rows; y++)
311787c09caeeb16217a92190b802477636aebd55bdcristy        {
3124c08aed51c5899665ade97263692328eea4af106cristy          SetPixelGreen(histogram_image,QuantumRange,r);
3136db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy          r+=GetPixelChannels(histogram_image);
314787c09caeeb16217a92190b802477636aebd55bdcristy        }
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      }
316ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy    if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
3171bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy      {
318bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].blue-0.5);
3196db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy        r=q+y*GetPixelChannels(histogram_image);
320bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy        for ( ; y < (ssize_t) histogram_image->rows; y++)
321787c09caeeb16217a92190b802477636aebd55bdcristy        {
3224c08aed51c5899665ade97263692328eea4af106cristy          SetPixelBlue(histogram_image,QuantumRange,r);
3236db52da8af55ddc52b33fa84df8ddcc58bf1d0c1cristy          r+=GetPixelChannels(histogram_image);
324787c09caeeb16217a92190b802477636aebd55bdcristy        }
3251bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy      }
326787c09caeeb16217a92190b802477636aebd55bdcristy    if (SyncAuthenticPixels(histogram_image,exception) == MagickFalse)
327787c09caeeb16217a92190b802477636aebd55bdcristy      break;
328787c09caeeb16217a92190b802477636aebd55bdcristy    status=SetImageProgress(image,SaveImageTag,y,histogram_image->rows);
329787c09caeeb16217a92190b802477636aebd55bdcristy    if (status == MagickFalse)
330787c09caeeb16217a92190b802477636aebd55bdcristy      break;
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3324c08aed51c5899665ade97263692328eea4af106cristy  histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
333092ec8d083fedaedfb7792995e7ea42164553cffcristy  option=GetImageOption(image_info,"histogram:unique-colors");
334d5f40a91c013256a09b3e3c66cb6ea036ab44b95cristy  if ((option == (const char *) NULL) || (IsStringTrue(option) != MagickFalse))
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
336787c09caeeb16217a92190b802477636aebd55bdcristy      FILE
337787c09caeeb16217a92190b802477636aebd55bdcristy        *file;
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
339787c09caeeb16217a92190b802477636aebd55bdcristy      int
340787c09caeeb16217a92190b802477636aebd55bdcristy        unique_file;
3411bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy
342787c09caeeb16217a92190b802477636aebd55bdcristy      /*
343787c09caeeb16217a92190b802477636aebd55bdcristy        Add a unique colors as an image comment.
344787c09caeeb16217a92190b802477636aebd55bdcristy      */
345787c09caeeb16217a92190b802477636aebd55bdcristy      file=(FILE *) NULL;
346787c09caeeb16217a92190b802477636aebd55bdcristy      unique_file=AcquireUniqueFileResource(filename);
347787c09caeeb16217a92190b802477636aebd55bdcristy      if (unique_file != -1)
348787c09caeeb16217a92190b802477636aebd55bdcristy        file=fdopen(unique_file,"wb");
349787c09caeeb16217a92190b802477636aebd55bdcristy      if ((unique_file != -1) && (file != (FILE *) NULL))
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        {
351787c09caeeb16217a92190b802477636aebd55bdcristy          char
352787c09caeeb16217a92190b802477636aebd55bdcristy            *property;
3531bd4a3a6b7cc5505da6698c4e61423a091d9d79fcristy
3541e178e70fb3c956f9fc1e30c3ba863e882666465cristy          (void) GetNumberColors(image,file,exception);
355787c09caeeb16217a92190b802477636aebd55bdcristy          (void) fclose(file);
3561e178e70fb3c956f9fc1e30c3ba863e882666465cristy          property=FileToString(filename,~0UL,exception);
357787c09caeeb16217a92190b802477636aebd55bdcristy          if (property != (char *) NULL)
358787c09caeeb16217a92190b802477636aebd55bdcristy            {
359d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(histogram_image,"comment",property,
360d15e65928aec551b7388c2863de3e3e628e2e0ddcristy                exception);
361787c09caeeb16217a92190b802477636aebd55bdcristy              property=DestroyString(property);
362787c09caeeb16217a92190b802477636aebd55bdcristy            }
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        }
364787c09caeeb16217a92190b802477636aebd55bdcristy      (void) RelinquishUniqueFileResource(filename);
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
366787c09caeeb16217a92190b802477636aebd55bdcristy  /*
367787c09caeeb16217a92190b802477636aebd55bdcristy    Write Histogram image.
368787c09caeeb16217a92190b802477636aebd55bdcristy  */
369787c09caeeb16217a92190b802477636aebd55bdcristy  (void) CopyMagickString(histogram_image->filename,image_info->filename,
370151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    MagickPathExtent);
371787c09caeeb16217a92190b802477636aebd55bdcristy  write_info=CloneImageInfo(image_info);
372e6fb02dc1886ecc7669872eb4144730b42b871b7Cristy  *write_info->magick='\0';
3731e178e70fb3c956f9fc1e30c3ba863e882666465cristy  (void) SetImageInfo(write_info,1,exception);
37460f21f2ac2609b04da3830e79673846568078737Cristy  if ((*write_info->magick == '\0') ||
37560f21f2ac2609b04da3830e79673846568078737Cristy      (LocaleCompare(write_info->magick,"HISTOGRAM") == 0))
376e6fb02dc1886ecc7669872eb4144730b42b871b7Cristy    (void) FormatLocaleString(histogram_image->filename,MagickPathExtent,
377e6fb02dc1886ecc7669872eb4144730b42b871b7Cristy      "miff:%s",write_info->filename);
378bc3d31cb071e1a8b1ce2dead3e124f215b2938e1Cristy  histogram_image->blob=DetachBlob(histogram_image->blob);
379bc3d31cb071e1a8b1ce2dead3e124f215b2938e1Cristy  histogram_image->blob=CloneBlobInfo(image->blob);
3801e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=WriteImage(write_info,histogram_image,exception);
381bc3d31cb071e1a8b1ce2dead3e124f215b2938e1Cristy  image->blob=DetachBlob(image->blob);
382bc3d31cb071e1a8b1ce2dead3e124f215b2938e1Cristy  image->blob=CloneBlobInfo(histogram_image->blob);
383787c09caeeb16217a92190b802477636aebd55bdcristy  histogram_image=DestroyImage(histogram_image);
384787c09caeeb16217a92190b802477636aebd55bdcristy  write_info=DestroyImageInfo(write_info);
385787c09caeeb16217a92190b802477636aebd55bdcristy  return(status);
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
387