13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            EEEEE  X   X  RRRR                               %
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            E       X X   R   R                              %
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            EEE      X    RRRR                               %
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            E       X X   R R                                %
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                            EEEEE  X   X  R  R                               %
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%            Read/Write High Dynamic-Range (HDR) Image File Format            %
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                              Software Design                                %
16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                 April 2007                                  %
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"
434c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob.h"
444c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/blob-private.h"
454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h"
464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h"
474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h"
484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h"
494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h"
504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h"
514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/magick.h"
524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h"
531838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy#include "MagickCore/option.h"
544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h"
554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h"
564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h"
574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/static.h"
584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h"
594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/module.h"
604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/resource_.h"
614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/utility.h"
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_OPENEXR_DELEGATE)
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <ImfCRgbaFile.h>
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Forward declarations.
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType
691e178e70fb3c956f9fc1e30c3ba863e882666465cristy  WriteEXRImage(const ImageInfo *,Image *,ExceptionInfo *);
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   I s E X R                                                                 %
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  IsEXR() returns MagickTrue if the image format type, identified by the
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  magick string, is EXR.
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the IsEXR method is:
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      MagickBooleanType IsEXR(const unsigned char *magick,const size_t length)
893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o magick: compare image format pattern against these bytes.
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o length: Specifies the length of the magick string.
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType IsEXR(const unsigned char *magick,const size_t length)
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (length < 4)
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickFalse);
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (memcmp(magick,"\166\057\061\001",4) == 0)
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(MagickTrue);
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickFalse);
1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_OPENEXR_DELEGATE)
1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e a d E X R I m a g e                                                   %
1133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  ReadEXRImage reads an image in the high dynamic-range (HDR) file format
1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  developed by Industrial Light & Magic.  It allocates the memory necessary
1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  for the new Image structure and returns a pointer to the new image.
1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the ReadEXRImage method is:
1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      Image *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception)
1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows:
1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o exception: return any errors or warnings in this structure.
1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic Image *ReadEXRImage(const ImageInfo *image_info,ExceptionInfo *exception)
1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const ImfHeader
1363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hdr_info;
1373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  Image
1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *image;
1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *read_info;
1433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfInputFile
1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *file;
1463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfRgba
1483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *scanline;
1493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_x,
1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    max_y,
1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min_x,
1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    min_y;
1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
156202de443c199963563857f50153b88fbe65afa80cristy  MagickBooleanType
157202de443c199963563857f50153b88fbe65afa80cristy    status;
1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
159bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
1603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
1613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1624c08aed51c5899665ade97263692328eea4af106cristy  register Quantum
1633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *q;
1643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
165202de443c199963563857f50153b88fbe65afa80cristy  ssize_t
166202de443c199963563857f50153b88fbe65afa80cristy    y;
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open image.
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
172e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->debug != MagickFalse)
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image_info->filename);
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(exception != (ExceptionInfo *) NULL);
177e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
1789950d57e1124b73f684fb5946e206994cefda628cristy  image=AcquireImage(image_info,exception);
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image=DestroyImageList(image);
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  read_info=CloneImageInfo(image_info);
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (IsPathAccessible(read_info->filename) == MagickFalse)
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) AcquireUniqueFilename(read_info->filename);
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ImageToFile(image,read_info->filename,exception);
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  file=ImfOpenInputFile(read_info->filename);
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (file == (ImfInputFile *) NULL)
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowFileException(exception,BlobError,"UnableToOpenBlob",
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImfErrorMessage());
196ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      if (LocaleCompare(image_info->filename,read_info->filename) != 0)
197ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk        (void) RelinquishUniqueFileResource(read_info->filename);
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      read_info=DestroyImageInfo(read_info);
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return((Image *) NULL);
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hdr_info=ImfInputHeader(file);
2021ff6c47f6ab145736980714e13ecfdc66fcaa331cristy  ImfHeaderDisplayWindow(hdr_info,&min_x,&min_y,&max_x,&max_y);
2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->columns=max_x-min_x+1UL;
2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  image->rows=max_y-min_y+1UL;
2058a46d827a124555f0c48fb2368ec1bba8e079ab6cristy  image->alpha_trait=BlendPixelTrait;
206e2c4f18a7274c0c5c6231a2f3d73741a87d583facristy  SetImageColorspace(image,RGBColorspace,exception);
207651478345f77d8fac3608be5866884062f27eacfcristy  image->gamma=1.0;
2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image_info->ping != MagickFalse)
2093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ImfCloseInputFile(file);
2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (LocaleCompare(image_info->filename,read_info->filename) != 0)
2123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        (void) RelinquishUniqueFileResource(read_info->filename);
2133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      read_info=DestroyImageInfo(read_info);
2143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) CloseBlob(image);
2153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(GetFirstImageInList(image));
2163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
217acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  status=SetImageExtent(image,image->columns,image->rows,exception);
218acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy  if (status == MagickFalse)
219acabb847a592ca5e430c1c0949d03acfc0b78bb9cristy    return(DestroyImageList(image));
2203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scanline=(ImfRgba *) AcquireQuantumMemory(image->columns,sizeof(*scanline));
2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scanline == (ImfRgba *) NULL)
2223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ImfCloseInputFile(file);
224ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      if (LocaleCompare(image_info->filename,read_info->filename) != 0)
225ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk        (void) RelinquishUniqueFileResource(read_info->filename);
226ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      read_info=DestroyImageInfo(read_info);
2273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
229bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
232acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy    if (q == (Quantum *) NULL)
2333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
23496eafde4b1b6ac9d4197c8120e5a2f25f3f4a981cristy    ResetMagickMemory(scanline,0,image->columns*sizeof(*scanline));
2353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ImfInputSetFrameBuffer(file,scanline-min_x-image->columns*(min_y+y),1,
2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      image->columns);
2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ImfInputReadPixels(file,min_y+y,min_y+y);
238bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
2393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
2408cd03c32d039162196906ff36501f3543019b56acristy      SetPixelRed(image,ClampToQuantum(QuantumRange*
2414c08aed51c5899665ade97263692328eea4af106cristy        ImfHalfToFloat(scanline[x].r)),q);
2428cd03c32d039162196906ff36501f3543019b56acristy      SetPixelGreen(image,ClampToQuantum(QuantumRange*
2434c08aed51c5899665ade97263692328eea4af106cristy        ImfHalfToFloat(scanline[x].g)),q);
2448cd03c32d039162196906ff36501f3543019b56acristy      SetPixelBlue(image,ClampToQuantum(QuantumRange*
2454c08aed51c5899665ade97263692328eea4af106cristy        ImfHalfToFloat(scanline[x].b)),q);
2468cd03c32d039162196906ff36501f3543019b56acristy      SetPixelAlpha(image,ClampToQuantum(QuantumRange*
2474c08aed51c5899665ade97263692328eea4af106cristy        ImfHalfToFloat(scanline[x].a)),q);
248ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      q+=GetPixelChannels(image);
2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
2503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (SyncAuthenticPixels(image,exception) == MagickFalse)
2513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
2533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scanline=(ImfRgba *) RelinquishMagickMemory(scanline);
2543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ImfCloseInputFile(file);
2553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (LocaleCompare(image_info->filename,read_info->filename) != 0)
2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) RelinquishUniqueFileResource(read_info->filename);
2573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  read_info=DestroyImageInfo(read_info);
2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(GetFirstImageInList(image));
2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   R e g i s t e r E X R I m a g e                                           %
2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  RegisterEXRImage() adds properties for the EXR image format
2753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  to the list of supported formats.  The properties include the image format
2763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  tag, a method to read and/or write the format, whether the format
2773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  supports the saving of more than one frame to the same file or blob,
2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  whether the format supports native in-memory I/O, and a brief
2793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  description of the format.
2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the RegisterEXRImage method is:
2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
283bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy%      size_t RegisterEXRImage(void)
2843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
286bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyModuleExport size_t RegisterEXRImage(void)
2873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
2883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickInfo
2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *entry;
2903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
29106b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("EXR","EXR","High Dynamic-range (HDR)");
2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_OPENEXR_DELEGATE)
2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->decoder=(DecodeImageHandler *) ReadEXRImage;
2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->encoder=(EncodeImageHandler *) WriteEXRImage;
2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  entry->magick=(IsImageFormatHandler *) IsEXR;
29708e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderAdjoinFlag;
29808e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags^=CoderBlobSupportFlag;
2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RegisterMagickInfo(entry);
3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickImageCoderSignature);
3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   U n r e g i s t e r E X R I m a g e                                       %
3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  UnregisterEXRImage() removes format registrations made by the
3153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  EXR module from the list of supported formats.
3163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the UnregisterEXRImage method is:
3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%      UnregisterEXRImage(void)
3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3223ed852eea50f9d4cd633efb8c2b054b8e33c253cristyModuleExport void UnregisterEXRImage(void)
3233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) UnregisterMagickInfo("EXR");
3253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_OPENEXR_DELEGATE)
3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
3293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%   W r i t e E X R I m a g e                                                 %
3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%                                                                             %
3373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  WriteEXRImage() writes an image to a file the in the high dynamic-range
3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  (HDR) file format developed by Industrial Light & Magic.
3413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  The format of the WriteEXRImage method is:
3433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3441e178e70fb3c956f9fc1e30c3ba863e882666465cristy%      MagickBooleanType WriteEXRImage(const ImageInfo *image_info,
3451e178e70fb3c956f9fc1e30c3ba863e882666465cristy%        Image *image,ExceptionInfo *exception)
3463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%  A description of each parameter follows.
3483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image_info: the image info.
3503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%    o image:  The image.
3523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%
3531e178e70fb3c956f9fc1e30c3ba863e882666465cristy%    o exception: return any errors or warnings in this structure.
3541e178e70fb3c956f9fc1e30c3ba863e882666465cristy%
3553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/
3561e178e70fb3c956f9fc1e30c3ba863e882666465cristystatic MagickBooleanType WriteEXRImage(const ImageInfo *image_info,Image *image,
3571e178e70fb3c956f9fc1e30c3ba863e882666465cristy  ExceptionInfo *exception)
3583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3591838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  const char
3601838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    *sampling_factor,
3611838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    *value;
3621838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy
3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImageInfo
3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *write_info;
3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHalf
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    half_quantum;
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHeader
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *hdr_info;
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfOutputFile
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *file;
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfRgba
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *scanline;
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  int
3791838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    channels,
3801838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    compression,
3811838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    factors[3];
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  MagickBooleanType
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    status;
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3864c08aed51c5899665ade97263692328eea4af106cristy  register const Quantum
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    *p;
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
389bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  register ssize_t
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    x;
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
392202de443c199963563857f50153b88fbe65afa80cristy  ssize_t
393202de443c199963563857f50153b88fbe65afa80cristy    y;
394202de443c199963563857f50153b88fbe65afa80cristy
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  /*
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    Open output image file.
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  */
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image_info != (const ImageInfo *) NULL);
399e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  assert(image != (Image *) NULL);
401e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image->signature == MagickCoreSignature);
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (image->debug != MagickFalse)
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4043a37efd7ece979e9c63dc8f2f2d3816bab8b1156cristy  assert(exception != (ExceptionInfo *) NULL);
405e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
4061e178e70fb3c956f9fc1e30c3ba863e882666465cristy  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (status == MagickFalse)
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return(status);
409d74fdd01f4bbd7296d3d0c4418527c1ed5f5b12bcristy  (void) SetImageColorspace(image,RGBColorspace,exception);
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  write_info=CloneImageInfo(image_info);
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) AcquireUniqueFilename(write_info->filename);
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hdr_info=ImfNewHeader();
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHeaderSetDataWindow(hdr_info,0,0,(int) image->columns-1,(int)
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows-1);
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHeaderSetDisplayWindow(hdr_info,0,0,(int) image->columns-1,(int)
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    image->rows-1);
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  compression=IMF_NO_COMPRESSION;
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == ZipSCompression)
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_ZIPS_COMPRESSION;
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == ZipCompression)
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_ZIP_COMPRESSION;
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == PizCompression)
4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_PIZ_COMPRESSION;
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == Pxr24Compression)
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_PXR24_COMPRESSION;
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(B44Compression)
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == B44Compression)
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_B44_COMPRESSION;
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(B44ACompression)
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (write_info->compression == B44ACompression)
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    compression=IMF_B44A_COMPRESSION;
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
4341838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  channels=0;
4351838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  value=GetImageOption(image_info,"exr:color-type");
4361838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  if (value != (const char *) NULL)
4371838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    {
4381838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      if (LocaleCompare(value,"RGB") == 0)
4391838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_RGB;
4401838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"RGBA") == 0)
4411838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_RGBA;
4421838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"YC") == 0)
4431838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_YC;
4441838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"YCA") == 0)
4451838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_YCA;
4461838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"Y") == 0)
4471838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_Y;
4481838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"YA") == 0)
4491838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_YA;
4501838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"R") == 0)
4511838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_R;
4521838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"G") == 0)
4531838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_G;
4541838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"B") == 0)
4551838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_B;
4561838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (LocaleCompare(value,"A") == 0)
4571838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=IMF_WRITE_A;
4581838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else
4591838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
4601838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          "ignoring invalid defined exr:color-type","=%s",value);
4611838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy   }
4621838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  sampling_factor=(const char *) NULL;
4631838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  factors[0]=0;
4641838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  if (image_info->sampling_factor != (char *) NULL)
4651838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    sampling_factor=image_info->sampling_factor;
4661838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  if (sampling_factor != NULL)
4671838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    {
4681838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      /*
4691838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        Sampling factors, valid values are 1x1 or 2x2.
4701838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      */
4711838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      if (sscanf(sampling_factor,"%d:%d:%d",factors,factors+1,factors+2) == 3)
4721838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        {
4731838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          if ((factors[0] == factors[1]) && (factors[1] == factors[2]))
4741838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            factors[0]=1;
4751838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          else
4761838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            if ((factors[0] == (2*factors[1])) && (factors[2] == 0))
4771838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy              factors[0]=2;
4781838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        }
4791838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else
4801838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        if (sscanf(sampling_factor,"%dx%d",factors,factors+1) == 2)
4811838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          {
4821838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            if (factors[0] != factors[1])
4831838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy              factors[0]=0;
4841838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          }
4851838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      if ((factors[0] != 1) && (factors[0] != 2))
4861838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
4871838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          "ignoring sampling-factor","=%s",sampling_factor);
4881838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else if (channels != 0)
4891838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        {
4901838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          /*
4911838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            Cross check given color type and subsampling.
4921838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          */
4931838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          factors[1]=((channels == IMF_WRITE_YCA) ||
4941838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            (channels == IMF_WRITE_YC)) ? 2 : 1;
4951838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          if (factors[0] != factors[1])
4961838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy            (void) ThrowMagickException(exception,GetMagickModule(),
4971838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy              CoderWarning,"sampling-factor and color type mismatch","=%s",
4981838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy              sampling_factor);
4991838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        }
5001838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    }
5011838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  if (channels == 0)
5021838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    {
5031838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      /*
5041838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        If no color type given, select it now.
5051838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      */
5061838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      if (factors[0] == 2)
5071838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=image->alpha_trait != UndefinedPixelTrait ? IMF_WRITE_YCA :
5081838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          IMF_WRITE_YC;
5091838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy      else
5101838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy        channels=image->alpha_trait != UndefinedPixelTrait ? IMF_WRITE_RGBA :
5111838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy          IMF_WRITE_RGB;
5121838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy    }
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHeaderSetCompression(hdr_info,compression);
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfHeaderSetLineOrder(hdr_info,IMF_INCREASING_Y);
5151838bfe51181cf4bf37f34ee3dc7740c55f6f56fcristy  file=ImfOpenOutputFile(write_info->filename,hdr_info,channels);
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ImfDeleteHeader(hdr_info);
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (file == (ImfOutputFile *) NULL)
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
519ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      (void) RelinquishUniqueFileResource(write_info->filename);
520ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      write_info=DestroyImageInfo(write_info);
5211e178e70fb3c956f9fc1e30c3ba863e882666465cristy      ThrowFileException(exception,BlobError,"UnableToOpenBlob",
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImfErrorMessage());
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return(MagickFalse);
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scanline=(ImfRgba *) AcquireQuantumMemory(image->columns,sizeof(*scanline));
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (scanline == (ImfRgba *) NULL)
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      (void) ImfCloseOutputFile(file);
529ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      (void) RelinquishUniqueFileResource(write_info->filename);
530ce6b1224b32707d1eaeb77be461f76fe4e245e04dirk      write_info=DestroyImageInfo(write_info);
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
53396eafde4b1b6ac9d4197c8120e5a2f25f3f4a981cristy  ResetMagickMemory(scanline,0,image->columns*sizeof(*scanline));
534bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  for (y=0; y < (ssize_t) image->rows; y++)
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5361e178e70fb3c956f9fc1e30c3ba863e882666465cristy    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
5374c08aed51c5899665ade97263692328eea4af106cristy    if (p == (const Quantum *) NULL)
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      break;
539bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    for (x=0; x < (ssize_t) image->columns; x++)
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5414c08aed51c5899665ade97263692328eea4af106cristy      ImfFloatToHalf(QuantumScale*GetPixelRed(image,p),&half_quantum);
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scanline[x].r=half_quantum;
5434c08aed51c5899665ade97263692328eea4af106cristy      ImfFloatToHalf(QuantumScale*GetPixelGreen(image,p),&half_quantum);
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scanline[x].g=half_quantum;
5454c08aed51c5899665ade97263692328eea4af106cristy      ImfFloatToHalf(QuantumScale*GetPixelBlue(image,p),&half_quantum);
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scanline[x].b=half_quantum;
54717f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy      if (image->alpha_trait == UndefinedPixelTrait)
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        ImfFloatToHalf(1.0,&half_quantum);
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
5504c08aed51c5899665ade97263692328eea4af106cristy        ImfFloatToHalf(QuantumScale*GetPixelAlpha(image,p),&half_quantum);
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      scanline[x].a=half_quantum;
552ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy      p+=GetPixelChannels(image);
5533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ImfOutputSetFrameBuffer(file,scanline-(y*image->columns),1,image->columns);
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    ImfOutputWritePixels(file,1);
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) ImfCloseOutputFile(file);
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  scanline=(ImfRgba *) RelinquishMagickMemory(scanline);
559c82a27bb8e3138ff9bbf0f696663bdf3e704cedecristy  (void) FileToImage(image,write_info->filename,exception);
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) RelinquishUniqueFileResource(write_info->filename);
5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  write_info=DestroyImageInfo(write_info);
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  (void) CloseBlob(image);
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return(MagickTrue);
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif
566