]> granicus.if.org Git - imagemagick/blobdiff - coders/jp2.c
(no commit message)
[imagemagick] / coders / jp2.c
index 0f61cbc85cccdeb32b9f806ba81f90c9e2cb1a53..02f09ab5bb05d998663439f1f281cc3a99d20238 100644 (file)
@@ -17,7 +17,7 @@
 %                                 June 2001                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2012 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  %
 /*
   Include declarations.
 */
-#include "magick/studio.h"
-#include "magick/blob.h"
-#include "magick/blob-private.h"
-#include "magick/cache.h"
-#include "magick/colorspace.h"
-#include "magick/color.h"
-#include "magick/color-private.h"
-#include "magick/exception.h"
-#include "magick/exception-private.h"
-#include "magick/image.h"
-#include "magick/image-private.h"
-#include "magick/list.h"
-#include "magick/magick.h"
-#include "magick/memory_.h"
-#include "magick/monitor.h"
-#include "magick/monitor-private.h"
-#include "magick/option.h"
-#include "magick/profile.h"
-#include "magick/quantum-private.h"
-#include "magick/static.h"
-#include "magick/statistic.h"
-#include "magick/string_.h"
-#include "magick/module.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/attribute.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
+#include "MagickCore/color.h"
+#include "MagickCore/color-private.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/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/statistic.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/module.h"
 #if defined(MAGICKCORE_JP2_DELEGATE)
 #ifndef JAS_IMAGE_CM_GRAY
 #define JAS_IMAGE_CM_GRAY JAS_IMAGE_CS_GRAY
 #if !defined(uint)
 #define uint  unsigned int
 #endif
-#if !defined(longlong)
-#define longlong  long long
+#if !defined(ssize_tssize_t)
+#define ssize_tssize_t  long long
 #endif
-#if !defined(ulonglong)
-#define ulonglong  unsigned long long
+#if !defined(ussize_tssize_t)
+#define ussize_tssize_t  unsigned long long
 #endif
 
-#ifdef __VMS
-#define JAS_VERSION 1.700.0
-#define PACKAGE jasper
-#define VERSION 1.700.0
-#endif
 #undef PACKAGE_NAME
 #undef PACKAGE_STRING
 #undef PACKAGE_TARNAME
 */
 #if defined(MAGICKCORE_JP2_DELEGATE)
 static MagickBooleanType
-  WriteJP2Image(const ImageInfo *,Image *);
+  WriteJP2Image(const ImageInfo *,Image *,ExceptionInfo *);
+
+static volatile MagickBooleanType
+  instantiate_jp2 = MagickFalse;
 #endif
 \f
 /*
@@ -261,7 +262,8 @@ static int BlobClose(jas_stream_obj_t *object)
 
   source=(StreamManager *) object;
   (void) CloseBlob(source->image);
-  source=(StreamManager *) RelinquishMagickMemory(source);
+  free(source);
+  source=(StreamManager *) NULL;
   return(0);
 }
 
@@ -347,31 +349,30 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
   jas_stream_t
     *jp2_stream;
 
-  long
-    components[4],
-    y;
-
   MagickBooleanType
     status;
 
   QuantumAny
     pixel,
-    *map[4],
-    range;
+    range[4];
 
-  register long
+  register ssize_t
     i,
     x;
 
-  register PixelPacket
+  register Quantum
     *q;
 
-  unsigned long
+  size_t
     maximum_component_depth,
     number_components,
     x_step[4],
     y_step[4];
 
+  ssize_t
+    components[4],
+    y;
+
   /*
     Open image file.
   */
@@ -382,7 +383,7 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
       image_info->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  image=AcquireImage(image_info);
+  image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
@@ -466,15 +467,17 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
   image->columns=jas_image_width(jp2_image);
   image->rows=jas_image_height(jp2_image);
   image->compression=JPEG2000Compression;
