Coverage Report

Created: 2025-12-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/jnx.c
Line
Count
Source
1
/*
2
% Copyright (C) 2012-2025 GraphicsMagick Group
3
%
4
% This program is covered by multiple licenses, which are described in
5
% Copyright.txt. You should have received a copy of Copyright.txt with this
6
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
7
%
8
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9
%                                                                             %
10
%                                                                             %
11
%                               J   NN   N  X    X                            %
12
%                               J   N N  N   X  X                             %
13
%                               J   N N  N    XX                              %
14
%                           JJ  J   N  N N   X  X                             %
15
%                             JJ    N   NN  X    X                            %
16
%                                                                             %
17
%                                                                             %
18
%                   JNX: Garmin proprietary Image Format.                     %
19
%                                                                             %
20
%                                                                             %
21
%                              Software Design                                %
22
%                              Jaroslav Fojtik                                %
23
%                                2012 - 2018                                  %
24
%                                                                             %
25
%                                                                             %
26
%                                                                             %
27
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28
%
29
%
30
*/
31

32
/*
33
  Include declarations.
34
*/
35
#include "magick/studio.h"
36
#include "magick/blob.h"
37
#include "magick/colormap.h"
38
#include "magick/constitute.h"
39
#include "magick/log.h"
40
#include "magick/magick.h"
41
#include "magick/monitor.h"
42
#include "magick/pixel_cache.h"
43
#include "magick/utility.h"
44
#include "magick/tempfile.h"
45
#include "magick/magic.h"
46
#include "magick/resource.h"
47
#include "magick/attribute.h"
48
#include "magick/static.h"
49

50
typedef struct
51
{
52
  int lat, lon;
53
} TJNXPoint;
54
55
typedef struct
56
{
57
  TJNXPoint NorthEast, SouthWest;
58
} TJNXRect;
59
60
typedef struct
61
{
62
  unsigned Version;
63
  unsigned DeviceSN;
64
  TJNXRect MapBounds;
65
  unsigned Levels;
66
  unsigned Expiration;
67
  unsigned ProductID;
68
  unsigned CRC;
69
  unsigned SigVersion;
70
  unsigned SigOffset;
71
  unsigned ZOrder;
72
} TJNXHeader;
73
74
typedef struct
75
{
76
  unsigned TileCount;
77
  unsigned TilesOffset;
78
  unsigned Scale;
79
  char *Copyright;
80
  unsigned Dummy;
81
} TJNXLevelInfo;
82
83
typedef struct
84
{
85
  TJNXRect TileBounds;
86
  unsigned short PicWidth, PicHeight;
87
  unsigned PicSize;
88
  unsigned PicOffset;
89
} TJNXTileInfo;
90
91
92
static Image *
93
ExtractTileJPG(Image * image, const ImageInfo * image_info,
94
               TJNXTileInfo *TileInfo, ExceptionInfo * exception)
