PageRenderTime 35ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/coders/jnx.c

https://gitlab.com/jiapei100/ImageMagick
C | 388 lines | 237 code | 27 blank | 124 comment | 47 complexity | e1648079a6fc11d7108249bd03c0b7c6 MD5 | raw file
  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % %
  4. % %
  5. % %
  6. % JJJ N N X X %
  7. % J NN N X X %
  8. % J N N N X %
  9. % J J N NN X X %
  10. % JJ N N X X %
  11. % %
  12. % %
  13. % Read/Write Garmin Image Format %
  14. % %
  15. % Cristy %
  16. % July 2012 %
  17. % %
  18. % %
  19. % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
  20. % dedicated to making software imaging solutions freely available. %
  21. % %
  22. % You may not use this file except in compliance with the License. You may %
  23. % obtain a copy of the License at %
  24. % %
  25. % http://www.imagemagick.org/script/license.php %
  26. % %
  27. % Unless required by applicable law or agreed to in writing, software %
  28. % distributed under the License is distributed on an "AS IS" BASIS, %
  29. % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
  30. % See the License for the specific language governing permissions and %
  31. % limitations under the License. %
  32. % %
  33. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  34. %
  35. %
  36. */
  37. /*
  38. Include declarations.
  39. */
  40. /*
  41. Include declarations.
  42. */
  43. #include "MagickCore/studio.h"
  44. #include "MagickCore/blob.h"
  45. #include "MagickCore/blob-private.h"
  46. #include "MagickCore/cache.h"
  47. #include "MagickCore/colorspace.h"
  48. #include "MagickCore/colorspace-private.h"
  49. #include "MagickCore/draw.h"
  50. #include "MagickCore/exception.h"
  51. #include "MagickCore/exception-private.h"
  52. #include "MagickCore/image.h"
  53. #include "MagickCore/image-private.h"
  54. #include "MagickCore/list.h"
  55. #include "MagickCore/magick.h"
  56. #include "MagickCore/memory_.h"
  57. #include "MagickCore/module.h"
  58. #include "MagickCore/monitor.h"
  59. #include "MagickCore/monitor-private.h"
  60. #include "MagickCore/property.h"
  61. #include "MagickCore/pixel-accessor.h"
  62. #include "MagickCore/quantum-private.h"
  63. #include "MagickCore/static.h"
  64. #include "MagickCore/string_.h"
  65. typedef struct _JNXInfo
  66. {
  67. int
  68. version,
  69. serial;
  70. PointInfo
  71. northeast,
  72. southwest;
  73. int
  74. levels,
  75. expire,
  76. id,
  77. crc,
  78. signature;
  79. unsigned int
  80. offset;
  81. int
  82. order;
  83. } JNXInfo;
  84. typedef struct _JNXLevelInfo
  85. {
  86. int
  87. count,
  88. offset;
  89. unsigned int
  90. scale;
  91. unsigned short
  92. copyright[MagickPathExtent];
  93. } JNXLevelInfo;
  94. /*
  95. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  96. % %
  97. % %
  98. % %
  99. % R e a d J N X I m a g e %
  100. % %
  101. % %
  102. % %
  103. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  104. %
  105. % ReadJNXImage() reads an image in the Garmin tile storage format and returns
  106. % it. It allocates the memory necessary for the new Image structure and
  107. % returns a pointer to the new image.
  108. %
  109. % The format of the ReadJNXImage method is:
  110. %
  111. % Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
  112. %
  113. % A description of each parameter follows:
  114. %
  115. % o image_info: the image info.
  116. %
  117. % o exception: return any errors or warnings in this structure.
  118. %
  119. */
  120. static Image *ReadJNXImage(const ImageInfo *image_info,ExceptionInfo *exception)
  121. {
  122. #define JNXMaxLevels 20
  123. Image
  124. *image,
  125. *images;
  126. JNXInfo
  127. jnx_info;
  128. JNXLevelInfo
  129. jnx_level_info[JNXMaxLevels];
  130. MagickBooleanType
  131. status;
  132. register ssize_t
  133. i;
  134. /*
  135. Open image file.
  136. */
  137. assert(image_info != (const ImageInfo *) NULL);
  138. assert(image_info->signature == MagickCoreSignature);
  139. if (image_info->debug != MagickFalse)
  140. (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
  141. image_info->filename);
  142. assert(exception != (ExceptionInfo *) NULL);
  143. assert(exception->signature == MagickCoreSignature);
  144. image=AcquireImage(image_info,exception);
  145. status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  146. if (status == MagickFalse)
  147. {
  148. image=DestroyImageList(image);
  149. return((Image *) NULL);
  150. }
  151. /*
  152. Read JNX header.
  153. */
  154. (void) ResetMagickMemory(&jnx_info,0,sizeof(jnx_info));
  155. jnx_info.version=ReadBlobLSBSignedLong(image);
  156. if ((jnx_info.version != 3) && (jnx_info.version != 4))
  157. ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  158. jnx_info.serial=ReadBlobLSBSignedLong(image);
  159. jnx_info.northeast.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  160. jnx_info.northeast.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  161. jnx_info.southwest.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  162. jnx_info.southwest.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  163. jnx_info.levels=ReadBlobLSBSignedLong(image);
  164. if (jnx_info.levels > JNXMaxLevels)
  165. ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  166. jnx_info.expire=ReadBlobLSBSignedLong(image);
  167. jnx_info.id=ReadBlobLSBSignedLong(image);
  168. jnx_info.crc=ReadBlobLSBSignedLong(image);
  169. jnx_info.signature=ReadBlobLSBSignedLong(image);
  170. jnx_info.offset=ReadBlobLSBLong(image);
  171. if (jnx_info.version > 3)
  172. jnx_info.order=ReadBlobLSBSignedLong(image);
  173. else
  174. if (jnx_info.version == 3)
  175. jnx_info.order=30;
  176. /*
  177. Read JNX levels.
  178. */
  179. (void) ResetMagickMemory(&jnx_level_info,0,sizeof(jnx_level_info));
  180. for (i=0; i < (ssize_t) jnx_info.levels; i++)
  181. {
  182. jnx_level_info[i].count=ReadBlobLSBSignedLong(image);
  183. if (jnx_level_info[i].count > 50000)
  184. ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  185. jnx_level_info[i].offset=ReadBlobLSBSignedLong(image);
  186. jnx_level_info[i].scale=ReadBlobLSBLong(image);
  187. if (jnx_info.version > 3)
  188. {
  189. register ssize_t
  190. j;
  191. unsigned short
  192. c;
  193. (void) ReadBlobLSBLong(image);
  194. j=0;
  195. while ((c=ReadBlobLSBShort(image)) != 0)
  196. if (j < (MagickPathExtent-1))
  197. jnx_level_info[i].copyright[j++]=c;
  198. jnx_level_info[i].copyright[j]=0;
  199. }
  200. }
  201. /*
  202. Read JNX tiles.
  203. */
  204. images=NewImageList();
  205. for (i=0; i < (ssize_t) jnx_info.levels; i++)
  206. {
  207. MagickOffsetType
  208. offset;
  209. register ssize_t
  210. j;
  211. offset=SeekBlob(image,(MagickOffsetType) jnx_level_info[i].offset,SEEK_SET);
  212. if (offset != (MagickOffsetType) jnx_level_info[i].offset)
  213. continue;
  214. for (j=0; j < (ssize_t) jnx_level_info[i].count; j++)
  215. {
  216. Image
  217. *tile_image;
  218. ImageInfo
  219. *read_info;
  220. int
  221. tile_offset;
  222. MagickOffsetType
  223. restore_offset;
  224. PointInfo
  225. northeast,
  226. southwest;
  227. ssize_t
  228. count;
  229. unsigned char
  230. *blob;
  231. unsigned int
  232. tile_length;
  233. northeast.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  234. northeast.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  235. southwest.x=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  236. southwest.y=180.0*ReadBlobLSBSignedLong(image)/0x7fffffff;
  237. (void) ReadBlobLSBShort(image); /* width */
  238. (void) ReadBlobLSBShort(image); /* height */
  239. tile_length=ReadBlobLSBLong(image);
  240. tile_offset=ReadBlobLSBSignedLong(image);
  241. if (tile_offset == -1)
  242. continue;
  243. restore_offset=TellBlob(image);
  244. if (restore_offset < 0)
  245. continue;
  246. offset=SeekBlob(image,(MagickOffsetType) tile_offset,SEEK_SET);
  247. if (offset != (MagickOffsetType) tile_offset)
  248. continue;
  249. /*
  250. Read a tile.
  251. */
  252. blob=(unsigned char *) AcquireQuantumMemory((size_t) tile_length+2,
  253. sizeof(*blob));
  254. if (blob == (unsigned char *) NULL)
  255. {
  256. if (images != (Image *) NULL)
  257. images=DestroyImageList(images);
  258. ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
  259. }
  260. blob[0]=0xFF;
  261. blob[1]=0xD8;
  262. count=ReadBlob(image,tile_length,blob+2);
  263. if (count != (ssize_t) tile_length)
  264. {
  265. if (images != (Image *) NULL)
  266. images=DestroyImageList(images);
  267. blob=(unsigned char *) RelinquishMagickMemory(blob);
  268. ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
  269. }
  270. read_info=CloneImageInfo(image_info);
  271. (void) CopyMagickString(read_info->magick,"JPEG",MagickPathExtent);
  272. tile_image=BlobToImage(read_info,blob,tile_length+2,exception);
  273. read_info=DestroyImageInfo(read_info);
  274. blob=(unsigned char *) RelinquishMagickMemory(blob);
  275. offset=SeekBlob(image,restore_offset,SEEK_SET);
  276. if (tile_image == (Image *) NULL)
  277. continue;
  278. (void) CopyMagickString(tile_image->magick,image->magick,MagickPathExtent);
  279. (void) FormatImageProperty(tile_image,"jnx:northeast","%.20g,%.20g",
  280. northeast.x,northeast.y);
  281. (void) FormatImageProperty(tile_image,"jnx:southwest","%.20g,%.20g",
  282. southwest.x,southwest.y);
  283. AppendImageToList(&images,tile_image);
  284. }
  285. if (image->progress_monitor != (MagickProgressMonitor) NULL)
  286. {
  287. MagickBooleanType
  288. proceed;
  289. proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) i,
  290. (MagickSizeType) jnx_info.levels);
  291. if (proceed == MagickFalse)
  292. status=MagickFalse;
  293. }
  294. }
  295. (void) CloseBlob(image);
  296. image=DestroyImage(image);
  297. if (images == (Image *) NULL)
  298. return((Image *) NULL);
  299. return(GetFirstImageInList(images));
  300. }
  301. /*
  302. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  303. % %
  304. % %
  305. % %
  306. % R e g i s t e r J N X I m a g e %
  307. % %
  308. % %
  309. % %
  310. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  311. %
  312. % RegisterJNXImage() adds attributes for the JNX image format to the list
  313. % of supported formats. The attributes include the image format tag, a
  314. % method to read and/or write the format, whether the format supports the
  315. % saving of more than one frame to the same file or blob, whether the format
  316. % supports native in-memory I/O, and a brief description of the format.
  317. %
  318. % The format of the RegisterJNXImage method is:
  319. %
  320. % size_t RegisterJNXImage(void)
  321. %
  322. */
  323. ModuleExport size_t RegisterJNXImage(void)
  324. {
  325. MagickInfo
  326. *entry;
  327. entry=AcquireMagickInfo("JNX","JNX","Garmin tile format");
  328. entry->decoder=(DecodeImageHandler *) ReadJNXImage;
  329. entry->flags|=CoderSeekableStreamFlag;
  330. (void) RegisterMagickInfo(entry);
  331. return(MagickImageCoderSignature);
  332. }
  333. /*
  334. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  335. % %
  336. % %
  337. % %
  338. % U n r e g i s t e r J N X I m a g e %
  339. % %
  340. % %
  341. % %
  342. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343. %
  344. % UnregisterJNXImage() removes format registrations made by the
  345. % JNX module from the list of supported formats.
  346. %
  347. % The format of the UnregisterJNXImage method is:
  348. %
  349. % UnregisterJNXImage(void)
  350. %
  351. */
  352. ModuleExport void UnregisterJNXImage(void)
  353. {
  354. (void) UnregisterMagickInfo("JNX");
  355. }