-  for (i=0; i < (long) number_components; i++)
+  if (number_components == 1)
+    image->colorspace=GRAYColorspace;
+  for (i=0; i < (ssize_t) number_components; i++)
   {
-    unsigned long
+    size_t
       height,
       width;
 
-    width=(unsigned long) (jas_image_cmptwidth(jp2_image,components[i])*
+    width=(size_t) (jas_image_cmptwidth(jp2_image,components[i])*
       jas_image_cmpthstep(jp2_image,components[i]));
-    height=(unsigned long) (jas_image_cmptheight(jp2_image,components[i])*
+    height=(size_t) (jas_image_cmptheight(jp2_image,components[i])*
       jas_image_cmptvstep(jp2_image,components[i]));
     x_step[i]=(unsigned int) jas_image_cmpthstep(jp2_image,components[i]);
     y_step[i]=(unsigned int) jas_image_cmptvstep(jp2_image,components[i]);
@@ -494,7 +497,7 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
   */
   image->matte=number_components > 3 ? MagickTrue : MagickFalse;
   maximum_component_depth=0;
-  for (i=0; i < (long) number_components; i++)
+  for (i=0; i < (ssize_t) number_components; i++)
   {
     maximum_component_depth=(unsigned int) MagickMax((size_t)
       jas_image_cmptprec(jp2_image,components[i]),(size_t)
@@ -515,35 +518,18 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
       jas_image_destroy(jp2_image);
       return(GetFirstImageInList(image));
     }
-  for (i=0; i < (long) number_components; i++)
-  {
-    long
-      j;
-
-    map[i]=(QuantumAny *) AcquireQuantumMemory(MaxMap+1,sizeof(**map));
-    if (map[i] == (QuantumAny *) NULL)
-      {
-        for (--i; i >= 0; i--)
-          map[i]=(QuantumAny *) RelinquishMagickMemory(map[i]);
-        for (i=0; i < (long) number_components; i++)
-          jas_matrix_destroy(pixels[i]);
-        jas_image_destroy(jp2_image);
-        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-      }
-    range=GetQuantumRange((unsigned long) jas_image_cmptprec(jp2_image,
+  for (i=0; i < (ssize_t) number_components; i++)
+    range[i]=GetQuantumRange((size_t) jas_image_cmptprec(jp2_image,
       components[i]));
-    for (j=0; j <= (long) MaxMap; j++)
-      map[i][j]=ScaleQuantumToMap(ScaleAnyToQuantum((QuantumAny) j,range));
-  }
-  for (y=0; y < (long) image->rows; y++)
+  for (y=0; y < (ssize_t) image->rows; y++)
   {
     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
-    if (q == (PixelPacket *) NULL)
+    if (q == (Quantum *) NULL)
       break;
-    for (i=0; i < (long) number_components; i++)
+    for (i=0; i < (ssize_t) number_components; i++)
       (void) jas_image_readcmpt(jp2_image,(short) components[i],0,
-        ((unsigned int) y)/y_step[i],((unsigned int) image->columns)/x_step[i],
-        1,pixels[i]);
+        (jas_image_coord_t) (y/y_step[i]),(jas_image_coord_t) (image->columns/
+        x_step[i]),1,pixels[i]);
     switch (number_components)
     {
       case 1:
@@ -551,13 +537,11 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
         /*
           Grayscale.
         */
-        for (x=0; x < (long) image->columns; x++)
+        for (x=0; x < (ssize_t) image->columns; x++)
         {
           pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
-          q->red=(Quantum) map[0][pixel];
-          q->green=q->red;
-          q->blue=q->red;
-          q++;
+          SetPixelGray(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
+          q+=GetPixelChannels(image);
         }
         break;
       }
@@ -566,15 +550,15 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
         /*
           RGB.
         */
-        for (x=0; x < (long) image->columns; x++)
+        for (x=0; x < (ssize_t) image->columns; x++)
         {
           pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
-          q->red=(Quantum) map[0][pixel];
+          SetPixelRed(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
           pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
-          q->green=(Quantum) map[1][pixel];
+          SetPixelGreen(image,ScaleAnyToQuantum((QuantumAny) pixel,range[1]),q);
           pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
-          q->blue=(Quantum) map[2][pixel];
-          q++;
+          SetPixelBlue(image,ScaleAnyToQuantum((QuantumAny) pixel,range[2]),q);
+          q+=GetPixelChannels(image);
         }
         break;
       }
@@ -583,29 +567,28 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
         /*
           RGBA.
         */
-        for (x=0; x < (long) image->columns; x++)
+        for (x=0; x < (ssize_t) image->columns; x++)
         {
           pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
-          q->red=(Quantum) map[0][pixel];
+          SetPixelRed(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
           pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
-          q->green=(Quantum) map[1][pixel];
+          SetPixelGreen(image,ScaleAnyToQuantum((QuantumAny) pixel,range[1]),q);
           pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
-          q->blue=(Quantum) map[2][pixel];
+          SetPixelBlue(image,ScaleAnyToQuantum((QuantumAny) pixel,range[2]),q);
           pixel=(QuantumAny) jas_matrix_getv(pixels[3],x/x_step[3]);
-          q->opacity=(Quantum) map[3][(QuantumAny) (QuantumRange-pixel)];
-          q++;
+          SetPixelAlpha(image,ScaleAnyToQuantum((QuantumAny) pixel,range[3]),q);
+          q+=GetPixelChannels(image);
         }
         break;
       }
     }
     if (SyncAuthenticPixels(image,exception) == MagickFalse)
       break;
-    status=SetImageProgress(image,LoadImageTag,y,image->rows);
+    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
+      image->rows);
     if (status == MagickFalse)
       break;
   }
-  for (i=0; i < (long) number_components; i++)
-    map[i]=(QuantumAny *) RelinquishMagickMemory(map[i]);
   cm_profile=jas_image_cmprof(jp2_image);
   icc_profile=(jas_iccprof_t *) NULL;
   if (cm_profile != (jas_cmprof_t *) NULL)
@@ -633,12 +616,13 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
           blob=(jas_stream_memobj_t *) icc_stream->obj_;
           if (image->debug != MagickFalse)
             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-              "Profile: ICC, %lu bytes",(unsigned long) blob->len_);
-          profile=AcquireStringInfo(blob->len_);
-          SetStringInfoDatum(profile,blob->buf_);
+              "Profile: ICC, %.20g bytes",(double) blob->len_);
+          profile=BlobToStringInfo(blob->buf_,blob->len_);
+          if (profile == (StringInfo *) NULL)
+            ThrowReaderException(CorruptImageError,"MemoryAllocationFailed");
           icc_profile=(StringInfo *) GetImageProfile(image,"icc");
           if (icc_profile == (StringInfo *) NULL)
-            (void) SetImageProfile(image,"icc",profile);
+            (void) SetImageProfile(image,"icc",profile,exception);
           else
             (void) ConcatenateStringInfo(icc_profile,profile);
           profile=DestroyStringInfo(profile);
@@ -647,7 +631,7 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
     }
   (void) jas_stream_close(jp2_stream);
   jas_image_destroy(jp2_image);
-  for (i=0; i < (long) number_components; i++)
+  for (i=0; i < (ssize_t) number_components; i++)
     jas_matrix_destroy(pixels[i]);
   return(GetFirstImageInList(image));
 }
@@ -672,10 +656,10 @@ static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
 %
 %  The format of the RegisterJP2Image method is:
 %
-%      unsigned long RegisterJP2Image(void)
+%      size_t RegisterJP2Image(void)
 %
 */
-ModuleExport unsigned long RegisterJP2Image(void)
+ModuleExport size_t RegisterJP2Image(void)
 {
   MagickInfo
     *entry;
@@ -694,7 +678,19 @@ ModuleExport unsigned long RegisterJP2Image(void)
   (void) RegisterMagickInfo(entry);
   entry=SetMagickInfo("JPC");
   entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
-  entry->module=ConstantString("JPC");
+  entry->module=ConstantString("JP2");
+  entry->magick=(IsImageFormatHandler *) IsJPC;
+  entry->adjoin=MagickFalse;
+  entry->seekable_stream=MagickTrue;
+  entry->thread_support=NoThreadSupport;
+#if defined(MAGICKCORE_JP2_DELEGATE)
+  entry->decoder=(DecodeImageHandler *) ReadJP2Image;
+  entry->encoder=(EncodeImageHandler *) WriteJP2Image;
+#endif
+  (void) RegisterMagickInfo(entry);
+  entry=SetMagickInfo("J2C");
+  entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
+  entry->module=ConstantString("JP2");
   entry->magick=(IsImageFormatHandler *) IsJPC;
   entry->adjoin=MagickFalse;
   entry->seekable_stream=MagickTrue;
@@ -706,7 +702,7 @@ ModuleExport unsigned long RegisterJP2Image(void)
   (void) RegisterMagickInfo(entry);
   entry=SetMagickInfo("JPX");
   entry->description=ConstantString("JPEG-2000 File Format Syntax");
-  entry->module=ConstantString("JPX");
+  entry->module=ConstantString("JP2");
   entry->magick=(IsImageFormatHandler *) IsJPC;
   entry->adjoin=MagickFalse;
   entry->seekable_stream=MagickTrue;
@@ -718,7 +714,7 @@ ModuleExport unsigned long RegisterJP2Image(void)
   (void) RegisterMagickInfo(entry);
   entry=SetMagickInfo("PGX");
   entry->description=ConstantString("JPEG-2000 VM Format");
-  entry->module=ConstantString("PGX");
+  entry->module=ConstantString("JP2");
   entry->magick=(IsImageFormatHandler *) IsJPC;
   entry->adjoin=MagickFalse;
   entry->seekable_stream=MagickTrue;
@@ -728,7 +724,11 @@ ModuleExport unsigned long RegisterJP2Image(void)
 #endif
   (void) RegisterMagickInfo(entry);
 #if defined(MAGICKCORE_JP2_DELEGATE)
-  jas_init();
+  if (instantiate_jp2 == MagickFalse)
+    {
+      jas_init();
+      instantiate_jp2=MagickTrue;
+    }
 #endif
   return(MagickImageCoderSignature);
 }
@@ -754,11 +754,16 @@ ModuleExport unsigned long RegisterJP2Image(void)
 */
 ModuleExport void UnregisterJP2Image(void)
 {
-  (void) UnregisterMagickInfo("JP2");
-  (void) UnregisterMagickInfo("JPC");
   (void) UnregisterMagickInfo("PGX");
+  (void) UnregisterMagickInfo("J2C");
+  (void) UnregisterMagickInfo("JPC");
+  (void) UnregisterMagickInfo("JP2");
 #if defined(MAGICKCORE_JP2_DELEGATE)
-  jas_cleanup();
+  if (instantiate_jp2 != MagickFalse)
+    {
+      jas_cleanup();
+      instantiate_jp2=MagickFalse;
+    }
 #endif
 }
 \f
@@ -780,7 +785,8 @@ ModuleExport void UnregisterJP2Image(void)
 %
 %  The format of the WriteJP2Image method is:
 %
-%      MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
+%      MagickBooleanType WriteJP2Image(const ImageInfo *image_info,
+%        Image *image,ExceptionInfo *exception)
 %
 %  A description of each parameter follows.
 %
@@ -788,8 +794,11 @@ ModuleExport void UnregisterJP2Image(void)
 %
 %    o image:  The image.
 %
+%    o exception: return any errors or warnings in this structure.
+%
 */
-static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
+static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image,
+  ExceptionInfo *exception)
 {
   char
     *key,
@@ -799,10 +808,6 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
   const char
     *option;
 
-  long
-    format,
-    y;
-
   jas_image_cmptparm_t
     component_info[4];
 
@@ -821,19 +826,20 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
   QuantumAny
     range;
 
-  register const PixelPacket
+  register const Quantum
     *p;
 
-  register long
+  register ssize_t
     i,
     x;
 
-  unsigned short
-    *map;
-
-  unsigned long
+  size_t
     number_components;
 
+  ssize_t
+    format,
+    y;
+
   /*
     Open image file.
   */
@@ -843,26 +849,28 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(status);
   /*
-    Intialize JPEG 2000 API.
+    Initialize JPEG 2000 API.
   */
-  if (image->colorspace != RGBColorspace)
-    (void) TransformImageColorspace(image,RGBColorspace);
+  if (IsRGBColorspace(image->colorspace) == MagickFalse)
+    (void) TransformImageColorspace(image,sRGBColorspace,exception);
   jp2_stream=JP2StreamManager(image);
   if (jp2_stream == (jas_stream_t *) NULL)
     ThrowWriterException(DelegateError,"UnableToManageJP2Stream");
   number_components=image->matte ? 4UL : 3UL;
   if ((image_info->type != TrueColorType) &&
-      IsGrayImage(image,&image->exception))
+      (IsImageGray(image,exception) != MagickFalse))
     number_components=1;
   if ((image->columns != (unsigned int) image->columns) ||
       (image->rows != (unsigned int) image->rows))
     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
   (void) ResetMagickMemory(&component_info,0,sizeof(component_info));
-  for (i=0; i < (long) number_components; i++)
+  for (i=0; i < (ssize_t) number_components; i++)
   {
     component_info[i].tlx=0;
     component_info[i].tly=0;
@@ -872,7 +880,6 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
     component_info[i].height=(unsigned int) image->rows;
     component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2);
     component_info[i].sgnd=MagickFalse;
-    
   }
   jp2_image=jas_image_create((int) number_components,component_info,
     JAS_CLRSPC_UNKNOWN);
@@ -894,18 +901,18 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
       */
       jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB);
       jas_image_setcmpttype(jp2_image,0,
-        JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
+        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
       jas_image_setcmpttype(jp2_image,1,
-        JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
+        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
       jas_image_setcmpttype(jp2_image,2,
-        JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
+        (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
       if (number_components == 4)
         jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
     }
   /*
     Convert to JPEG 2000 pixels.
   */
-  for (i=0; i < (long) number_components; i++)
+  for (i=0; i < (ssize_t) number_components; i++)
   {
     pixels[i]=jas_matrix_create(1,(int) image->columns);
     if (pixels[i] == (jas_matrix_t *) NULL)
@@ -916,70 +923,62 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
       }
   }
-  range=GetQuantumRange((unsigned long) component_info[0].prec);
-  map=(unsigned short *) AcquireQuantumMemory(MaxMap+1,sizeof(*map));
-  for (i=0; i <= (long) MaxMap; i++)
-    map[i]=(unsigned short) ScaleQuantumToMap((Quantum)
-      ScaleQuantumToAny((Quantum) i,range));
-  if (map == (unsigned short *) NULL)
-    {
-      for (i=0; i < (long) number_components; i++)
-        jas_matrix_destroy(pixels[i]);
-      jas_image_destroy(jp2_image);
-      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
-    }
-  for (y=0; y < (long) image->rows; y++)
+  range=GetQuantumRange((size_t) component_info[0].prec);
+  for (y=0; y < (ssize_t) image->rows; y++)
   {
-    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
-    if (p == (const PixelPacket *) NULL)
+    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+    if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (long) image->columns; x++)
+    for (x=0; x < (ssize_t) image->columns; x++)
     {
       if (number_components == 1)
-        jas_matrix_setv(pixels[0],x,map[ScaleQuantumToMap(
-          PixelIntensityToQuantum(p))]);
+        jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
+          GetPixelIntensity(image,p),range));
       else
         {
-          jas_matrix_setv(pixels[0],x,map[ScaleQuantumToMap(p->red)]);
-          jas_matrix_setv(pixels[1],x,map[ScaleQuantumToMap(p->green)]);
-          jas_matrix_setv(pixels[2],x,map[ScaleQuantumToMap(p->blue)]);
+          jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
+            GetPixelRed(image,p),range));
+          jas_matrix_setv(pixels[1],x,(jas_seqent_t) ScaleQuantumToAny(
+            GetPixelGreen(image,p),range));
+          jas_matrix_setv(pixels[2],x,(jas_seqent_t) ScaleQuantumToAny(
+            GetPixelBlue(image,p),range));
           if (number_components > 3)