95
24.3k
{
96
24.3k
  size_t
97
24.3k
    alloc_size;
98
99
24.3k
  unsigned char
100
24.3k
    *blob;
101
102
24.3k
  char img_label_str[MaxTextExtent];
103
104
105
24.3k
  alloc_size = (size_t) TileInfo->PicSize + 2;
106
107
24.3k
  if (image->logging)
108
24.3k
    (void) LogMagickEvent(CoderEvent, GetMagickModule(),
109
24.3k
                          "JNX tile offset %u, size %u bytes",
110
24.3k
                          TileInfo->PicOffset, TileInfo->PicSize);
111
112
24.3k
  if ((alloc_size > TileInfo->PicSize) &&
113
24.3k
      (blob = MagickAllocateResourceLimitedMemory(unsigned char *,alloc_size)) != NULL)
114
24.3k
    {
115
      /* Add missing JPEG header bytes */
116
24.3k
      blob[0] = 0xFF;
117
24.3k
      blob[1] = 0xD8;
118
119
      /* Copy JPG to memory blob */
120
24.3k
      if (SeekBlob(image, TileInfo->PicOffset, SEEK_SET) == TileInfo->PicOffset)
121
24.3k
        {
122
24.3k
          if (ReadBlob(image,TileInfo->PicSize,blob+2) == TileInfo->PicSize)
123
24.2k
            {
124
24.2k
              Image
125
24.2k
                *image2;
126
127
24.2k
              ImageInfo
128
24.2k
                *clone_info;
129
130
24.2k
              clone_info=CloneImageInfo(image_info);
131
132
              /* BlobToFile("/tmp/jnx-tile.jpg", blob,alloc_size,exception); */
133
134
24.2k
              (void) strlcpy(clone_info->filename,"JPEG:",sizeof(clone_info->filename));
135
24.2k
              if ((image2 = BlobToImage(clone_info,blob,alloc_size,exception))
136
24.2k
                  != NULL)
137
5.19k
                {
138
                  /*
139
                    Replace current image with new image while copying
140
                    base image attributes.
141
                  */
142
5.19k
                  (void) strlcpy(image2->filename, image->filename,
143
5.19k
                                 sizeof(image2->filename));
144
5.19k
                  (void) strlcpy(image2->magick_filename, image->magick_filename,
145
5.19k
                                 sizeof(image2->magick_filename));
146
5.19k
                  (void) strlcpy(image2->magick, image->magick,
147
5.19k
                                 sizeof(image2->magick));
148
5.19k
                  DestroyBlob(image2);
149
5.19k
                  image2->blob = ReferenceBlob(image->blob);
150
151
5.19k
                  if ((image->rows == 0) || (image->columns == 0))
152
2.26k
                    DeleteImageFromList(&image);
153
154
5.19k
                  FormatString(img_label_str, "%.20g;%.20g",
155
5.19k
                               (double) TileInfo->TileBounds.NorthEast.lat*180.0/0x7FFFFFFF,
156
5.19k
                               (double) TileInfo->TileBounds.NorthEast.lon*180.0/0x7FFFFFFF);
157
5.19k
                  SetImageAttribute(image2, "jnx:northeast", img_label_str);
158
159
5.19k
                  FormatString(img_label_str, "%.20g;%.20g",
160
5.19k
                               (double) TileInfo->TileBounds.SouthWest.lat*180.0/0x7FFFFFFF,
161
5.19k
                               (double) TileInfo->TileBounds.SouthWest.lon*180.0/0x7FFFFFFF);
162
5.19k
                  SetImageAttribute(image2, "jnx:southwest", img_label_str);
163
164
5.19k
                  AppendImageToList(&image, image2);
165
5.19k
                }
166
24.2k
              DestroyImageInfo(clone_info);
167
24.2k
              clone_info = (ImageInfo *) NULL;
168
24.2k
            }
169
10
          else
170
10
            {
171
              /* Failed to read enough data from input */
172
10
              ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
173
10
                             image->filename);
174
10
            }
175
24.3k
        }
176
0
      else
177
0
        {
178
          /* Failed to seek in input */
179
0
          ThrowException(exception,BlobError,UnableToSeekToOffset,
180
0
                         image->filename);
181
0
        }
182
24.3k
      MagickFreeResourceLimitedMemory(unsigned char *,blob);
183
24.3k
    }
184
0
  else
185
0
    {
186
      /* Failed to allocate memory */
187
0
      ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
188
0
                     image->filename);
189
0
    }
190
191
24.3k
  return(image);
192
24.3k
}
193

