Add framework to support the Cube LUT image format
diff --git a/coders/cube.c b/coders/cube.c
new file mode 100644
index 0000000..e84f9c8
--- /dev/null
+++ b/coders/cube.c
@@ -0,0 +1,277 @@
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%                         CCCC  U   U  BBBB   EEEEE                           %
+%                        C      U   U  B   B  E                               %
+%                        C      U   U  BBBB   EEE                             %
+%                        C      U   U  B   B  E                               %
+%                         CCCC   UUU   BBBB   EEEEE                           %
+%                                                                             %
+%                                                                             %
+%                           Cube LUT Image Format                             %
+%                                                                             %
+%                              Software Design                                %
+%                                   Cristy                                    %
+%                                 July 2018                                   %
+%                                                                             %
+%                                                                             %
+%  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
+%  dedicated to making software imaging solutions freely available.           %
+%                                                                             %
+%  You may not use this file except in compliance with the License.  You may  %
+%  obtain a copy of the License at                                            %
+%                                                                             %
+%    https://imagemagick.org/script/license.php                               %
+%                                                                             %
+%  Unless required by applicable law or agreed to in writing, software        %
+%  distributed under the License is distributed on an "AS IS" BASIS,          %
+%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
+%  See the License for the specific language governing permissions and        %
+%  limitations under the License.                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+*/
+
+/*
+  Include declarations.
+*/
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/module.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/resource_.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
+#include "MagickCore/thread-private.h"
+^L
+/*
+  Forward declarations.
+*/
+static MagickBooleanType
+  WriteCUBEImage(const ImageInfo *,Image *,ExceptionInfo *);
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e a d H A L D I m a g e                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadCUBEImage() creates a Cube color lookup table image and returns it.  It
+%  allocates the memory necessary for the new Image structure and returns a
+%  pointer to the new image.
+%
+%  The format of the ReadCUBEImage method is:
+%
+%      Image *ReadCUBEImage(const ImageInfo *image_info,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: the image info.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+static Image *ReadCUBEImage(const ImageInfo *image_info,
+  ExceptionInfo *exception)
+{
+  Image
+    *image;
+
+  MagickBooleanType
+    status;
+
+  size_t
+    cube_size,
+    level;
+
+  ssize_t
+    y;
+
+  /*
+    Create CUBE color lookup table image.
+  */
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickCoreSignature);
+  image=AcquireImage(image_info,exception);
+  level=0;
+  if (*image_info->filename != '\0')
+    level=StringToUnsignedLong(image_info->filename);
+  if (level < 2)
+    level=8;
+  status=MagickTrue;
+  cube_size=level*level;
+  image->columns=(size_t) (level*cube_size);
+  image->rows=(size_t) (level*cube_size);
+  status=SetImageExtent(image,image->columns,image->rows,exception);
+  if (status == MagickFalse)
+    return(DestroyImageList(image));
+  for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) level)
+  {
+    ssize_t
+      blue,
+      green,
+      red;
+
+    register Quantum
+      *magick_restrict q;
+
+    if (status == MagickFalse)
+      continue;
+    q=QueueAuthenticPixels(image,0,y,image->columns,(size_t) level,exception);
+    if (q == (Quantum *) NULL)
+      {
+        status=MagickFalse;
+        continue;
+      }
+    blue=y/(ssize_t) level;
+    for (green=0; green < (ssize_t) cube_size; green++)
+    {
+      for (red=0; red < (ssize_t) cube_size; red++)
+      {
+        SetPixelRed(image,ClampToQuantum(QuantumRange*red/(cube_size-1.0)),q);
+        SetPixelGreen(image,ClampToQuantum(QuantumRange*green/(cube_size-1.0)),
+          q);
+        SetPixelBlue(image,ClampToQuantum(QuantumRange*blue/(cube_size-1.0)),q);
+        SetPixelAlpha(image,OpaqueAlpha,q);
+        q+=GetPixelChannels(image);
+      }
+    }
+    if (SyncAuthenticPixels(image,exception) == MagickFalse)
+      status=MagickFalse;
+  }
+  return(GetFirstImageInList(image));
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e g i s t e r H A L D I m a g e                                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  RegisterCUBEImage() adds attributes for the Hald color lookup table image
+%  format to the list of supported formats.  The attributes include the image
+%  format tag, a method to read and/or write the format, whether the format
+%  supports the saving of more than one frame to the same file or blob, whether
+%  the format supports native in-memory I/O, and a brief description of the
+%  format.
+%
+%  The format of the RegisterCUBEImage method is:
+%
+%      size_t RegisterCUBEImage(void)
+%
+*/
+ModuleExport size_t RegisterCUBEImage(void)
+{
+  MagickInfo
+    *entry;
+
+  entry=AcquireMagickInfo("CUBE","CUBE",
+    "Identity Cube color lookup table image");
+  entry->decoder=(DecodeImageHandler *) ReadCUBEImage;
+  entry->encoder=(EncodeImageHandler *) WriteCUBEImage;
+  entry->flags^=CoderAdjoinFlag;
+  entry->format_type=ImplicitFormatType;
+  entry->flags|=CoderRawSupportFlag;
+  entry->flags|=CoderEndianSupportFlag;
+  (void) RegisterMagickInfo(entry);
+  return(MagickImageCoderSignature);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   U n r e g i s t e r H A L D I m a g e                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  UnregisterCUBEImage() removes format registrations made by the
+%  CUBE module from the list of supported formats.
+%
+%  The format of the UnregisterCUBEImage method is:
+%
+%      UnregisterCUBEImage(void)
+%
+*/
+ModuleExport void UnregisterCUBEImage(void)
+{
+  (void) UnregisterMagickInfo("CUBE");
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   W r i t e C U B E I m a g e                                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteCUBEImage an image in the Cube coloe lookup table image format.
+%
+%  The format of the WriteCUBEImage method is:
+%
+%      MagickBooleanType WriteCUBEImage(const ImageInfo *image_info,
+%        Image *image,ExceptionInfo *exception)
+%
+%  A description of each parameter follows.
+%
+%    o image_info: the image info.
+%
+%    o image:  The image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+static MagickBooleanType WriteCUBEImage(const ImageInfo *image_info,
+  Image *image,ExceptionInfo *exception)
+{
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickCoreSignature);
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickCoreSignature);
+  assert(exception != (ExceptionInfo *) NULL);
+  (void) exception;
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  return(MagickTrue);
+}