184713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
284713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
484713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
584713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
684713a3f3c3faafc53488c0307d48bca0902bea9cristy%                              JJJ  N   N  X   X                              %
784713a3f3c3faafc53488c0307d48bca0902bea9cristy%                               J   NN  N   X X                               %
884713a3f3c3faafc53488c0307d48bca0902bea9cristy%                               J   N N N    X                                %
984713a3f3c3faafc53488c0307d48bca0902bea9cristy%                            J  J   N  NN   X X                               %
1084713a3f3c3faafc53488c0307d48bca0902bea9cristy%                             JJ    N   N  X   X                              %
1184713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
1284713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
1384713a3f3c3faafc53488c0307d48bca0902bea9cristy%                       Read/Write Garmin Image Format                        %
1484713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
15de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy%                                   Cristy                                    %
1684713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                 July 2012                                   %
1784713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
1884713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
197ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
2084713a3f3c3faafc53488c0307d48bca0902bea9cristy%  dedicated to making software imaging solutions freely available.           %
2184713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
2284713a3f3c3faafc53488c0307d48bca0902bea9cristy%  You may not use this file except in compliance with the License.  You may  %
2384713a3f3c3faafc53488c0307d48bca0902bea9cristy%  obtain a copy of the License at                                            %
2484713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
2584713a3f3c3faafc53488c0307d48bca0902bea9cristy%    http://www.imagemagick.org/script/license.php                            %
2684713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
2784713a3f3c3faafc53488c0307d48bca0902bea9cristy%  Unless required by applicable law or agreed to in writing, software        %
2884713a3f3c3faafc53488c0307d48bca0902bea9cristy%  distributed under the License is distributed on an "AS IS" BASIS,          %
2984713a3f3c3faafc53488c0307d48bca0902bea9cristy%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
3084713a3f3c3faafc53488c0307d48bca0902bea9cristy%  See the License for the specific language governing permissions and        %
3184713a3f3c3faafc53488c0307d48bca0902bea9cristy%  limitations under the License.                                             %
3284713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
3384713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3484713a3f3c3faafc53488c0307d48bca0902bea9cristy%
3584713a3f3c3faafc53488c0307d48bca0902bea9cristy%
3684713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
3784713a3f3c3faafc53488c0307d48bca0902bea9cristy
3884713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
3984713a3f3c3faafc53488c0307d48bca0902bea9cristy  Include declarations.
4084713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
4184713a3f3c3faafc53488c0307d48bca0902bea9cristy
4284713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
4384713a3f3c3faafc53488c0307d48bca0902bea9cristy  Include declarations.
4484713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
4584713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/studio.h"
4684713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/blob.h"
4784713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/blob-private.h"
4884713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/cache.h"
4984713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/colorspace.h"
5084713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/colorspace-private.h"
518d1c74e40dfa0406f2172531f652aac99a454075cristy#include "MagickCore/draw.h"
5284713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/exception.h"
5384713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/exception-private.h"
5484713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/image.h"
5584713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/image-private.h"
5684713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/list.h"
5784713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/magick.h"
5884713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/memory_.h"
5984713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/module.h"
6084713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/monitor.h"
6184713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/monitor-private.h"
62f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy#include "MagickCore/property.h"
6384713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/pixel-accessor.h"
6484713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/quantum-private.h"
6584713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/static.h"
6684713a3f3c3faafc53488c0307d48bca0902bea9cristy#include "MagickCore/string_.h"
6784713a3f3c3faafc53488c0307d48bca0902bea9cristy
68f2be7a37aa8f7f8c84489950241817f7db36fcf5cristytypedef struct _JNXInfo
69f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy{
7086a135da8eb3f25503c3bef128bcda8ec0eca446cristy  int
71f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    version,
72f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    serial;
73f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
74f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  PointInfo
75f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    northeast,
76f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    southwest;
77f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
7886a135da8eb3f25503c3bef128bcda8ec0eca446cristy  int
79f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    levels,
80f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    expire,
81f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    id,
82f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    crc,
83f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    signature;
84f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
8586a135da8eb3f25503c3bef128bcda8ec0eca446cristy  unsigned int
86f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    offset;
87f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
8886a135da8eb3f25503c3bef128bcda8ec0eca446cristy  int
89f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    order;
90f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy} JNXInfo;
91f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
92f2be7a37aa8f7f8c84489950241817f7db36fcf5cristytypedef struct _JNXLevelInfo
93f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy{
94f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  int
9586a135da8eb3f25503c3bef128bcda8ec0eca446cristy    count,
96f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    offset;
97f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
98f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  unsigned int
99f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    scale;
100f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
10186a135da8eb3f25503c3bef128bcda8ec0eca446cristy  unsigned short
102151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy    copyright[MagickPathExtent];
103f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy} JNXLevelInfo;
104f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
10584713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
10684713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10784713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
10884713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
10984713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
11084713a3f3c3faafc53488c0307d48bca0902bea9cristy%   R e a d J N X I m a g e                                                   %
11184713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
11284713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
11384713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
11484713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11584713a3f3c3faafc53488c0307d48bca0902bea9cristy%
11684713a3f3c3faafc53488c0307d48bca0902bea9cristy%  ReadJNXImage() reads an image in the Garmin tile storage format and returns
11784713a3f3c3faafc53488c0307d48bca0902bea9cristy%  it.  It allocates the memory necessary for the new Image structure and
11884713a3f3c3faafc53488c0307d48bca0902bea9cristy%  returns a pointer to the new image.
11984713a3f3c3faafc53488c0307d48bca0902bea9cristy%
12084713a3f3c3faafc53488c0307d48bca0902bea9cristy%  The format of the ReadJNXImage method is:
12184713a3f3c3faafc53488c0307d48bca0902bea9cristy%
12284713a3f3c3faafc53488c0307d48bca0902bea9cristy%      Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
12384713a3f3c3faafc53488c0307d48bca0902bea9cristy%
12484713a3f3c3faafc53488c0307d48bca0902bea9cristy%  A description of each parameter follows:
12584713a3f3c3faafc53488c0307d48bca0902bea9cristy%
12684713a3f3c3faafc53488c0307d48bca0902bea9cristy%    o image_info: the image info.
12784713a3f3c3faafc53488c0307d48bca0902bea9cristy%
12884713a3f3c3faafc53488c0307d48bca0902bea9cristy%    o exception: return any errors or warnings in this structure.
12984713a3f3c3faafc53488c0307d48bca0902bea9cristy%
13084713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
13184713a3f3c3faafc53488c0307d48bca0902bea9cristystatic Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
13284713a3f3c3faafc53488c0307d48bca0902bea9cristy{
133f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy#define JNXMaxLevels  20
134f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
135f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  Image
136f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    *image,
137f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    *images;
138f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
139f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  JNXInfo
140f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    jnx_info;
141f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
142f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  JNXLevelInfo
143f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    jnx_level_info[JNXMaxLevels];
144f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
145f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  MagickBooleanType
146f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    status;
147f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
148f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  register ssize_t
149f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    i;
150f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
151f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  /*
152f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    Open image file.
153f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  */
154f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  assert(image_info != (const ImageInfo *) NULL);
155e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(image_info->signature == MagickCoreSignature);
156f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  if (image_info->debug != MagickFalse)
157f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
158f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      image_info->filename);
159f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  assert(exception != (ExceptionInfo *) NULL);
160e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy  assert(exception->signature == MagickCoreSignature);
161f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  image=AcquireImage(image_info,exception);
162f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
163f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  if (status == MagickFalse)
164f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    {
165f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      image=DestroyImageList(image);
166f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      return((Image *) NULL);
167f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    }
168f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  /*
169f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    Read JNX header.
170f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  */
171f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  (void) ResetMagickMemory(&jnx_info,0,sizeof(jnx_info));
1721fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.version=ReadBlobLSBSignedLong(image);
17386a135da8eb3f25503c3bef128bcda8ec0eca446cristy  if ((jnx_info.version != 3) && (jnx_info.version != 4))
174f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1751fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.serial=ReadBlobLSBSignedLong(image);
1761fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.northeast.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
1771fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.northeast.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
1781fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.southwest.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
1791fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.southwest.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
1801fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.levels=ReadBlobLSBSignedLong(image);
181f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  if (jnx_info.levels > JNXMaxLevels)
182f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1831fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.expire=ReadBlobLSBSignedLong(image);
1841fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.id=ReadBlobLSBSignedLong(image);
1851fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.crc=ReadBlobLSBSignedLong(image);
1861fe0b879964fa7797e3d68574d297922a47c4034Cristy  jnx_info.signature=ReadBlobLSBSignedLong(image);
187f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  jnx_info.offset=ReadBlobLSBLong(image);
188f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  if (jnx_info.version > 3)
1891fe0b879964fa7797e3d68574d297922a47c4034Cristy    jnx_info.order=ReadBlobLSBSignedLong(image);
19086a135da8eb3f25503c3bef128bcda8ec0eca446cristy  else
19186a135da8eb3f25503c3bef128bcda8ec0eca446cristy    if (jnx_info.version == 3)
19286a135da8eb3f25503c3bef128bcda8ec0eca446cristy      jnx_info.order=30;
193f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  /*
194f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    Read JNX levels.
195f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  */
196f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  (void) ResetMagickMemory(&jnx_level_info,0,sizeof(jnx_level_info));
197f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  for (i=0; i < (ssize_t) jnx_info.levels; i++)
198f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  {
1991fe0b879964fa7797e3d68574d297922a47c4034Cristy    jnx_level_info[i].count=ReadBlobLSBSignedLong(image);
20086a135da8eb3f25503c3bef128bcda8ec0eca446cristy    if (jnx_level_info[i].count > 50000)
20186a135da8eb3f25503c3bef128bcda8ec0eca446cristy      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
2021fe0b879964fa7797e3d68574d297922a47c4034Cristy    jnx_level_info[i].offset=ReadBlobLSBSignedLong(image);
20386a135da8eb3f25503c3bef128bcda8ec0eca446cristy    jnx_level_info[i].scale=ReadBlobLSBLong(image);
204f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    if (jnx_info.version > 3)
205f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      {
206f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        register ssize_t
207f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          j;
208f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
2099e2d53c10d610e2e6099cdae06516926d133c321cristy        unsigned short
2109e2d53c10d610e2e6099cdae06516926d133c321cristy          c;
2119e2d53c10d610e2e6099cdae06516926d133c321cristy
212f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        (void) ReadBlobLSBLong(image);
213f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        j=0;
214f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        while ((c=ReadBlobLSBShort(image)) != 0)
215151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy          if (j < (MagickPathExtent-1))
216f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy            jnx_level_info[i].copyright[j++]=c;
21786a135da8eb3f25503c3bef128bcda8ec0eca446cristy        jnx_level_info[i].copyright[j]=0;
218f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      }
219f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  }
220f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  /*
221f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    Read JNX tiles.
222f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  */
223f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  images=NewImageList();
224f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  for (i=0; i < (ssize_t) jnx_info.levels; i++)
225f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  {
226c69908373e2725d2142152a376c9d392feeab265cristy    MagickOffsetType
227c69908373e2725d2142152a376c9d392feeab265cristy      offset;
228c69908373e2725d2142152a376c9d392feeab265cristy
229f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    register ssize_t
230f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      j;
231f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
232c69908373e2725d2142152a376c9d392feeab265cristy    offset=SeekBlob(image,(MagickOffsetType) jnx_level_info[i].offset,SEEK_SET);
233c69908373e2725d2142152a376c9d392feeab265cristy    if (offset != (MagickOffsetType) jnx_level_info[i].offset)
234c69908373e2725d2142152a376c9d392feeab265cristy      continue;
235f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    for (j=0; j < (ssize_t) jnx_level_info[i].count; j++)
236f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    {
237f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      Image
238f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        *tile_image;
239f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
240f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      ImageInfo
241f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        *read_info;
242f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
243f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      int
244f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        tile_offset;
245f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
2469e2d53c10d610e2e6099cdae06516926d133c321cristy      MagickOffsetType
2479e2d53c10d610e2e6099cdae06516926d133c321cristy        restore_offset;
2489e2d53c10d610e2e6099cdae06516926d133c321cristy
249f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      PointInfo
250f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        northeast,
251f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        southwest;
252f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
253f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      ssize_t
254f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        count;
255f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
256f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      unsigned char
257f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        *blob;
258f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
259f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      unsigned int
260f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        tile_length;
261f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
2621fe0b879964fa7797e3d68574d297922a47c4034Cristy      northeast.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
2631fe0b879964fa7797e3d68574d297922a47c4034Cristy      northeast.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
2641fe0b879964fa7797e3d68574d297922a47c4034Cristy      southwest.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
2651fe0b879964fa7797e3d68574d297922a47c4034Cristy      southwest.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
266f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      (void) ReadBlobLSBShort(image); /* width */
267f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      (void) ReadBlobLSBShort(image); /* height */
268f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      tile_length=ReadBlobLSBLong(image);
2691fe0b879964fa7797e3d68574d297922a47c4034Cristy      tile_offset=ReadBlobLSBSignedLong(image);
2704d0ca34912f861b25e5ed95e3f624048cb180358cristy      if (tile_offset == -1)
2714d0ca34912f861b25e5ed95e3f624048cb180358cristy        continue;
2729e2d53c10d610e2e6099cdae06516926d133c321cristy      restore_offset=TellBlob(image);
2738418c7e51974060a1c724e25d700d72fb437174bcristy      if (restore_offset < 0)
2748418c7e51974060a1c724e25d700d72fb437174bcristy        continue;
2759e2d53c10d610e2e6099cdae06516926d133c321cristy      offset=SeekBlob(image,(MagickOffsetType) tile_offset,SEEK_SET);
2769e2d53c10d610e2e6099cdae06516926d133c321cristy      if (offset != (MagickOffsetType) tile_offset)
2779e2d53c10d610e2e6099cdae06516926d133c321cristy        continue;
278f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      /*
279f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        Read a tile.
280f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      */
281ede8a0e2dcd1dab584ad324dbd6d5bf4cf9df488cristy      blob=(unsigned char *) AcquireQuantumMemory((size_t) tile_length+2,
282ede8a0e2dcd1dab584ad324dbd6d5bf4cf9df488cristy        sizeof(*blob));
283f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      if (blob == (unsigned char *) NULL)
284f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        {
285f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          if (images != (Image *) NULL)
286f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy            images=DestroyImageList(images);
287f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
288f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        }
289f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      blob[0]=0xFF;
290f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      blob[1]=0xD8;
291f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      count=ReadBlob(image,tile_length,blob+2);
29286a135da8eb3f25503c3bef128bcda8ec0eca446cristy      if (count != (ssize_t) tile_length)
293f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        {
294f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          if (images != (Image *) NULL)
295f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy            images=DestroyImageList(images);
296f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          blob=(unsigned char *) RelinquishMagickMemory(blob);
297f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
298f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        }
299f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      read_info=CloneImageInfo(image_info);
300151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(read_info->magick,"JPEG",MagickPathExtent);
301f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      tile_image=BlobToImage(read_info,blob,tile_length+2,exception);
302f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      read_info=DestroyImageInfo(read_info);
303f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      blob=(unsigned char *) RelinquishMagickMemory(blob);
3049e2d53c10d610e2e6099cdae06516926d133c321cristy      offset=SeekBlob(image,restore_offset,SEEK_SET);
305f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      if (tile_image == (Image *) NULL)
306f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        continue;
307151b66dffc9e3c2e8c4f8cdaca37ff987ca0f497cristy      (void) CopyMagickString(tile_image->magick,image->magick,MagickPathExtent);
3088b170c30af2b2b5c76aff3ee7510d52c65ba001bcristy      (void) FormatImageProperty(tile_image,"jnx:northeast","%.20g,%.20g",
3098b170c30af2b2b5c76aff3ee7510d52c65ba001bcristy        northeast.x,northeast.y);
3108b170c30af2b2b5c76aff3ee7510d52c65ba001bcristy      (void) FormatImageProperty(tile_image,"jnx:southwest","%.20g,%.20g",
3118b170c30af2b2b5c76aff3ee7510d52c65ba001bcristy        southwest.x,southwest.y);
312f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      AppendImageToList(&images,tile_image);
313f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    }
314f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    if (image->progress_monitor != (MagickProgressMonitor) NULL)
315f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      {
316f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        MagickBooleanType
317f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          proceed;
318f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy
319f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) i,
320f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          (MagickSizeType) jnx_info.levels);
321f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy        if (proceed == MagickFalse)
322f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy          status=MagickFalse;
323f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy      }
324f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  }
325f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  (void) CloseBlob(image);
326f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  image=DestroyImage(image);
327f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  if (images == (Image *) NULL)
328f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy    return((Image *) NULL);
329f2be7a37aa8f7f8c84489950241817f7db36fcf5cristy  return(GetFirstImageInList(images));
33084713a3f3c3faafc53488c0307d48bca0902bea9cristy}
33184713a3f3c3faafc53488c0307d48bca0902bea9cristy
33284713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
33384713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33484713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
33584713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
33684713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
33784713a3f3c3faafc53488c0307d48bca0902bea9cristy%   R e g i s t e r J N X I m a g e                                           %
33884713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
33984713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
34084713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
34184713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34284713a3f3c3faafc53488c0307d48bca0902bea9cristy%
34384713a3f3c3faafc53488c0307d48bca0902bea9cristy%  RegisterJNXImage() adds attributes for the JNX image format to the list
34484713a3f3c3faafc53488c0307d48bca0902bea9cristy%  of supported formats.  The attributes include the image format tag, a
34584713a3f3c3faafc53488c0307d48bca0902bea9cristy%  method to read and/or write the format, whether the format supports the
34684713a3f3c3faafc53488c0307d48bca0902bea9cristy%  saving of more than one frame to the same file or blob, whether the format
34784713a3f3c3faafc53488c0307d48bca0902bea9cristy%  supports native in-memory I/O, and a brief description of the format.
34884713a3f3c3faafc53488c0307d48bca0902bea9cristy%
34984713a3f3c3faafc53488c0307d48bca0902bea9cristy%  The format of the RegisterJNXImage method is:
35084713a3f3c3faafc53488c0307d48bca0902bea9cristy%
35184713a3f3c3faafc53488c0307d48bca0902bea9cristy%      size_t RegisterJNXImage(void)
35284713a3f3c3faafc53488c0307d48bca0902bea9cristy%
35384713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
35484713a3f3c3faafc53488c0307d48bca0902bea9cristyModuleExport size_t RegisterJNXImage(void)
35584713a3f3c3faafc53488c0307d48bca0902bea9cristy{
35684713a3f3c3faafc53488c0307d48bca0902bea9cristy  MagickInfo
35784713a3f3c3faafc53488c0307d48bca0902bea9cristy    *entry;
35884713a3f3c3faafc53488c0307d48bca0902bea9cristy
35906b627a07ff44e1ff93ef1288c9f428066ded10ddirk  entry=AcquireMagickInfo("JNX","JNX","Garmin tile format");
36084713a3f3c3faafc53488c0307d48bca0902bea9cristy  entry->decoder=(DecodeImageHandler *) ReadJNXImage;
36108e9a113db499034abb5ad8d59b42f8eca3c641cdirk  entry->flags|=CoderSeekableStreamFlag;
36284713a3f3c3faafc53488c0307d48bca0902bea9cristy  (void) RegisterMagickInfo(entry);
36384713a3f3c3faafc53488c0307d48bca0902bea9cristy  return(MagickImageCoderSignature);
36484713a3f3c3faafc53488c0307d48bca0902bea9cristy}
36584713a3f3c3faafc53488c0307d48bca0902bea9cristy
36684713a3f3c3faafc53488c0307d48bca0902bea9cristy/*
36784713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36884713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
36984713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
37084713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
37184713a3f3c3faafc53488c0307d48bca0902bea9cristy%   U n r e g i s t e r J N X I m a g e                                       %
37284713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
37384713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
37484713a3f3c3faafc53488c0307d48bca0902bea9cristy%                                                                             %
37584713a3f3c3faafc53488c0307d48bca0902bea9cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37684713a3f3c3faafc53488c0307d48bca0902bea9cristy%
37784713a3f3c3faafc53488c0307d48bca0902bea9cristy%  UnregisterJNXImage() removes format registrations made by the
37884713a3f3c3faafc53488c0307d48bca0902bea9cristy%  JNX module from the list of supported formats.
37984713a3f3c3faafc53488c0307d48bca0902bea9cristy%
38084713a3f3c3faafc53488c0307d48bca0902bea9cristy%  The format of the UnregisterJNXImage method is:
38184713a3f3c3faafc53488c0307d48bca0902bea9cristy%
38284713a3f3c3faafc53488c0307d48bca0902bea9cristy%      UnregisterJNXImage(void)
38384713a3f3c3faafc53488c0307d48bca0902bea9cristy%
38484713a3f3c3faafc53488c0307d48bca0902bea9cristy*/
38584713a3f3c3faafc53488c0307d48bca0902bea9cristyModuleExport void UnregisterJNXImage(void)
38684713a3f3c3faafc53488c0307d48bca0902bea9cristy{
38784713a3f3c3faafc53488c0307d48bca0902bea9cristy  (void) UnregisterMagickInfo("JNX");
38884713a3f3c3faafc53488c0307d48bca0902bea9cristy}
389