Add framework to support the Cube LUT image format
diff --git a/coders/Makefile.am b/coders/Makefile.am
index 116c661..d34e653 100644
--- a/coders/Makefile.am
+++ b/coders/Makefile.am
@@ -109,6 +109,7 @@
 	coders/cip.c \
 	coders/clip.c \
 	coders/cmyk.c \
+	coders/cube.c \
 	coders/cut.c \
 	coders/dcm.c \
 	coders/dds.c \
@@ -241,6 +242,7 @@
 	coders/coders.h \
 	coders/coders-list.h \
 	coders/coders-private.h \
+	coders/cube.h \
 	coders/cut.h \
 	coders/dcm.h \
 	coders/dds.h \
@@ -372,6 +374,7 @@
 	coders/cip.la \
 	coders/clip.la \
 	coders/cmyk.la \
+	coders/cube.la \
 	coders/cut.la \
 	coders/dcm.la \
 	coders/dds.la \
@@ -566,6 +569,12 @@
 coders_cmyk_la_LDFLAGS     = $(MODULECOMMONFLAGS)
 coders_cmyk_la_LIBADD      = $(MAGICKCORE_LIBS)
 
+# CUBE coder module
+coders_cube_la_SOURCES     = coders/cube.c
+coders_cube_la_CPPFLAGS    = $(MAGICK_CODER_CPPFLAGS)
+coders_cube_la_LDFLAGS     = $(MODULECOMMONFLAGS)
+coders_cube_la_LIBADD      = $(MAGICKCORE_LIBS) $(GOMP_LIBS)
+
 # CUT coder module
 coders_cut_la_SOURCES      = coders/cut.c
 coders_cut_la_CPPFLAGS     = $(MAGICK_CODER_CPPFLAGS)
diff --git a/coders/coders.h b/coders/coders.h
index 5345f5d..65bcec4 100644
--- a/coders/coders.h
+++ b/coders/coders.h
@@ -34,6 +34,7 @@
 #endif
 #include "coders/clip.h"
 #include "coders/cmyk.h"
+#include "coders/cube.h"
 #include "coders/cut.h"
 #include "coders/dcm.h"
 #include "coders/dds.h"
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);
+}
diff --git a/coders/cube.h b/coders/cube.h
new file mode 100644
index 0000000..c865fe9
--- /dev/null
+++ b/coders/cube.h
@@ -0,0 +1,31 @@
+/*
+  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.
+  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 "coders/coders-private.h"
+
+#define MagickCUBEHeaders
+
+#define MagickCUBEAliases
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+MagickCoderExports(CUBE)
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif