]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Mon, 13 Aug 2012 16:03:09 +0000 (16:03 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Mon, 13 Aug 2012 16:03:09 +0000 (16:03 +0000)
coders/jnx.c

index d0433633d99fe0b47972d7032a009fa203872e94..76a6de669371cc5373b7a2fba5ba349459466d88 100644 (file)
 #include "MagickCore/module.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
+#include "MagickCore/property.h"
 #include "MagickCore/pixel-accessor.h"
 #include "MagickCore/quantum-private.h"
 #include "MagickCore/static.h"
 #include "MagickCore/string_.h"
 \f
+typedef struct _JNXInfo
+{
+  unsigned int
+    version,
+    serial;
+
+  PointInfo
+    northeast,
+    southwest;
+
+  unsigned int
+    levels,
+    expire,
+    id,
+    crc,
+    signature;
+
+  int
+    offset;
+
+  unsigned int
+    order;
+} JNXInfo;
+
+typedef struct _JNXLevelInfo
+{
+  unsigned int
+    count;
+
+  int
+    offset;
+
+  unsigned int
+    scale;
+
+  char
+    copyright[MaxTextExtent];
+} JNXLevelInfo;
+\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
 */
 static Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
-  return((Image *) NULL);
+#define JNXMaxLevels  20
+
+  Image
+    *image,
+    *images;
+
+  JNXInfo
+    jnx_info;
+
+  JNXLevelInfo
+    jnx_level_info[JNXMaxLevels];
+
+  MagickBooleanType
+    status;
+
+  register ssize_t
+    i;
+
+  /*
+    Open image file.
+  */
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  image=AcquireImage(image_info,exception);
+  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
+  if (status == MagickFalse)
+    {
+      image=DestroyImageList(image);
+      return((Image *) NULL);
+    }
+  /*
+    Read JNX header.
+  */
+  (void) ResetMagickMemory(&jnx_info,0,sizeof(jnx_info));
+  jnx_info.version=ReadBlobLSBLong(image);
+  if (jnx_info.version > 4)
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  jnx_info.serial=ReadBlobLSBLong(image);
+  jnx_info.northeast.x=(double) ReadBlobLSBLong(image);
+  jnx_info.northeast.y=(double) ReadBlobLSBLong(image);
+  jnx_info.southwest.x=(double) ReadBlobLSBLong(image);
+  jnx_info.southwest.y=(double) ReadBlobLSBLong(image);
+  jnx_info.levels=ReadBlobLSBLong(image);
+  if (jnx_info.levels > JNXMaxLevels)
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  jnx_info.expire=ReadBlobLSBLong(image);
+  jnx_info.id=ReadBlobLSBLong(image);
+  jnx_info.crc=ReadBlobLSBLong(image);
+  jnx_info.signature=ReadBlobLSBLong(image);
+  jnx_info.offset=ReadBlobLSBLong(image);
+  if (jnx_info.version > 3)
+    jnx_info.order=(int) ReadBlobLSBLong(image);
+  /*
+    Read JNX levels.
+  */
+  (void) ResetMagickMemory(&jnx_level_info,0,sizeof(jnx_level_info));
+  for (i=0; i < (ssize_t) jnx_info.levels; i++)
+  {
+    jnx_level_info[i].count=ReadBlobLSBLong(image);
+    jnx_level_info[i].offset=(int) ReadBlobLSBLong(image);
+    jnx_level_info[i].scale=(int) ReadBlobLSBLong(image);
+    if (jnx_info.version > 3)
+      {
+        int
+          c;
+
+        register ssize_t
+          j;
+
+        (void) ReadBlobLSBLong(image);
+        j=0;
+        while ((c=ReadBlobLSBShort(image)) != 0)
+          if (j < (MaxTextExtent-1))
+            jnx_level_info[i].copyright[j++]=c;
+        jnx_level_info[i].copyright[j]='\0';
+      }
+  }
+  /*
+    Read JNX tiles.
+  */
+  images=NewImageList();
+  for (i=0; i < (ssize_t) jnx_info.levels; i++)
+  {
+    register ssize_t
+      j;
+
+    (void) SeekBlob(image,jnx_level_info[i].offset,SEEK_SET);
+    for (j=0; j < (ssize_t) jnx_level_info[i].count; j++)
+    {
+      Image
+        *tile_image;
+
+      ImageInfo
+        *read_info;
+
+      int
+        tile_offset;
+
+      MagickOffsetType
+        offset;
+
+      PointInfo
+        northeast,
+        southwest;
+
+      ssize_t
+        count;
+
+      unsigned char
+        *blob;
+
+      unsigned int
+        tile_length;
+
+      northeast.x=(double) ReadBlobLSBLong(image);
+      northeast.y=(double) ReadBlobLSBLong(image);
+      southwest.x=(double) ReadBlobLSBLong(image);
+      southwest.y=(double) ReadBlobLSBLong(image);
+      (void) ReadBlobLSBShort(image); /* width */
+      (void) ReadBlobLSBShort(image); /* height */
+      tile_length=ReadBlobLSBLong(image);
+      tile_offset=(int) ReadBlobLSBLong(image);
+      offset=TellBlob(image);
+      /*
+        Read a tile.
+      */
+      blob=(unsigned char *) AcquireMagickMemory((tile_length+2)*sizeof(*blob));
+      if (blob == (unsigned char *) NULL)
+        {
+          if (images != (Image *) NULL)
+            images=DestroyImageList(images);
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        }
+      (void) SeekBlob(image,tile_offset,SEEK_SET);
+      blob[0]=0xFF;
+      blob[1]=0xD8;
+      count=ReadBlob(image,tile_length,blob+2);
+      if (count != tile_length)
+        {
+          if (images != (Image *) NULL)
+            images=DestroyImageList(images);
+          blob=(unsigned char *) RelinquishMagickMemory(blob);
+          ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
+        }
+      read_info=CloneImageInfo(image_info);
+      (void) CopyMagickString(read_info->magick,"JPEG",MaxTextExtent);
+      tile_image=BlobToImage(read_info,blob,tile_length+2,exception);
+      read_info=DestroyImageInfo(read_info);
+      blob=(unsigned char *) RelinquishMagickMemory(blob);
+      (void) SeekBlob(image,offset,SEEK_SET);
+      if (tile_image == (Image *) NULL)
+        continue;
+      if (*jnx_level_info[i].copyright != '\0')
+        (void) SetImageProperty(tile_image,"jnx:copyright",
+          jnx_level_info[i].copyright,exception);
+      (void) FormatImageProperty(tile_image,"jnx:northeast","%g,%g",northeast.x,
+        northeast.y);
+      (void) FormatImageProperty(tile_image,"jnx:southwest","%g,%g",southwest.x,
+        southwest.y);
+      AppendImageToList(&images,tile_image);
+    }
+    if (image->progress_monitor != (MagickProgressMonitor) NULL)
+      {
+        MagickBooleanType
+          proceed;
+
+        proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) i,
+          (MagickSizeType) jnx_info.levels);
+        if (proceed == MagickFalse)
+          status=MagickFalse;
+      }
+  }
+  (void) CloseBlob(image);
+  image=DestroyImage(image);
+  if (images == (Image *) NULL)
+    return((Image *) NULL);
+  return(GetFirstImageInList(images));
 }
 \f
 /*
@@ -124,6 +345,7 @@ ModuleExport size_t RegisterJNXImage(void)
   entry=SetMagickInfo("JNX");
   entry->decoder=(DecodeImageHandler *) ReadJNXImage;
   entry->description=ConstantString("Garmin tile storage format");
+  entry->seekable_stream=MagickTrue;
   entry->module=ConstantString("JNX");
   (void) RegisterMagickInfo(entry);
   return(MagickImageCoderSignature);