194
/*
195
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196
%                                                                             %
197
%                                                                             %
198
%                                                                             %
199
%   R e a d J N X I m a g e                                                   %
200
%                                                                             %
201
%                                                                             %
202
%                                                                             %
203
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204
%
205
%  Method ReadJNXImage reads an JNX X image file and returns it.  It
206
%  allocates the memory necessary for the new Image structure and returns a
207
%  pointer to the new image.
208
%
209
%  The format of the ReadJNXImage method is:
210
%
211
%      Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
212
%
213
%  A description of each parameter follows:
214
%
215
%    o image:  Method ReadJNXImage returns a pointer to the image after
216
%      reading. A null image is returned if there is a memory shortage or if
217
%      the image cannot be read.
218
%
219
%    o image_info: Specifies a pointer to a ImageInfo structure.
220
%
221
%    o exception: return any errors or warnings in this structure.
222
%
223
*/
224
static Image *
225
ReadJNXImage(const ImageInfo * image_info, ExceptionInfo * exception)
226
6.99k
{
227
6.99k
  Image
228
6.99k
    *image;
229
230
6.99k
  unsigned int
231
6.99k
    i,
232
6.99k
    j;
233
234
6.99k
  TJNXHeader
235
6.99k
    JNXHeader;
236
237
6.99k
  TJNXLevelInfo
238
6.99k
    JNXLevelInfo[20];
239
240
6.99k
  unsigned int
241
6.99k
    status;
242
243
6.99k
  TJNXTileInfo
244
6.99k
    *PositionList = NULL;
245
246
6.99k
  int
247
6.99k
    logging;
248
249
6.99k
  magick_int64_t
250
6.99k
    SaveLimit;
251
252
6.99k
  unsigned int
253
6.99k
    total_tiles,
254
6.99k
    current_tile;
255
256
6.99k
  magick_off_t
257
6.99k
    file_size;
258
259
  /* Open image file. */
260
6.99k
  assert(image_info != (const ImageInfo *) NULL);
261
6.99k
  assert(image_info->signature == MagickSignature);
262
6.99k
  assert(exception != (ExceptionInfo *) NULL);
263
6.99k
  assert(exception->signature == MagickSignature);
264
6.99k
  logging = LogMagickEvent(CoderEvent, GetMagickModule(), "enter");
265
266
6.99k
  image = AllocateImage(image_info);
267
6.99k
  image->rows = 0;
268
6.99k
  image->columns = 0;
269
6.99k
  status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception);
270
6.99k
  if (status == False)
271
6.99k
    ThrowReaderException(FileOpenError, UnableToOpenFile, image);
272
273
  /* Read JNX image header. */
274
6.99k
  (void) memset(&JNXHeader, 0, sizeof(JNXHeader));
275
6.99k
  JNXHeader.Version = ReadBlobLSBLong(image);
276
6.99k
  if (JNXHeader.Version > 4)
277
6.95k
    ThrowReaderException(CorruptImageError, ImproperImageHeader, image);
278
6.95k
  JNXHeader.DeviceSN = ReadBlobLSBLong(image);
279
6.95k
  JNXHeader.MapBounds.NorthEast.lat = ReadBlobLSBLong(image);
280
6.95k
  JNXHeader.MapBounds.NorthEast.lon = ReadBlobLSBLong(image);
281
6.95k
  JNXHeader.MapBounds.SouthWest.lat = ReadBlobLSBLong(image);
282
6.95k
  JNXHeader.MapBounds.SouthWest.lon = ReadBlobLSBLong(image);
283
6.95k
  JNXHeader.Levels = ReadBlobLSBLong(image);
284
6.95k
  JNXHeader.Expiration = ReadBlobLSBLong(image);
285
6.95k
  JNXHeader.ProductID = ReadBlobLSBLong(image);
286
6.95k
  JNXHeader.CRC = ReadBlobLSBLong(image);
287
6.95k
  JNXHeader.SigVersion = ReadBlobLSBLong(image);
288
6.95k
  JNXHeader.SigOffset = ReadBlobLSBLong(image);
289
6.95k
  if (JNXHeader.Version >= 4)
290
41
    JNXHeader.ZOrder = ReadBlobLSBLong(image);
291
292
6.95k
  if (EOFBlob(image))
293
6.92k
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
294
295
6.92k
  file_size = GetBlobSize(image);
296
297
6.92k
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),
298
6.92k
                        "JNX Header:\n"
299
6.92k
                        "    Version:    %u\n"
300
6.92k
                        "    DeviceSN:   %u\n"
301
6.92k
                        "    MapBounds:\n"
302
6.92k
                        "      NorthEast: lat = %u, lon = %u\n"
303
6.92k
                        "      SouthWest: lat = %u, lon = %u\n"
304
6.92k
                        "    Levels:     %u\n"
305
6.92k
                        "    Expiration: %u\n"
306
6.92k
                        "    ProductID:  %u\n"
307
6.92k
                        "    CRC:        %u\n"
308
6.92k
                        "    SigVersion: %u\n"
309
6.92k
                        "    SigOffset:  %u\n"
310
6.92k
                        "    ZOrder:     %u",
311
6.92k
                        JNXHeader.Version,
312
6.92k
                        JNXHeader.DeviceSN,
313
6.92k
                        JNXHeader.MapBounds.NorthEast.lat,
314
6.92k
                        JNXHeader.MapBounds.NorthEast.lon,
315
6.92k
                        JNXHeader.MapBounds.SouthWest.lat,
316
6.92k
                        JNXHeader.MapBounds.SouthWest.lon,
317
6.92k
                        JNXHeader.Levels,
318
6.92k
                        JNXHeader.Expiration,
319
6.92k
                        JNXHeader.ProductID,
320
6.92k
                        JNXHeader.CRC,
321
6.92k
                        JNXHeader.SigVersion,
322
6.92k
                        JNXHeader.SigOffset,
323
6.92k
                        JNXHeader.ZOrder);
324
325
6.92k
  if (JNXHeader.Levels > 20)
326
6.88k
    ThrowReaderException(CorruptImageError, ImproperImageHeader, image);
327
328
  /* Read JNX image level info. */
329
6.88k
  memset(JNXLevelInfo, 0, sizeof(JNXLevelInfo));
330
6.88k
  total_tiles = 0;
331
6.88k
  current_tile = 0;
332
46.7k
  for (i = 0; i < JNXHeader.Levels; i++)
333
39.8k
    {
334
39.8k
      JNXLevelInfo[i].TileCount = ReadBlobLSBLong(image);
335
39.8k
      JNXLevelInfo[i].TilesOffset = ReadBlobLSBLong(image);
336
39.8k
      JNXLevelInfo[i].Scale = ReadBlobLSBLong(image);
337
39.8k
      total_tiles += JNXLevelInfo[i].TileCount;
338
339
39.8k
      if (JNXHeader.Version >= 4)
340
267
        {
341
267
          JNXLevelInfo[i].Dummy = ReadBlobLSBLong(image);
342
267
          JNXLevelInfo[i].Copyright = NULL;
343
3.07M
          while (ReadBlobLSBShort(image) != 0)
344
3.07M
            {
345
              /* char *Copyright; */
346
3.07M
            }
347
267
        }
348
39.6k
      else
349
39.6k
        {
350
39.6k
          JNXLevelInfo[i].Copyright = NULL;
351
39.6k
        }
352
353
39.8k
      if (EOFBlob(image))
354
39.8k
        ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
355
356
39.8k
      if (image->logging)
357
39.8k
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
358
39.8k
                              "Level[%u] Info:"
359
39.8k
                              "  TileCount: %4u"
360
39.8k
                              "  TilesOffset: %6u"
361
39.8k
                              "  Scale: %04u",
362
39.8k
                              i,
363
39.8k
                              JNXLevelInfo[i].TileCount,
364
39.8k
                              JNXLevelInfo[i].TilesOffset,
365
39.8k
                              JNXLevelInfo[i].Scale
366
39.8k
                              );
367
39.8k
    }
368
369
  /* Get the current limit */
370
6.83k
  SaveLimit = GetMagickResourceLimit(MapResource);
371
372
  /* Temporarily set the limit to zero */
373
6.83k
  SetMagickResourceLimit(MapResource, 0);
374
375
  /* Read JNX image data. */
376
30.7k
  for (i = 0; i < JNXHeader.Levels; i++)
377
27.7k
    {
378
      /*
379
        Validate TileCount against remaining file data
380
      */
381
27.7k
      const magick_off_t current_offset = TellBlob(image);
382
27.7k
      const size_t pos_list_entry_size =
383
27.7k
        sizeof(magick_uint32_t) + sizeof(magick_uint32_t) + sizeof(magick_uint32_t) +
384
27.7k
        sizeof(magick_uint32_t) + sizeof(magick_uint16_t) + sizeof(magick_uint16_t) +
385
27.7k
        sizeof(magick_uint32_t) + sizeof(magick_uint32_t);
386
27.7k
      const magick_off_t remaining = file_size-current_offset;
387
27.7k
      const size_t needed = MagickArraySize(pos_list_entry_size,JNXLevelInfo[i].TileCount);
388
389
27.7k
      if ((needed == 0U) || (remaining <= 0) || (remaining < (magick_off_t) needed))
390
3.43k
        {
391
3.43k
          (void) SetMagickResourceLimit(MapResource, SaveLimit);
392
3.43k
          ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
393
0
        }
394
395
24.3k
      PositionList = MagickAllocateResourceLimitedArray(TJNXTileInfo *,
396
24.3k
                                         JNXLevelInfo[i].TileCount,
397
24.3k
                                         sizeof(TJNXTileInfo));
398
24.3k
      if (PositionList == NULL)
399
0
        {
400
0
          (void) SetMagickResourceLimit(MapResource, SaveLimit);
401
0
          ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
402
0
                               image);
403
0
        }
404
405
24.3k
      (void) SeekBlob(image, JNXLevelInfo[i].TilesOffset, SEEK_SET);
406
49.9k
      for (j = 0; j < JNXLevelInfo[i].TileCount; j++)
407
26.0k
        {
408
26.0k
          PositionList[j].TileBounds.NorthEast.lat = ReadBlobLSBLong(image);
409
26.0k
          PositionList[j].TileBounds.NorthEast.lon = ReadBlobLSBLong(image);
410
26.0k
          PositionList[j].TileBounds.SouthWest.lat = ReadBlobLSBLong(image);
411
26.0k
          PositionList[j].TileBounds.SouthWest.lon = ReadBlobLSBLong(image);
412
26.0k
          PositionList[j].PicWidth = ReadBlobLSBShort(image);
413
26.0k
          PositionList[j].PicHeight = ReadBlobLSBShort(image);
414
26.0k
          PositionList[j].PicSize = ReadBlobLSBLong(image);
415
26.0k
          PositionList[j].PicOffset = ReadBlobLSBLong(image);
416
417
26.0k
          if (EOFBlob(image) ||
418
25.6k
              ((magick_off_t) PositionList[j].PicOffset +
419
25.6k
               PositionList[j].PicSize > file_size))
420
455
            {
421
455
              (void) SetMagickResourceLimit(MapResource, SaveLimit);
422
455
              MagickFreeResourceLimitedMemory(TJNXTileInfo *,PositionList);
423
455
              ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
424
0
            }
425
26.0k
        }
426
427
29.0k
      for (j = 0; j < JNXLevelInfo[i].TileCount; j++)
428
24.3k
        {
429
24.3k
          MonitorHandler
430
24.3k
            previous_handler;
431
432
          /* Disable progress monitor while loading individual tiles */
433
24.3k
          previous_handler = SetMonitorHandler(0);
434
24.3k
          image = ExtractTileJPG(image, image_info, PositionList+j, exception);
435
24.3k
          (void) SetMonitorHandler(previous_handler);
436
437
24.3k
          if (exception->severity >= ErrorException)
438
19.1k
            break;
439
440
5.19k
          current_tile++;
441
5.19k
          if (QuantumTick(current_tile,total_tiles))
442
2.39k
            if (!MagickMonitorFormatted(current_tile,total_tiles,exception,
443
2.39k
                                        LoadImageText,image->filename,
444
2.39k
                                        image->columns,image->rows))
445
0
              break;
446
5.19k
        }
447
448
23.8k
      MagickFreeResourceLimitedMemory(TJNXTileInfo *,PositionList);
449
23.8k
    }
450
451
2.94k
  CloseBlob(image);
452
453
  /* Restore the previous limit */
454
2.94k
  (void) SetMagickResourceLimit(MapResource, SaveLimit);