-            jas_matrix_setv(pixels[3],x,map[ScaleQuantumToMap((Quantum)
-              (QuantumRange-p->opacity))]);
+            jas_matrix_setv(pixels[3],x,(jas_seqent_t) ScaleQuantumToAny(
+              GetPixelAlpha(image,p),range));
         }
-      p++;
+      p+=GetPixelChannels(image);
     }
-    for (i=0; i < (long) number_components; i++)
+    for (i=0; i < (ssize_t) number_components; i++)
       (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y,
         (unsigned int) image->columns,1,pixels[i]);
-    status=SetImageProgress(image,SaveImageTag,y,image->rows);
+    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
+      image->rows);
     if (status == MagickFalse)
       break;
   }
-  map=(unsigned short *) RelinquishMagickMemory(map);
   (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
+  if (LocaleCompare(magick,"J2C") == 0)
+    (void) CopyMagickString(magick,"JPC",MaxTextExtent);
   LocaleLower(magick);
   format=jas_image_strtofmt(magick);
   options=(char *) NULL;
   ResetImageOptionIterator(image_info);
   key=GetNextImageOption(image_info);
-  while (key != (char *) NULL)
+  for ( ; key != (char *) NULL; key=GetNextImageOption(image_info))
   {
     option=GetImageOption(image_info,key);
-    if (option != (const char *) NULL)
+    if (option == (const char *) NULL)
+      continue;
+    if (LocaleNCompare(key,"jp2:",4) == 0)
       {
-        if (LocaleNCompare(key,"jp2:",4) == 0)
+        (void) ConcatenateString(&options,key+4);
+        if (*option != '\0')
           {
-            (void) ConcatenateString(&options,key+4);
-            if (*option != '\0')
-              {
-                (void) ConcatenateString(&options,"=");
-                (void) ConcatenateString(&options,option);
-              }
-            (void) ConcatenateString(&options," ");
+            (void) ConcatenateString(&options,"=");
+            (void) ConcatenateString(&options,option);
           }
-       }
-    key=GetNextImageOption(image_info);
+        (void) ConcatenateString(&options," ");
+      }
   }
   option=GetImageOption(image_info,"jp2:rate");
   if ((option == (const char *) NULL) &&
@@ -1006,13 +1005,15 @@ static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
         (GetImageQuantumDepth(image,MagickTrue)/8);
       target_size=(number_pixels*rate)+header_size;
       rate=target_size/number_pixels;
-      (void) FormatMagickString(option,MaxTextExtent,"rate=%g",rate);
+      (void) FormatLocaleString(option,MaxTextExtent,"rate=%g",rate);
       (void) ConcatenateString(&options,option);
     }
   status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ?
     MagickTrue : MagickFalse;
+  if (options != (char *) NULL)
+    options=DestroyString(options);
   (void) jas_stream_close(jp2_stream);
-  for (i=0; i < (long) number_components; i++)
+  for (i=0; i < (ssize_t) number_components; i++)
     jas_matrix_destroy(pixels[i]);
   jas_image_destroy(jp2_image);
   if (status != MagickFalse)