1579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy/*
2579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
4579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
5579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
6579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                            H   H  DDDD   RRRR                               %
7579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                            H   H  D   D  R   R                              %
8579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                            HHHHH  D   D  RRRR                               %
9579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                            H   H  D   D  R R                                %
10579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                            H   H  DDDD   R  R                               %
11579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
12579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
1303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                   Read/Write Radiance RGBE Image Format                     %
14579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
15579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
17579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                 July 1992                                   %
18579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
19579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
21579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  dedicated to making software imaging solutions freely available.           %
22579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
23579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  You may not use this file except in compliance with the License.  You may  %
24579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  obtain a copy of the License at                                            %
25579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
26579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%    http://www.imagemagick.org/script/license.php                            %
27579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
28579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  Unless required by applicable law or agreed to in writing, software        %
29579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
30579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  See the License for the specific language governing permissions and        %
32579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  limitations under the License.                                             %
33579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
34579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
36579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
37579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy*/
38579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
39579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy/*
40579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  Include declarations.
41579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy*/
424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace.h"
47510d06a3f7063e91993e13d546d5685048248074cristy#include "MagickCore/colorspace-private.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
624c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string-private.h"
634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
64579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
65579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy/*
6684c3d05cd3bced7357f65191d88bb019758d9f90cristy  Forward declarations.
6784c3d05cd3bced7357f65191d88bb019758d9f90cristy*/
6884c3d05cd3bced7357f65191d88bb019758d9f90cristystatic MagickBooleanType
691e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WriteHDRImage(const ImageInfo *,Image *,ExceptionInfo *);
7084c3d05cd3bced7357f65191d88bb019758d9f90cristy
7184c3d05cd3bced7357f65191d88bb019758d9f90cristy/*
72579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
74579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
75579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
7603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%   I s H D R                                                                 %
7703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
7803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
7903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
8003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
8203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  IsHDR() returns MagickTrue if the image format type, identified by the
8303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  magick string, is Radiance RGBE image format.
8403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
8503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  The format of the IsHDR method is:
8603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
8703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%      MagickBooleanType IsHDR(const unsigned char *magick,
8803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%        const size_t length)
8903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
9003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  A description of each parameter follows:
9103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
9203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%    o magick: compare image format pattern against these bytes.
9303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
9403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%    o length: Specifies the length of the magick string.
9503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%
9603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy*/
9703533f2c0a4746924d8aae185e28e5a364b9a2ddcristystatic MagickBooleanType IsHDR(const unsigned char *magick,
9803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  const size_t length)
9903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy{
10003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (length < 10)
10103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    return(MagickFalse);
10203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (LocaleNCompare((const char *) magick,"#?RADIANCE",10) == 0)
10303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    return(MagickTrue);
10484c3d05cd3bced7357f65191d88bb019758d9f90cristy  if (LocaleNCompare((const char *) magick,"#?RGBE",6) == 0)
10584c3d05cd3bced7357f65191d88bb019758d9f90cristy    return(MagickTrue);
10603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  return(MagickFalse);
10703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy}
10803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy
10903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy/*
11003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
11203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
11303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%                                                                             %
114579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%   R e a d H D R I m a g e                                                   %
115579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
116579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
117579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
118579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
12003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  ReadHDRImage() reads the Radiance RGBE image format and returns it.  It
1212138423d7e19b0623dab3c1c287e1e10c2ae90ddcristy%  allocates the memory necessary for the new Image structure and returns a
1222138423d7e19b0623dab3c1c287e1e10c2ae90ddcristy%  pointer to the new image.
123579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
124579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  The format of the ReadHDRImage method is:
125579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
126579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%      Image *ReadHDRImage(const ImageInfo *image_info,ExceptionInfo *exception)
127579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
128579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  A description of each parameter follows:
129579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
130579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%    o image_info: the image info.
131579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
132579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%    o exception: return any errors or warnings in this structure.
133579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
134579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy*/
135579bc8fd4e0088dfa82a440afe6002e95c4abf07cristystatic Image *ReadHDRImage(const ImageInfo *image_info,ExceptionInfo *exception)
136579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy{
13703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  char
138151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    format[MagickPathExtent],
139151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    keyword[MagickPathExtent],
140151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    tag[MagickPathExtent],
141151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    value[MagickPathExtent];
14203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy
14303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  double
14403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    gamma;
14503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy
146579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  Image
147579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    *image;
148579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
14903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  int
15003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    c;
151579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
15203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  MagickBooleanType
15303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    status,
15403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    value_expected;
155579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
1564c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
157579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    *q;
158579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
15903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  register ssize_t
16003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    i,
16103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    x;
162579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
16319c9c3c2dd34bf7fdc18eb27ba087d0346724080cristy  register unsigned char
16419c9c3c2dd34bf7fdc18eb27ba087d0346724080cristy    *p;
16519c9c3c2dd34bf7fdc18eb27ba087d0346724080cristy
166579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  ssize_t
167579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    count,
168579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    y;
169579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
170579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  unsigned char
17103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    *end,
17203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    pixel[4],
173579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    *pixels;
174579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
175579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  /*
176579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    Open image file.
177579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  */
178579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  assert(image_info != (const ImageInfo *) NULL);
179e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
180579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  if (image_info->debug != MagickFalse)
181579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
182579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy      image_info->filename);
183579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  assert(exception != (ExceptionInfo *) NULL);
184e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
1859950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
186579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
187579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  if (status == MagickFalse)
188579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    {
189579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy      image=DestroyImageList(image);
190579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy      return((Image *) NULL);
191579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    }
192579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  /*
19303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    Decode image header.
194579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  */
19503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  image->columns=0;
19603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  image->rows=0;
19703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  *format='\0';
19803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  c=ReadBlobByte(image);
19903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (c == EOF)
200579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    {
20103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      image=DestroyImage(image);
20203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      return((Image *) NULL);
203579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    }
20403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  while (isgraph(c) && (image->columns == 0) && (image->rows == 0))
20503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  {
20697bd7c3dd4286a28f67610e8708d824d43b80536cristy    if (c == (int) '#')
207579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy      {
20897bd7c3dd4286a28f67610e8708d824d43b80536cristy        char
20997bd7c3dd4286a28f67610e8708d824d43b80536cristy          *comment;
21097bd7c3dd4286a28f67610e8708d824d43b80536cristy
21103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        register char
21203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          *p;
21303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy
21497bd7c3dd4286a28f67610e8708d824d43b80536cristy        size_t
21597bd7c3dd4286a28f67610e8708d824d43b80536cristy          length;
21697bd7c3dd4286a28f67610e8708d824d43b80536cristy
217579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy        /*
21897bd7c3dd4286a28f67610e8708d824d43b80536cristy          Read comment-- any text between # and end-of-line.
219579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy        */
220151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy        length=MagickPathExtent;
22197bd7c3dd4286a28f67610e8708d824d43b80536cristy        comment=AcquireString((char *) NULL);
22297bd7c3dd4286a28f67610e8708d824d43b80536cristy        for (p=comment; comment != (char *) NULL; p++)
22303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        {
22403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          c=ReadBlobByte(image);
22597bd7c3dd4286a28f67610e8708d824d43b80536cristy          if ((c == EOF) || (c == (int) '\n'))
22697bd7c3dd4286a28f67610e8708d824d43b80536cristy            break;
22797bd7c3dd4286a28f67610e8708d824d43b80536cristy          if ((size_t) (p-comment+1) >= length)
22897bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
22997bd7c3dd4286a28f67610e8708d824d43b80536cristy              *p='\0';
23097bd7c3dd4286a28f67610e8708d824d43b80536cristy              length<<=1;
23197bd7c3dd4286a28f67610e8708d824d43b80536cristy              comment=(char *) ResizeQuantumMemory(comment,length+
232151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                MagickPathExtent,sizeof(*comment));
23397bd7c3dd4286a28f67610e8708d824d43b80536cristy              if (comment == (char *) NULL)
23497bd7c3dd4286a28f67610e8708d824d43b80536cristy                break;
23597bd7c3dd4286a28f67610e8708d824d43b80536cristy              p=comment+strlen(comment);
23697bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
23797bd7c3dd4286a28f67610e8708d824d43b80536cristy          *p=(char) c;
23803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        }
23997bd7c3dd4286a28f67610e8708d824d43b80536cristy        if (comment == (char *) NULL)
24097bd7c3dd4286a28f67610e8708d824d43b80536cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
24103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        *p='\0';
242d15e65928aec551b7388c2863de3e3e628e2e0ddcristy        (void) SetImageProperty(image,"comment",comment,exception);
24397bd7c3dd4286a28f67610e8708d824d43b80536cristy        comment=DestroyString(comment);
24497bd7c3dd4286a28f67610e8708d824d43b80536cristy        c=ReadBlobByte(image);
24597bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
24697bd7c3dd4286a28f67610e8708d824d43b80536cristy    else
24797bd7c3dd4286a28f67610e8708d824d43b80536cristy      if (isalnum(c) == MagickFalse)
24897bd7c3dd4286a28f67610e8708d824d43b80536cristy        c=ReadBlobByte(image);
24997bd7c3dd4286a28f67610e8708d824d43b80536cristy      else
25003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        {
25197bd7c3dd4286a28f67610e8708d824d43b80536cristy          register char
25297bd7c3dd4286a28f67610e8708d824d43b80536cristy            *p;
25397bd7c3dd4286a28f67610e8708d824d43b80536cristy
25497bd7c3dd4286a28f67610e8708d824d43b80536cristy          /*
25597bd7c3dd4286a28f67610e8708d824d43b80536cristy            Determine a keyword and its value.
25697bd7c3dd4286a28f67610e8708d824d43b80536cristy          */
25797bd7c3dd4286a28f67610e8708d824d43b80536cristy          p=keyword;
25897bd7c3dd4286a28f67610e8708d824d43b80536cristy          do
25903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          {
260151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy            if ((size_t) (p-keyword) < (MagickPathExtent-1))
26197bd7c3dd4286a28f67610e8708d824d43b80536cristy              *p++=c;
26297bd7c3dd4286a28f67610e8708d824d43b80536cristy            c=ReadBlobByte(image);
26397bd7c3dd4286a28f67610e8708d824d43b80536cristy          } while (isalnum(c) || (c == '_'));
26497bd7c3dd4286a28f67610e8708d824d43b80536cristy          *p='\0';
26597bd7c3dd4286a28f67610e8708d824d43b80536cristy          value_expected=MagickFalse;
26697bd7c3dd4286a28f67610e8708d824d43b80536cristy          while ((isspace((int) ((unsigned char) c)) != 0) || (c == '='))
26703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          {
26897bd7c3dd4286a28f67610e8708d824d43b80536cristy            if (c == '=')
26997bd7c3dd4286a28f67610e8708d824d43b80536cristy              value_expected=MagickTrue;
27097bd7c3dd4286a28f67610e8708d824d43b80536cristy            c=ReadBlobByte(image);
27103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          }
27297bd7c3dd4286a28f67610e8708d824d43b80536cristy          if (LocaleCompare(keyword,"Y") == 0)
27397bd7c3dd4286a28f67610e8708d824d43b80536cristy            value_expected=MagickTrue;
27497bd7c3dd4286a28f67610e8708d824d43b80536cristy          if (value_expected == MagickFalse)
27597bd7c3dd4286a28f67610e8708d824d43b80536cristy            continue;
27697bd7c3dd4286a28f67610e8708d824d43b80536cristy          p=value;
27797aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk          while ((c != '\n') && (c != '\0') && (c != EOF))
27803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          {
279151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy            if ((size_t) (p-value) < (MagickPathExtent-1))
28097bd7c3dd4286a28f67610e8708d824d43b80536cristy              *p++=c;
28197bd7c3dd4286a28f67610e8708d824d43b80536cristy            c=ReadBlobByte(image);
28203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          }
28397bd7c3dd4286a28f67610e8708d824d43b80536cristy          *p='\0';
28497bd7c3dd4286a28f67610e8708d824d43b80536cristy          /*
28597bd7c3dd4286a28f67610e8708d824d43b80536cristy            Assign a value to the specified keyword.
28697bd7c3dd4286a28f67610e8708d824d43b80536cristy          */
28797bd7c3dd4286a28f67610e8708d824d43b80536cristy          switch (*keyword)
28803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          {
28997bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'F':
29097bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'f':
29197bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
29297bd7c3dd4286a28f67610e8708d824d43b80536cristy              if (LocaleCompare(keyword,"format") == 0)
29397bd7c3dd4286a28f67610e8708d824d43b80536cristy                {
294151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy                  (void) CopyMagickString(format,value,MagickPathExtent);
29597bd7c3dd4286a28f67610e8708d824d43b80536cristy                  break;
29697bd7c3dd4286a28f67610e8708d824d43b80536cristy                }
297151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy              (void) FormatLocaleString(tag,MagickPathExtent,"hdr:%s",keyword);
298d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(image,tag,value,exception);
29997bd7c3dd4286a28f67610e8708d824d43b80536cristy              break;
30097bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
30197bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'G':
30297bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'g':
30397bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
30497bd7c3dd4286a28f67610e8708d824d43b80536cristy              if (LocaleCompare(keyword,"gamma") == 0)
30597bd7c3dd4286a28f67610e8708d824d43b80536cristy                {
306dbdd0e35efc03c9bccda644f5407db38b7c17eeccristy                  image->gamma=StringToDouble(value,(char **) NULL);
30797bd7c3dd4286a28f67610e8708d824d43b80536cristy                  break;
30897bd7c3dd4286a28f67610e8708d824d43b80536cristy                }
309151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy              (void) FormatLocaleString(tag,MagickPathExtent,"hdr:%s",keyword);
310d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(image,tag,value,exception);
31197bd7c3dd4286a28f67610e8708d824d43b80536cristy              break;
31297bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
31397bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'P':
31497bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'p':
31597bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
31697bd7c3dd4286a28f67610e8708d824d43b80536cristy              if (LocaleCompare(keyword,"primaries") == 0)
31797bd7c3dd4286a28f67610e8708d824d43b80536cristy                {
31897bd7c3dd4286a28f67610e8708d824d43b80536cristy                  float
31997bd7c3dd4286a28f67610e8708d824d43b80536cristy                    chromaticity[6],
32097bd7c3dd4286a28f67610e8708d824d43b80536cristy                    white_point[2];
32103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy
32249c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                  int
32349c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                    count;
32449c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy
32549c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                  count=sscanf(value,"%g %g %g %g %g %g %g %g",&chromaticity[0],
32649c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                    &chromaticity[1],&chromaticity[2],&chromaticity[3],
32749c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                    &chromaticity[4],&chromaticity[5],&white_point[0],
32849c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                    &white_point[1]);
32949c1cb3d17f2d45bc8d422e4b4c3e00b909b7714cristy                  if (count == 8)
33097aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                    {
33197aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.red_primary.x=chromaticity[0];
33297aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.red_primary.y=chromaticity[1];
33397aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.green_primary.x=chromaticity[2];
33497aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.green_primary.y=chromaticity[3];
33597aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.blue_primary.x=chromaticity[4];
33697aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.blue_primary.y=chromaticity[5];
33797aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.white_point.x=white_point[0],
33897aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->chromaticity.white_point.y=white_point[1];
33997aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                    }
34097bd7c3dd4286a28f67610e8708d824d43b80536cristy                  break;
34197bd7c3dd4286a28f67610e8708d824d43b80536cristy                }
342151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy              (void) FormatLocaleString(tag,MagickPathExtent,"hdr:%s",keyword);
343d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(image,tag,value,exception);
34497bd7c3dd4286a28f67610e8708d824d43b80536cristy              break;
34597bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
34697bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'Y':
34797bd7c3dd4286a28f67610e8708d824d43b80536cristy            case 'y':
34897bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
349587235d2854810066a543e4c80be0f91b12e4ad2cristy              char
350587235d2854810066a543e4c80be0f91b12e4ad2cristy                target[] = "Y";
351587235d2854810066a543e4c80be0f91b12e4ad2cristy
352587235d2854810066a543e4c80be0f91b12e4ad2cristy              if (strcmp(keyword,target) == 0)
35397bd7c3dd4286a28f67610e8708d824d43b80536cristy                {
35497bd7c3dd4286a28f67610e8708d824d43b80536cristy                  int
35597bd7c3dd4286a28f67610e8708d824d43b80536cristy                    height,
35697bd7c3dd4286a28f67610e8708d824d43b80536cristy                    width;
35797bd7c3dd4286a28f67610e8708d824d43b80536cristy
35897aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                  if (sscanf(value,"%d +X %d",&height,&width) == 2)
35997aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                    {
36097aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->columns=(size_t) width;
36197aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                      image->rows=(size_t) height;
36297aa7d7cfd2027f6ba7ce42caf8b798541b9cdc6dirk                    }
36397bd7c3dd4286a28f67610e8708d824d43b80536cristy                  break;
36497bd7c3dd4286a28f67610e8708d824d43b80536cristy                }
365151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy              (void) FormatLocaleString(tag,MagickPathExtent,"hdr:%s",keyword);
366d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(image,tag,value,exception);
36797bd7c3dd4286a28f67610e8708d824d43b80536cristy              break;
36897bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
36997bd7c3dd4286a28f67610e8708d824d43b80536cristy            default:
37097bd7c3dd4286a28f67610e8708d824d43b80536cristy            {
371151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy              (void) FormatLocaleString(tag,MagickPathExtent,"hdr:%s",keyword);
372d15e65928aec551b7388c2863de3e3e628e2e0ddcristy              (void) SetImageProperty(image,tag,value,exception);
37397bd7c3dd4286a28f67610e8708d824d43b80536cristy              break;
37497bd7c3dd4286a28f67610e8708d824d43b80536cristy            }
375579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy          }
37603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        }
37703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    if ((image->columns == 0) && (image->rows == 0))
37803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      while (isspace((int) ((unsigned char) c)) != 0)
37903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        c=ReadBlobByte(image);
38003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  }
381a74b77f50bdc7ed1f76a22c01b6257eed87afc73cristy  if ((LocaleCompare(format,"32-bit_rle_rgbe") != 0) &&
382a74b77f50bdc7ed1f76a22c01b6257eed87afc73cristy      (LocaleCompare(format,"32-bit_rle_xyze") != 0))
38303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
38403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if ((image->columns == 0) || (image->rows == 0))
38503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
38674d59d9aba057044655de03d08241d7923f4f362cristy  (void) SetImageColorspace(image,RGBColorspace,exception);
387a0d69f26a469fda5fdd7b6e964b9b40665bf9b41cristy  if (LocaleCompare(format,"32-bit_rle_xyze") == 0)
38874d59d9aba057044655de03d08241d7923f4f362cristy    (void) SetImageColorspace(image,XYZColorspace,exception);
389f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy  image->compression=(image->columns < 8) || (image->columns > 0x7ffff) ?
390f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy    NoCompression : RLECompression;
39103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (image_info->ping != MagickFalse)
39203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    {
39303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      (void) CloseBlob(image);
39403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      return(GetFirstImageInList(image));
39503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    }
396acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  status=SetImageExtent(image,image->columns,image->rows,exception);
397acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  if (status == MagickFalse)
398acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy    return(DestroyImageList(image));
39903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  /*
400a8ff94218c61fcff00f43be0684af7cc3ef060dfcristy    Read RGBE (red+green+blue+exponent) pixels.
40103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  */
402b84ca11ed968d83c68c046e85f0c29ef60212efdcristy  pixels=(unsigned char *) AcquireQuantumMemory(image->columns,4*
403b84ca11ed968d83c68c046e85f0c29ef60212efdcristy    sizeof(*pixels));
40403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (pixels == (unsigned char *) NULL)
40503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
40603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  for (y=0; y < (ssize_t) image->rows; y++)
40703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  {
408f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy    if (image->compression != RLECompression)
40903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      {
410a74b77f50bdc7ed1f76a22c01b6257eed87afc73cristy        count=ReadBlob(image,4*image->columns*sizeof(*pixels),pixels);
411a74b77f50bdc7ed1f76a22c01b6257eed87afc73cristy        if (count != (ssize_t) (4*image->columns*sizeof(*pixels)))
412579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy          break;
41397bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
41497bd7c3dd4286a28f67610e8708d824d43b80536cristy    else
41597bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
41697bd7c3dd4286a28f67610e8708d824d43b80536cristy        count=ReadBlob(image,4*sizeof(*pixel),pixel);
41797bd7c3dd4286a28f67610e8708d824d43b80536cristy        if (count != 4)
41897bd7c3dd4286a28f67610e8708d824d43b80536cristy          break;
41997bd7c3dd4286a28f67610e8708d824d43b80536cristy        if ((size_t) ((((size_t) pixel[2]) << 8) | pixel[3]) != image->columns)
42003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          {
421f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            (void) memcpy(pixels,pixel,4*sizeof(*pixel));
422f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            count=ReadBlob(image,4*(image->columns-1)*sizeof(*pixels),pixels+4);
423f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            image->compression=NoCompression;
424f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy          }
425f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy        else
426f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy          {
427f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            p=pixels;
428f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            for (i=0; i < 4; i++)
429f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            {
430f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy              end=&pixels[(i+1)*image->columns];
431f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy              while (p < end)
43203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy              {
433f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                count=ReadBlob(image,2*sizeof(*pixel),pixel);
434f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                if (count < 1)
43503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy                  break;
436f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                if (pixel[0] > 128)
43797bd7c3dd4286a28f67610e8708d824d43b80536cristy                  {
438f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    count=(ssize_t) pixel[0]-128;
439f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    if ((count == 0) || (count > (ssize_t) (end-p)))
44097bd7c3dd4286a28f67610e8708d824d43b80536cristy                      break;
441f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    while (count-- > 0)
442f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                      *p++=pixel[1];
443f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                  }
444f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                else
445f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                  {
446f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    count=(ssize_t) pixel[0];
447f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    if ((count == 0) || (count > (ssize_t) (end-p)))
448f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                      break;
449f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    *p++=pixel[1];
450f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                    if (--count > 0)
451f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                      {
452f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                        count=ReadBlob(image,(size_t) count*sizeof(*p),p);
453f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                        if (count < 1)
454f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                          break;
455f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                        p+=count;
456f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy                      }
45797bd7c3dd4286a28f67610e8708d824d43b80536cristy                  }
45803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy              }
459f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy            }
46003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          }
461579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy      }
46203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
463acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
46403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      break;
46597bd7c3dd4286a28f67610e8708d824d43b80536cristy    i=0;
46603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    for (x=0; x < (ssize_t) image->columns; x++)
46703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    {
468f0e4a5adabb660b74133f2d265ccb51e3f5e7582cristy      if (image->compression == RLECompression)
46997bd7c3dd4286a28f67610e8708d824d43b80536cristy        {
47097bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[0]=pixels[x];
47197bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[1]=pixels[x+image->columns];
47297bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[2]=pixels[x+2*image->columns];
47397bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[3]=pixels[x+3*image->columns];
47497bd7c3dd4286a28f67610e8708d824d43b80536cristy        }
47597bd7c3dd4286a28f67610e8708d824d43b80536cristy      else
47697bd7c3dd4286a28f67610e8708d824d43b80536cristy        {
47797bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[0]=pixels[i++];
47897bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[1]=pixels[i++];
47997bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[2]=pixels[i++];
48097bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[3]=pixels[i++];
48197bd7c3dd4286a28f67610e8708d824d43b80536cristy        }
4824c08aed51c5899665ade97263692328eea4af106cristy      SetPixelRed(image,0,q);
4834c08aed51c5899665ade97263692328eea4af106cristy      SetPixelGreen(image,0,q);
4844c08aed51c5899665ade97263692328eea4af106cristy      SetPixelBlue(image,0,q);
48503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      if (pixel[3] != 0)
48603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        {
48703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy          gamma=pow(2.0,pixel[3]-(128.0+8.0));
4884c08aed51c5899665ade97263692328eea4af106cristy          SetPixelRed(image,ClampToQuantum(QuantumRange*gamma*pixel[0]),q);
4894c08aed51c5899665ade97263692328eea4af106cristy          SetPixelGreen(image,ClampToQuantum(QuantumRange*gamma*pixel[1]),q);
4904c08aed51c5899665ade97263692328eea4af106cristy          SetPixelBlue(image,ClampToQuantum(QuantumRange*gamma*pixel[2]),q);
49103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy        }
492ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
49303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    }
49403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
49503533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      break;
49603533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
49703533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      image->rows);
49803533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    if (status == MagickFalse)
49903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      break;
50003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  }
50103533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
50203533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  if (EOFBlob(image) != MagickFalse)
50303533f2c0a4746924d8aae185e28e5a364b9a2ddcristy    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
50403533f2c0a4746924d8aae185e28e5a364b9a2ddcristy      image->filename);
505579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  (void) CloseBlob(image);
506579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  return(GetFirstImageInList(image));
507579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy}
508579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
509579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy/*
510579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
512579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
513579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
514579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%   R e g i s t e r H D R I m a g e                                           %
515579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
516579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
517579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
518579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
52003533f2c0a4746924d8aae185e28e5a364b9a2ddcristy%  RegisterHDRImage() adds attributes for the Radiance RGBE image format to the
5212138423d7e19b0623dab3c1c287e1e10c2ae90ddcristy%  list of supported formats.  The attributes include the image format tag, a
522579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  method to read and/or write the format, whether the format supports the
523579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  saving of more than one frame to the same file or blob, whether the format
524579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  supports native in-memory I/O, and a brief description of the format.
525579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
526579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  The format of the RegisterHDRImage method is:
527579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
528579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%      size_t RegisterHDRImage(void)
529579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
530579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy*/
531579bc8fd4e0088dfa82a440afe6002e95c4abf07cristyModuleExport size_t RegisterHDRImage(void)
532579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy{
533579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  MagickInfo
534579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy    *entry;
535579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
53606b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("HDR","HDR","Radiance RGBE image format");
537579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  entry->decoder=(DecodeImageHandler *) ReadHDRImage;
53884c3d05cd3bced7357f65191d88bb019758d9f90cristy  entry->encoder=(EncodeImageHandler *) WriteHDRImage;
53903533f2c0a4746924d8aae185e28e5a364b9a2ddcristy  entry->magick=(IsImageFormatHandler *) IsHDR;
540579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  (void) RegisterMagickInfo(entry);
541579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  return(MagickImageCoderSignature);
542579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy}
543579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy
544579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy/*
545579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
547579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
548579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
549579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%   U n r e g i s t e r H D R I m a g e                                       %
550579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
551579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
552579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%                                                                             %
553579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
555579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  UnregisterHDRImage() removes format registrations made by the
556579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  HDR module from the list of supported formats.
557579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
558579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%  The format of the UnregisterHDRImage method is:
559579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
560579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%      UnregisterHDRImage(void)
561579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy%
562579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy*/
563579bc8fd4e0088dfa82a440afe6002e95c4abf07cristyModuleExport void UnregisterHDRImage(void)
564579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy{
565579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy  (void) UnregisterMagickInfo("HDR");
566579bc8fd4e0088dfa82a440afe6002e95c4abf07cristy}
56784c3d05cd3bced7357f65191d88bb019758d9f90cristy
56884c3d05cd3bced7357f65191d88bb019758d9f90cristy/*
56984c3d05cd3bced7357f65191d88bb019758d9f90cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57084c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57184c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57284c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57384c3d05cd3bced7357f65191d88bb019758d9f90cristy%   W r i t e H D R I m a g e                                                 %
57484c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57584c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57684c3d05cd3bced7357f65191d88bb019758d9f90cristy%                                                                             %
57784c3d05cd3bced7357f65191d88bb019758d9f90cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57884c3d05cd3bced7357f65191d88bb019758d9f90cristy%
57984c3d05cd3bced7357f65191d88bb019758d9f90cristy%  WriteHDRImage() writes an image in the Radience RGBE image format.
58084c3d05cd3bced7357f65191d88bb019758d9f90cristy%
58184c3d05cd3bced7357f65191d88bb019758d9f90cristy%  The format of the WriteHDRImage method is:
58284c3d05cd3bced7357f65191d88bb019758d9f90cristy%
58384c3d05cd3bced7357f65191d88bb019758d9f90cristy%      MagickBooleanType WriteHDRImage(const ImageInfo *image_info,
5841e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
58584c3d05cd3bced7357f65191d88bb019758d9f90cristy%
58684c3d05cd3bced7357f65191d88bb019758d9f90cristy%  A description of each parameter follows.
58784c3d05cd3bced7357f65191d88bb019758d9f90cristy%
58884c3d05cd3bced7357f65191d88bb019758d9f90cristy%    o image_info: the image info.
58984c3d05cd3bced7357f65191d88bb019758d9f90cristy%
59084c3d05cd3bced7357f65191d88bb019758d9f90cristy%    o image:  The image.
59184c3d05cd3bced7357f65191d88bb019758d9f90cristy%
59284c3d05cd3bced7357f65191d88bb019758d9f90cristy*/
59397bd7c3dd4286a28f67610e8708d824d43b80536cristy
59497bd7c3dd4286a28f67610e8708d824d43b80536cristystatic size_t HDRWriteRunlengthPixels(Image *image,unsigned char *pixels)
59597bd7c3dd4286a28f67610e8708d824d43b80536cristy{
59697bd7c3dd4286a28f67610e8708d824d43b80536cristy#define MinimumRunlength 4
59797bd7c3dd4286a28f67610e8708d824d43b80536cristy
59897bd7c3dd4286a28f67610e8708d824d43b80536cristy  register size_t
59997bd7c3dd4286a28f67610e8708d824d43b80536cristy    p,
60097bd7c3dd4286a28f67610e8708d824d43b80536cristy    q;
60197bd7c3dd4286a28f67610e8708d824d43b80536cristy
60297bd7c3dd4286a28f67610e8708d824d43b80536cristy  size_t
60397bd7c3dd4286a28f67610e8708d824d43b80536cristy    runlength;
60497bd7c3dd4286a28f67610e8708d824d43b80536cristy
60597bd7c3dd4286a28f67610e8708d824d43b80536cristy  ssize_t
60697bd7c3dd4286a28f67610e8708d824d43b80536cristy    count,
60797bd7c3dd4286a28f67610e8708d824d43b80536cristy    previous_count;
60897bd7c3dd4286a28f67610e8708d824d43b80536cristy
60997bd7c3dd4286a28f67610e8708d824d43b80536cristy  unsigned char
61097bd7c3dd4286a28f67610e8708d824d43b80536cristy    pixel[2];
61197bd7c3dd4286a28f67610e8708d824d43b80536cristy
61297bd7c3dd4286a28f67610e8708d824d43b80536cristy  for (p=0; p < image->columns; )
61397bd7c3dd4286a28f67610e8708d824d43b80536cristy  {
61497bd7c3dd4286a28f67610e8708d824d43b80536cristy    q=p;
61597bd7c3dd4286a28f67610e8708d824d43b80536cristy    runlength=0;
61697bd7c3dd4286a28f67610e8708d824d43b80536cristy    previous_count=0;
61797bd7c3dd4286a28f67610e8708d824d43b80536cristy    while ((runlength < MinimumRunlength) && (q < image->columns))
61897bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
61997bd7c3dd4286a28f67610e8708d824d43b80536cristy      q+=runlength;
62097bd7c3dd4286a28f67610e8708d824d43b80536cristy      previous_count=(ssize_t) runlength;
62197bd7c3dd4286a28f67610e8708d824d43b80536cristy      runlength=1;
62297bd7c3dd4286a28f67610e8708d824d43b80536cristy      while ((pixels[q] == pixels[q+runlength]) &&
62397bd7c3dd4286a28f67610e8708d824d43b80536cristy             ((q+runlength) < image->columns) && (runlength < 127))
62497bd7c3dd4286a28f67610e8708d824d43b80536cristy       runlength++;
62597bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
62697bd7c3dd4286a28f67610e8708d824d43b80536cristy    if ((previous_count > 1) && (previous_count == (ssize_t) (q-p)))
62797bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
62897bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[0]=(unsigned char) (128+previous_count);
62997bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[1]=pixels[p];
63097bd7c3dd4286a28f67610e8708d824d43b80536cristy        if (WriteBlob(image,2*sizeof(*pixel),pixel) < 1)
63197bd7c3dd4286a28f67610e8708d824d43b80536cristy          break;
63297bd7c3dd4286a28f67610e8708d824d43b80536cristy        p=q;
63397bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
63497bd7c3dd4286a28f67610e8708d824d43b80536cristy    while (p < q)
63597bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
63697bd7c3dd4286a28f67610e8708d824d43b80536cristy      count=(ssize_t) (q-p);
63797bd7c3dd4286a28f67610e8708d824d43b80536cristy      if (count > 128)
63897bd7c3dd4286a28f67610e8708d824d43b80536cristy        count=128;
63997bd7c3dd4286a28f67610e8708d824d43b80536cristy      pixel[0]=(unsigned char) count;
64097bd7c3dd4286a28f67610e8708d824d43b80536cristy      if (WriteBlob(image,sizeof(*pixel),pixel) < 1)
64197bd7c3dd4286a28f67610e8708d824d43b80536cristy        break;
64297bd7c3dd4286a28f67610e8708d824d43b80536cristy      if (WriteBlob(image,(size_t) count*sizeof(*pixel),&pixels[p]) < 1)
64397bd7c3dd4286a28f67610e8708d824d43b80536cristy        break;
64497bd7c3dd4286a28f67610e8708d824d43b80536cristy      p+=count;
64597bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
64697bd7c3dd4286a28f67610e8708d824d43b80536cristy    if (runlength >= MinimumRunlength)
64797bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
64897bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[0]=(unsigned char) (128+runlength);
64997bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[1]=pixels[q];
65097bd7c3dd4286a28f67610e8708d824d43b80536cristy        if (WriteBlob(image,2*sizeof(*pixel),pixel) < 1)
65197bd7c3dd4286a28f67610e8708d824d43b80536cristy          break;
65297bd7c3dd4286a28f67610e8708d824d43b80536cristy        p+=runlength;
65397bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
65497bd7c3dd4286a28f67610e8708d824d43b80536cristy  }
65597bd7c3dd4286a28f67610e8708d824d43b80536cristy  return(p);
65697bd7c3dd4286a28f67610e8708d824d43b80536cristy}
65797bd7c3dd4286a28f67610e8708d824d43b80536cristy
6581e178e70fb3c956f9fc1e30c3ba863e882666465cristystatic MagickBooleanType WriteHDRImage(const ImageInfo *image_info,Image *image,
6591e178e70fb3c956f9fc1e30c3ba863e882666465cristy  ExceptionInfo *exception)
66084c3d05cd3bced7357f65191d88bb019758d9f90cristy{
66184c3d05cd3bced7357f65191d88bb019758d9f90cristy  char
662151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    header[MagickPathExtent];
66384c3d05cd3bced7357f65191d88bb019758d9f90cristy
66497bd7c3dd4286a28f67610e8708d824d43b80536cristy  const char
66597bd7c3dd4286a28f67610e8708d824d43b80536cristy    *property;
66684c3d05cd3bced7357f65191d88bb019758d9f90cristy
66784c3d05cd3bced7357f65191d88bb019758d9f90cristy  MagickBooleanType
66884c3d05cd3bced7357f65191d88bb019758d9f90cristy    status;
66984c3d05cd3bced7357f65191d88bb019758d9f90cristy
6704c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
67184c3d05cd3bced7357f65191d88bb019758d9f90cristy    *p;
67284c3d05cd3bced7357f65191d88bb019758d9f90cristy
67397bd7c3dd4286a28f67610e8708d824d43b80536cristy  register ssize_t
67497bd7c3dd4286a28f67610e8708d824d43b80536cristy    i,
67597bd7c3dd4286a28f67610e8708d824d43b80536cristy    x;
67684c3d05cd3bced7357f65191d88bb019758d9f90cristy
67784c3d05cd3bced7357f65191d88bb019758d9f90cristy  size_t
67884c3d05cd3bced7357f65191d88bb019758d9f90cristy    length;
67984c3d05cd3bced7357f65191d88bb019758d9f90cristy
68097bd7c3dd4286a28f67610e8708d824d43b80536cristy  ssize_t
68197bd7c3dd4286a28f67610e8708d824d43b80536cristy    count,
68297bd7c3dd4286a28f67610e8708d824d43b80536cristy    y;
68397bd7c3dd4286a28f67610e8708d824d43b80536cristy
68484c3d05cd3bced7357f65191d88bb019758d9f90cristy  unsigned char
68597bd7c3dd4286a28f67610e8708d824d43b80536cristy    pixel[4],
68684c3d05cd3bced7357f65191d88bb019758d9f90cristy    *pixels;
68784c3d05cd3bced7357f65191d88bb019758d9f90cristy
68884c3d05cd3bced7357f65191d88bb019758d9f90cristy  /*
68984c3d05cd3bced7357f65191d88bb019758d9f90cristy    Open output image file.
69084c3d05cd3bced7357f65191d88bb019758d9f90cristy  */
69184c3d05cd3bced7357f65191d88bb019758d9f90cristy  assert(image_info != (const ImageInfo *) NULL);
692e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
69384c3d05cd3bced7357f65191d88bb019758d9f90cristy  assert(image != (Image *) NULL);
694e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
69584c3d05cd3bced7357f65191d88bb019758d9f90cristy  if (image->debug != MagickFalse)
69684c3d05cd3bced7357f65191d88bb019758d9f90cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6973a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
698e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
6991e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
70084c3d05cd3bced7357f65191d88bb019758d9f90cristy  if (status == MagickFalse)
70184c3d05cd3bced7357f65191d88bb019758d9f90cristy    return(status);
70274d59d9aba057044655de03d08241d7923f4f362cristy  if (IsRGBColorspace(image->colorspace) == MagickFalse)
70374d59d9aba057044655de03d08241d7923f4f362cristy    (void) TransformImageColorspace(image,RGBColorspace,exception);
70484c3d05cd3bced7357f65191d88bb019758d9f90cristy  /*
70584c3d05cd3bced7357f65191d88bb019758d9f90cristy    Write header.
70684c3d05cd3bced7357f65191d88bb019758d9f90cristy  */
707151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  (void) ResetMagickMemory(header,' ',MagickPathExtent);
708151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  length=CopyMagickString(header,"#?RGBE\n",MagickPathExtent);
70997bd7c3dd4286a28f67610e8708d824d43b80536cristy  (void) WriteBlob(image,length,(unsigned char *) header);
710d15e65928aec551b7388c2863de3e3e628e2e0ddcristy  property=GetImageProperty(image,"comment",exception);
71197bd7c3dd4286a28f67610e8708d824d43b80536cristy  if ((property != (const char *) NULL) &&
71297bd7c3dd4286a28f67610e8708d824d43b80536cristy      (strchr(property,'\n') == (char *) NULL))
71397bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
714151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      count=FormatLocaleString(header,MagickPathExtent,"#%s\n",property);
71597bd7c3dd4286a28f67610e8708d824d43b80536cristy      (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
71697bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
717d15e65928aec551b7388c2863de3e3e628e2e0ddcristy  property=GetImageProperty(image,"hdr:exposure",exception);
71897bd7c3dd4286a28f67610e8708d824d43b80536cristy  if (property != (const char *) NULL)
71997bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
720151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      count=FormatLocaleString(header,MagickPathExtent,"EXPOSURE=%g\n",
72179d053159ee1309bf7f9e6f346c9af5143d0af46cristy        strtod(property,(char **) NULL));
72297bd7c3dd4286a28f67610e8708d824d43b80536cristy      (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
72397bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
72497bd7c3dd4286a28f67610e8708d824d43b80536cristy  if (image->gamma != 0.0)
72597bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
72614e606db148d6ebcaae20f1e1d6d71903ca4a556Cristy      count=FormatLocaleString(header,MagickPathExtent,"GAMMA=%g\n",
72714e606db148d6ebcaae20f1e1d6d71903ca4a556Cristy        image->gamma);
72897bd7c3dd4286a28f67610e8708d824d43b80536cristy      (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
72997bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
730151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  count=FormatLocaleString(header,MagickPathExtent,
73197bd7c3dd4286a28f67610e8708d824d43b80536cristy    "PRIMARIES=%g %g %g %g %g %g %g %g\n",
73297bd7c3dd4286a28f67610e8708d824d43b80536cristy    image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
73397bd7c3dd4286a28f67610e8708d824d43b80536cristy    image->chromaticity.green_primary.x,image->chromaticity.green_primary.y,
73497bd7c3dd4286a28f67610e8708d824d43b80536cristy    image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y,
73597bd7c3dd4286a28f67610e8708d824d43b80536cristy    image->chromaticity.white_point.x,image->chromaticity.white_point.y);
73697bd7c3dd4286a28f67610e8708d824d43b80536cristy  (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
737151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  length=CopyMagickString(header,"FORMAT=32-bit_rle_rgbe\n\n",MagickPathExtent);
73897bd7c3dd4286a28f67610e8708d824d43b80536cristy  (void) WriteBlob(image,length,(unsigned char *) header);
739151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy  count=FormatLocaleString(header,MagickPathExtent,"-Y %.20g +X %.20g\n",
74084c3d05cd3bced7357f65191d88bb019758d9f90cristy    (double) image->rows,(double) image->columns);
74197bd7c3dd4286a28f67610e8708d824d43b80536cristy  (void) WriteBlob(image,(size_t) count,(unsigned char *) header);
74284c3d05cd3bced7357f65191d88bb019758d9f90cristy  /*
74384c3d05cd3bced7357f65191d88bb019758d9f90cristy    Write HDR pixels.
74484c3d05cd3bced7357f65191d88bb019758d9f90cristy  */
74514e606db148d6ebcaae20f1e1d6d71903ca4a556Cristy  pixels=(unsigned char *) AcquireQuantumMemory(image->columns+128,4*
746ebc891a1d9621a19c509200d7bf3470ca18dde7fcristy    sizeof(*pixels));
74797bd7c3dd4286a28f67610e8708d824d43b80536cristy  if (pixels == (unsigned char *) NULL)
74884c3d05cd3bced7357f65191d88bb019758d9f90cristy    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
74914e606db148d6ebcaae20f1e1d6d71903ca4a556Cristy  (void) ResetMagickMemory(pixels,0,4*(image->columns+128)*sizeof(*pixels));
75084c3d05cd3bced7357f65191d88bb019758d9f90cristy  for (y=0; y < (ssize_t) image->rows; y++)
75184c3d05cd3bced7357f65191d88bb019758d9f90cristy  {
7521e178e70fb3c956f9fc1e30c3ba863e882666465cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
7534c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
75484c3d05cd3bced7357f65191d88bb019758d9f90cristy      break;
75597bd7c3dd4286a28f67610e8708d824d43b80536cristy    if ((image->columns >= 8) && (image->columns <= 0x7ffff))
75697bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
75797bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[0]=2;
75897bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[1]=2;
75997bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[2]=(unsigned char) (image->columns >> 8);
76097bd7c3dd4286a28f67610e8708d824d43b80536cristy        pixel[3]=(unsigned char) (image->columns & 0xff);
76197bd7c3dd4286a28f67610e8708d824d43b80536cristy        count=WriteBlob(image,4*sizeof(*pixel),pixel);
76297bd7c3dd4286a28f67610e8708d824d43b80536cristy        if (count != (ssize_t) (4*sizeof(*pixel)))
76397bd7c3dd4286a28f67610e8708d824d43b80536cristy          break;
76497bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
76597bd7c3dd4286a28f67610e8708d824d43b80536cristy    i=0;
76697bd7c3dd4286a28f67610e8708d824d43b80536cristy    for (x=0; x < (ssize_t) image->columns; x++)
76797bd7c3dd4286a28f67610e8708d824d43b80536cristy    {
76897bd7c3dd4286a28f67610e8708d824d43b80536cristy      double
76997bd7c3dd4286a28f67610e8708d824d43b80536cristy        gamma;
77097bd7c3dd4286a28f67610e8708d824d43b80536cristy
77197bd7c3dd4286a28f67610e8708d824d43b80536cristy      pixel[0]=0;
77297bd7c3dd4286a28f67610e8708d824d43b80536cristy      pixel[1]=0;
77397bd7c3dd4286a28f67610e8708d824d43b80536cristy      pixel[2]=0;
77497bd7c3dd4286a28f67610e8708d824d43b80536cristy      pixel[3]=0;
7754c08aed51c5899665ade97263692328eea4af106cristy      gamma=QuantumScale*GetPixelRed(image,p);
7764c08aed51c5899665ade97263692328eea4af106cristy      if ((QuantumScale*GetPixelGreen(image,p)) > gamma)
7774c08aed51c5899665ade97263692328eea4af106cristy        gamma=QuantumScale*GetPixelGreen(image,p);
7784c08aed51c5899665ade97263692328eea4af106cristy      if ((QuantumScale*GetPixelBlue(image,p)) > gamma)
7794c08aed51c5899665ade97263692328eea4af106cristy        gamma=QuantumScale*GetPixelBlue(image,p);
78097bd7c3dd4286a28f67610e8708d824d43b80536cristy      if (gamma > MagickEpsilon)
78197bd7c3dd4286a28f67610e8708d824d43b80536cristy        {
78297bd7c3dd4286a28f67610e8708d824d43b80536cristy          int
78397bd7c3dd4286a28f67610e8708d824d43b80536cristy            exponent;
78497bd7c3dd4286a28f67610e8708d824d43b80536cristy
78597bd7c3dd4286a28f67610e8708d824d43b80536cristy          gamma=frexp(gamma,&exponent)*256.0/gamma;
7864c08aed51c5899665ade97263692328eea4af106cristy          pixel[0]=(unsigned char) (gamma*QuantumScale*GetPixelRed(image,p));
7874c08aed51c5899665ade97263692328eea4af106cristy          pixel[1]=(unsigned char) (gamma*QuantumScale*GetPixelGreen(image,p));
7884c08aed51c5899665ade97263692328eea4af106cristy          pixel[2]=(unsigned char) (gamma*QuantumScale*GetPixelBlue(image,p));
78997bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixel[3]=(unsigned char) (exponent+128);
79097bd7c3dd4286a28f67610e8708d824d43b80536cristy        }
79197bd7c3dd4286a28f67610e8708d824d43b80536cristy      if ((image->columns >= 8) && (image->columns <= 0x7ffff))
79297bd7c3dd4286a28f67610e8708d824d43b80536cristy        {
79397bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[x]=pixel[0];
79497bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[x+image->columns]=pixel[1];
79597bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[x+2*image->columns]=pixel[2];
79697bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[x+3*image->columns]=pixel[3];
79797bd7c3dd4286a28f67610e8708d824d43b80536cristy        }
79897bd7c3dd4286a28f67610e8708d824d43b80536cristy      else
79997bd7c3dd4286a28f67610e8708d824d43b80536cristy        {
80097bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[i++]=pixel[0];
80197bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[i++]=pixel[1];
80297bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[i++]=pixel[2];
80397bd7c3dd4286a28f67610e8708d824d43b80536cristy          pixels[i++]=pixel[3];
80497bd7c3dd4286a28f67610e8708d824d43b80536cristy        }
805ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
80697bd7c3dd4286a28f67610e8708d824d43b80536cristy    }
80797bd7c3dd4286a28f67610e8708d824d43b80536cristy    if ((image->columns >= 8) && (image->columns <= 0x7ffff))
80897bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
80997bd7c3dd4286a28f67610e8708d824d43b80536cristy        for (i=0; i < 4; i++)
81097bd7c3dd4286a28f67610e8708d824d43b80536cristy          length=HDRWriteRunlengthPixels(image,&pixels[i*image->columns]);
81197bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
81297bd7c3dd4286a28f67610e8708d824d43b80536cristy    else
81397bd7c3dd4286a28f67610e8708d824d43b80536cristy      {
814100a056069d5718f995e95a77950dcae6f412ff4cristy        count=WriteBlob(image,4*image->columns*sizeof(*pixels),pixels);
815100a056069d5718f995e95a77950dcae6f412ff4cristy        if (count != (ssize_t) (4*image->columns*sizeof(*pixels)))
81697bd7c3dd4286a28f67610e8708d824d43b80536cristy          break;
81797bd7c3dd4286a28f67610e8708d824d43b80536cristy      }
81884c3d05cd3bced7357f65191d88bb019758d9f90cristy    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
81984c3d05cd3bced7357f65191d88bb019758d9f90cristy      image->rows);
82084c3d05cd3bced7357f65191d88bb019758d9f90cristy    if (status == MagickFalse)
82184c3d05cd3bced7357f65191d88bb019758d9f90cristy      break;
82284c3d05cd3bced7357f65191d88bb019758d9f90cristy  }
82397bd7c3dd4286a28f67610e8708d824d43b80536cristy  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
82484c3d05cd3bced7357f65191d88bb019758d9f90cristy  (void) CloseBlob(image);
82584c3d05cd3bced7357f65191d88bb019758d9f90cristy  return(MagickTrue);
82684c3d05cd3bced7357f65191d88bb019758d9f90cristy}
827