455
456
2.94k
  {
457
2.94k
    Image *p;
458
2.94k
    long scene = 0;
459
460
    /* Rewind list, removing any empty images while rewinding. */
461
2.94k
    p = image;
462
2.94k
    image = NULL;
463
6.75k
    while (p != (Image *) NULL)
464
3.81k
      {
465
3.81k
        Image *tmp = p;
466
3.81k
        if ((p->rows == 0) || (p->columns == 0))
467
1.83k
          {
468
1.83k
            p = p->previous;
469
1.83k
            DeleteImageFromList(&tmp);
470
1.83k
          }
471
1.97k
        else
472
1.97k
          {
473
1.97k
            image = p;
474
1.97k
            p = p->previous;
475
1.97k
          }
476
3.81k
      }
477
478
    /* Fix scene numbers */
479
4.92k
    for (p = image; p != (Image *) NULL; p = p->next)
480
1.97k
      p->scene = scene++;
481
2.94k
  }
482
483
2.94k
  if (logging)
484
0
    (void) LogMagickEvent(CoderEvent, GetMagickModule(), "return");
485
2.94k
  if (image == NULL)
486
1.83k
    ThrowReaderException(CorruptImageError, ImageFileDoesNotContainAnyImageData,
487
2.94k
                         image);
488
489
1.10k
  return (image);
490
2.94k
}
491

492
/*
493
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494
%                                                                             %
495
%                                                                             %
496
%                                                                             %
497
%   W r i t e J N X I m a g e                                                 %
498
%                                                                             %
499
%                                                                             %
500
%                                                                             %
501
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502
%
503
%  Function WriteJNXImage writes an JNX image to a file.
504
%
505
%  The format of the WriteJNXImage method is:
506
%
507
%      unsigned int WriteJNXImage(const ImageInfo *image_info,Image *image)
508
%
509
%  A description of each parameter follows.
510
%
511
%    o status: Function WriteJNXImage return True if the image is written.
512
%      False is returned is there is a memory shortage or if the image file
513
%      fails to write.
514
%
515
%    o image_info: Specifies a pointer to a ImageInfo structure.
516
%
517
%    o image:  A pointer to an Image structure.
518
%
519
*/
520
/*
521
static MagickPassFail WriteJNXImage(const ImageInfo *image_info,Image *image)
522
{
523
  return(0);
524
}
525
*/
526

527
/*
528
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
529
%                                                                             %
530
%                                                                             %
531
%                                                                             %
532
%   R e g i s t e r J N X I m a g e                                           %
533
%                                                                             %
534
%                                                                             %
535
%                                                                             %
536
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537
%
538
%  Method RegisterJNXImage adds attributes for the JNX image format to
539
%  the list of supported formats.  The attributes include the image format
540
%  tag, a method to read and/or write the format, whether the format
541
%  supports the saving of more than one frame to the same file or blob,
542
%  whether the format supports native in-memory I/O, and a brief
543
%  description of the format.
544
%
545
%  The format of the RegisterJNXImage method is:
546
%
547
%      RegisterJNXImage(void)
548
%
549
*/
550
ModuleExport void RegisterJNXImage(void)
551
1
{
552
1
  MagickInfo
553
1
    *entry;
554
555
1
  entry = SetMagickInfo("JNX");
556
1
  entry->decoder = (DecoderHandler) ReadJNXImage;
557
  /* entry->encoder = (EncoderHandler)WriteJNXImage; */
558
1
  entry->description = "JNX: Garmin tile storage format";
559
1
  entry->module = "JNX";
560
1
  (void) RegisterMagickInfo(entry);
561
1
}
562

563
/*
564
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565
%                                                                             %
566
%                                                                             %
567
%                                                                             %
568
%   U n r e g i s t e r J N X I m a g e                                       %
569
%                                                                             %
570
%                                                                             %
571
%                                                                             %
572
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573
%
574
%  Method UnregisterJNXImage removes format registrations made by the
575
%  JNX module from the list of supported formats.
576
%
577
%  The format of the UnregisterJNXImage method is:
578
%
579
%      UnregisterJNXImage(void)
580
%
581
*/
582
ModuleExport void UnregisterJNXImage(void)
583
0
{
584
0
  (void) UnregisterMagickInfo("JNX");
585
0
}