pdf2json 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. data/README.markdown +9 -0
  2. data/bin/.gitkeep +0 -0
  3. data/ext/extconf.rb +30 -0
  4. data/lib/pdf2json.rb +8 -0
  5. data/pdf2json-0.52-source/AUTHORS +24 -0
  6. data/pdf2json-0.52-source/CHANGES +11 -0
  7. data/pdf2json-0.52-source/Makefile +84 -0
  8. data/pdf2json-0.52-source/Makefile.in +84 -0
  9. data/pdf2json-0.52-source/aclocal.m4 +274 -0
  10. data/pdf2json-0.52-source/aconf-win32.h +86 -0
  11. data/pdf2json-0.52-source/aconf.h +42 -0
  12. data/pdf2json-0.52-source/aconf.h.in +41 -0
  13. data/pdf2json-0.52-source/autom4te.cache/output.0 +6908 -0
  14. data/pdf2json-0.52-source/autom4te.cache/requests +76 -0
  15. data/pdf2json-0.52-source/autom4te.cache/traces.0 +466 -0
  16. data/pdf2json-0.52-source/config.log +1259 -0
  17. data/pdf2json-0.52-source/config.status +1050 -0
  18. data/pdf2json-0.52-source/configure +6908 -0
  19. data/pdf2json-0.52-source/configure.ac +93 -0
  20. data/pdf2json-0.52-source/doc/pdffonts.1 +130 -0
  21. data/pdf2json-0.52-source/doc/pdffonts.cat +107 -0
  22. data/pdf2json-0.52-source/doc/pdffonts.hlp +117 -0
  23. data/pdf2json-0.52-source/doc/pdfimages.1 +102 -0
  24. data/pdf2json-0.52-source/doc/pdfimages.cat +92 -0
  25. data/pdf2json-0.52-source/doc/pdfimages.hlp +101 -0
  26. data/pdf2json-0.52-source/doc/pdfinfo.1 +158 -0
  27. data/pdf2json-0.52-source/doc/pdfinfo.cat +119 -0
  28. data/pdf2json-0.52-source/doc/pdfinfo.hlp +129 -0
  29. data/pdf2json-0.52-source/doc/pdftoppm.1 +115 -0
  30. data/pdf2json-0.52-source/doc/pdftoppm.cat +105 -0
  31. data/pdf2json-0.52-source/doc/pdftoppm.hlp +114 -0
  32. data/pdf2json-0.52-source/doc/pdftops.1 +229 -0
  33. data/pdf2json-0.52-source/doc/pdftops.cat +221 -0
  34. data/pdf2json-0.52-source/doc/pdftops.hlp +231 -0
  35. data/pdf2json-0.52-source/doc/pdftotext.1 +137 -0
  36. data/pdf2json-0.52-source/doc/pdftotext.cat +120 -0
  37. data/pdf2json-0.52-source/doc/pdftotext.hlp +133 -0
  38. data/pdf2json-0.52-source/doc/sample-xpdfrc +91 -0
  39. data/pdf2json-0.52-source/doc/xpdf.1 +513 -0
  40. data/pdf2json-0.52-source/doc/xpdf.cat +476 -0
  41. data/pdf2json-0.52-source/doc/xpdf.hlp +489 -0
  42. data/pdf2json-0.52-source/doc/xpdfrc.5 +480 -0
  43. data/pdf2json-0.52-source/doc/xpdfrc.cat +474 -0
  44. data/pdf2json-0.52-source/doc/xpdfrc.hlp +479 -0
  45. data/pdf2json-0.52-source/fofi/.DS_Store +0 -0
  46. data/pdf2json-0.52-source/fofi/FoFiBase.cc +156 -0
  47. data/pdf2json-0.52-source/fofi/FoFiBase.h +57 -0
  48. data/pdf2json-0.52-source/fofi/FoFiBase.o +0 -0
  49. data/pdf2json-0.52-source/fofi/FoFiEncodings.cc +994 -0
  50. data/pdf2json-0.52-source/fofi/FoFiEncodings.h +36 -0
  51. data/pdf2json-0.52-source/fofi/FoFiEncodings.o +0 -0
  52. data/pdf2json-0.52-source/fofi/FoFiTrueType.cc +2027 -0
  53. data/pdf2json-0.52-source/fofi/FoFiTrueType.h +174 -0
  54. data/pdf2json-0.52-source/fofi/FoFiTrueType.o +0 -0
  55. data/pdf2json-0.52-source/fofi/FoFiType1.cc +252 -0
  56. data/pdf2json-0.52-source/fofi/FoFiType1.h +59 -0
  57. data/pdf2json-0.52-source/fofi/FoFiType1.o +0 -0
  58. data/pdf2json-0.52-source/fofi/FoFiType1C.cc +2603 -0
  59. data/pdf2json-0.52-source/fofi/FoFiType1C.h +233 -0
  60. data/pdf2json-0.52-source/fofi/FoFiType1C.o +0 -0
  61. data/pdf2json-0.52-source/fofi/Makefile +70 -0
  62. data/pdf2json-0.52-source/fofi/Makefile.dep +0 -0
  63. data/pdf2json-0.52-source/fofi/Makefile.in +70 -0
  64. data/pdf2json-0.52-source/fofi/libfofi.a +0 -0
  65. data/pdf2json-0.52-source/fofi/vms_make.com +0 -0
  66. data/pdf2json-0.52-source/freetype.win32/.DS_Store +0 -0
  67. data/pdf2json-0.52-source/freetype.win32/include/.DS_Store +0 -0
  68. data/pdf2json-0.52-source/freetype.win32/include/freetype/config/ftconfig.h +528 -0
  69. data/pdf2json-0.52-source/freetype.win32/include/freetype/config/ftheader.h +780 -0
  70. data/pdf2json-0.52-source/freetype.win32/include/freetype/config/ftmodule.h +32 -0
  71. data/pdf2json-0.52-source/freetype.win32/include/freetype/config/ftoption.h +733 -0
  72. data/pdf2json-0.52-source/freetype.win32/include/freetype/config/ftstdlib.h +173 -0
  73. data/pdf2json-0.52-source/freetype.win32/include/freetype/freetype.h +3919 -0
  74. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftadvanc.h +179 -0
  75. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftbbox.h +94 -0
  76. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftbdf.h +209 -0
  77. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftbitmap.h +227 -0
  78. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftcache.h +1128 -0
  79. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftchapters.h +103 -0
  80. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftcid.h +166 -0
  81. data/pdf2json-0.52-source/freetype.win32/include/freetype/fterrdef.h +244 -0
  82. data/pdf2json-0.52-source/freetype.win32/include/freetype/fterrors.h +206 -0
  83. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftgasp.h +120 -0
  84. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftglyph.h +613 -0
  85. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftgxval.h +358 -0
  86. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftgzip.h +102 -0
  87. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftimage.h +1313 -0
  88. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftincrem.h +353 -0
  89. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftlcdfil.h +213 -0
  90. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftlist.h +277 -0
  91. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftlzw.h +99 -0
  92. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftmac.h +274 -0
  93. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftmm.h +378 -0
  94. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftmodapi.h +483 -0
  95. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftmoderr.h +155 -0
  96. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftotval.h +203 -0
  97. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftoutln.h +537 -0
  98. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftpfr.h +172 -0
  99. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftrender.h +230 -0
  100. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftsizes.h +159 -0
  101. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftsnames.h +200 -0
  102. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftstroke.h +716 -0
  103. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftsynth.h +80 -0
  104. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftsystem.h +347 -0
  105. data/pdf2json-0.52-source/freetype.win32/include/freetype/fttrigon.h +350 -0
  106. data/pdf2json-0.52-source/freetype.win32/include/freetype/fttypes.h +588 -0
  107. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftwinfnt.h +274 -0
  108. data/pdf2json-0.52-source/freetype.win32/include/freetype/ftxf86.h +83 -0
  109. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/autohint.h +231 -0
  110. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftcalc.h +179 -0
  111. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftdebug.h +250 -0
  112. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftdriver.h +422 -0
  113. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftgloadr.h +168 -0
  114. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftmemory.h +380 -0
  115. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftobjs.h +1428 -0
  116. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftpic.h +67 -0
  117. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftrfork.h +196 -0
  118. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftserv.h +620 -0
  119. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftstream.h +539 -0
  120. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/fttrace.h +139 -0
  121. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/ftvalid.h +150 -0
  122. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/internal.h +51 -0
  123. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/pcftypes.h +56 -0
  124. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/psaux.h +873 -0
  125. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/pshints.h +712 -0
  126. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svbdf.h +77 -0
  127. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svcid.h +83 -0
  128. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svgldict.h +82 -0
  129. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svgxval.h +72 -0
  130. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svkern.h +51 -0
  131. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svmm.h +104 -0
  132. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svotval.h +55 -0
  133. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svpfr.h +66 -0
  134. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svpostnm.h +79 -0
  135. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svpscmap.h +164 -0
  136. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svpsinfo.h +92 -0
  137. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svsfnt.h +102 -0
  138. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svttcmap.h +106 -0
  139. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svtteng.h +53 -0
  140. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svttglyf.h +67 -0
  141. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svwinfnt.h +50 -0
  142. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/services/svxf86nm.h +55 -0
  143. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/sfnt.h +897 -0
  144. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/t1types.h +270 -0
  145. data/pdf2json-0.52-source/freetype.win32/include/freetype/internal/tttypes.h +1543 -0
  146. data/pdf2json-0.52-source/freetype.win32/include/freetype/t1tables.h +504 -0
  147. data/pdf2json-0.52-source/freetype.win32/include/freetype/ttnameid.h +1247 -0
  148. data/pdf2json-0.52-source/freetype.win32/include/freetype/tttables.h +759 -0
  149. data/pdf2json-0.52-source/freetype.win32/include/freetype/tttags.h +107 -0
  150. data/pdf2json-0.52-source/freetype.win32/include/freetype/ttunpat.h +59 -0
  151. data/pdf2json-0.52-source/freetype.win32/include/ft2build.h +39 -0
  152. data/pdf2json-0.52-source/freetype.win32/lib/freetype_a.lib +0 -0
  153. data/pdf2json-0.52-source/goo/.DS_Store +0 -0
  154. data/pdf2json-0.52-source/goo/FixedPoint.cc +118 -0
  155. data/pdf2json-0.52-source/goo/FixedPoint.h +155 -0
  156. data/pdf2json-0.52-source/goo/FixedPoint.o +0 -0
  157. data/pdf2json-0.52-source/goo/GHash.cc +380 -0
  158. data/pdf2json-0.52-source/goo/GHash.h +78 -0
  159. data/pdf2json-0.52-source/goo/GHash.o +0 -0
  160. data/pdf2json-0.52-source/goo/GList.cc +97 -0
  161. data/pdf2json-0.52-source/goo/GList.h +96 -0
  162. data/pdf2json-0.52-source/goo/GList.o +0 -0
  163. data/pdf2json-0.52-source/goo/GMutex.h +49 -0
  164. data/pdf2json-0.52-source/goo/GString.cc +724 -0
  165. data/pdf2json-0.52-source/goo/GString.cc.fixed +718 -0
  166. data/pdf2json-0.52-source/goo/GString.h +136 -0
  167. data/pdf2json-0.52-source/goo/GString.o +0 -0
  168. data/pdf2json-0.52-source/goo/ImgWriter.o +0 -0
  169. data/pdf2json-0.52-source/goo/JpegWriter.o +0 -0
  170. data/pdf2json-0.52-source/goo/Makefile +72 -0
  171. data/pdf2json-0.52-source/goo/Makefile.dep +0 -0
  172. data/pdf2json-0.52-source/goo/Makefile.in +72 -0
  173. data/pdf2json-0.52-source/goo/PNGWriter.o +0 -0
  174. data/pdf2json-0.52-source/goo/gfile.cc +731 -0
  175. data/pdf2json-0.52-source/goo/gfile.h +138 -0
  176. data/pdf2json-0.52-source/goo/gfile.o +0 -0
  177. data/pdf2json-0.52-source/goo/gmem.cc +264 -0
  178. data/pdf2json-0.52-source/goo/gmem.h +79 -0
  179. data/pdf2json-0.52-source/goo/gmem.o +0 -0
  180. data/pdf2json-0.52-source/goo/gmempp.cc +32 -0
  181. data/pdf2json-0.52-source/goo/gmempp.o +0 -0
  182. data/pdf2json-0.52-source/goo/gtypes.h +29 -0
  183. data/pdf2json-0.52-source/goo/libGoo.a +0 -0
  184. data/pdf2json-0.52-source/goo/parseargs.c +190 -0
  185. data/pdf2json-0.52-source/goo/parseargs.h +71 -0
  186. data/pdf2json-0.52-source/goo/parseargs.o +0 -0
  187. data/pdf2json-0.52-source/goo/vms_directory.c +214 -0
  188. data/pdf2json-0.52-source/goo/vms_dirent.h +67 -0
  189. data/pdf2json-0.52-source/goo/vms_make.com +82 -0
  190. data/pdf2json-0.52-source/goo/vms_sys_dirent.h +54 -0
  191. data/pdf2json-0.52-source/goo/vms_unix_time.h +102 -0
  192. data/pdf2json-0.52-source/goo/vms_unix_times.c +42 -0
  193. data/pdf2json-0.52-source/goo/vms_unlink.c +22 -0
  194. data/pdf2json-0.52-source/ms_make.bat +199 -0
  195. data/pdf2json-0.52-source/splash/.DS_Store +0 -0
  196. data/pdf2json-0.52-source/splash/Makefile +103 -0
  197. data/pdf2json-0.52-source/splash/Makefile.dep +0 -0
  198. data/pdf2json-0.52-source/splash/Makefile.in +103 -0
  199. data/pdf2json-0.52-source/splash/Splash.cc +3310 -0
  200. data/pdf2json-0.52-source/splash/Splash.h +293 -0
  201. data/pdf2json-0.52-source/splash/Splash.o +0 -0
  202. data/pdf2json-0.52-source/splash/SplashBitmap.cc +188 -0
  203. data/pdf2json-0.52-source/splash/SplashBitmap.h +64 -0
  204. data/pdf2json-0.52-source/splash/SplashBitmap.o +0 -0
  205. data/pdf2json-0.52-source/splash/SplashClip.cc +382 -0
  206. data/pdf2json-0.52-source/splash/SplashClip.h +107 -0
  207. data/pdf2json-0.52-source/splash/SplashClip.o +0 -0
  208. data/pdf2json-0.52-source/splash/SplashErrorCodes.h +32 -0
  209. data/pdf2json-0.52-source/splash/SplashFTFont.cc +357 -0
  210. data/pdf2json-0.52-source/splash/SplashFTFont.h +58 -0
  211. data/pdf2json-0.52-source/splash/SplashFTFont.o +0 -0
  212. data/pdf2json-0.52-source/splash/SplashFTFontEngine.cc +179 -0
  213. data/pdf2json-0.52-source/splash/SplashFTFontEngine.h +65 -0
  214. data/pdf2json-0.52-source/splash/SplashFTFontEngine.o +0 -0
  215. data/pdf2json-0.52-source/splash/SplashFTFontFile.cc +114 -0
  216. data/pdf2json-0.52-source/splash/SplashFTFontFile.h +73 -0
  217. data/pdf2json-0.52-source/splash/SplashFTFontFile.o +0 -0
  218. data/pdf2json-0.52-source/splash/SplashFont.cc +176 -0
  219. data/pdf2json-0.52-source/splash/SplashFont.h +104 -0
  220. data/pdf2json-0.52-source/splash/SplashFont.o +0 -0
  221. data/pdf2json-0.52-source/splash/SplashFontEngine.cc +317 -0
  222. data/pdf2json-0.52-source/splash/SplashFontEngine.h +91 -0
  223. data/pdf2json-0.52-source/splash/SplashFontEngine.o +0 -0
  224. data/pdf2json-0.52-source/splash/SplashFontFile.cc +55 -0
  225. data/pdf2json-0.52-source/splash/SplashFontFile.h +60 -0
  226. data/pdf2json-0.52-source/splash/SplashFontFile.o +0 -0
  227. data/pdf2json-0.52-source/splash/SplashFontFileID.cc +23 -0
  228. data/pdf2json-0.52-source/splash/SplashFontFileID.h +30 -0
  229. data/pdf2json-0.52-source/splash/SplashFontFileID.o +0 -0
  230. data/pdf2json-0.52-source/splash/SplashGlyphBitmap.h +26 -0
  231. data/pdf2json-0.52-source/splash/SplashMath.h +89 -0
  232. data/pdf2json-0.52-source/splash/SplashPath.cc +184 -0
  233. data/pdf2json-0.52-source/splash/SplashPath.h +121 -0
  234. data/pdf2json-0.52-source/splash/SplashPath.o +0 -0
  235. data/pdf2json-0.52-source/splash/SplashPattern.cc +40 -0
  236. data/pdf2json-0.52-source/splash/SplashPattern.h +65 -0
  237. data/pdf2json-0.52-source/splash/SplashPattern.o +0 -0
  238. data/pdf2json-0.52-source/splash/SplashScreen.cc +383 -0
  239. data/pdf2json-0.52-source/splash/SplashScreen.h +56 -0
  240. data/pdf2json-0.52-source/splash/SplashScreen.o +0 -0
  241. data/pdf2json-0.52-source/splash/SplashState.cc +165 -0
  242. data/pdf2json-0.52-source/splash/SplashState.h +103 -0
  243. data/pdf2json-0.52-source/splash/SplashState.o +0 -0
  244. data/pdf2json-0.52-source/splash/SplashT1Font.cc +287 -0
  245. data/pdf2json-0.52-source/splash/SplashT1Font.h +57 -0
  246. data/pdf2json-0.52-source/splash/SplashT1Font.o +0 -0
  247. data/pdf2json-0.52-source/splash/SplashT1FontEngine.cc +124 -0
  248. data/pdf2json-0.52-source/splash/SplashT1FontEngine.h +53 -0
  249. data/pdf2json-0.52-source/splash/SplashT1FontEngine.o +0 -0
  250. data/pdf2json-0.52-source/splash/SplashT1FontFile.cc +97 -0
  251. data/pdf2json-0.52-source/splash/SplashT1FontFile.h +58 -0
  252. data/pdf2json-0.52-source/splash/SplashT1FontFile.o +0 -0
  253. data/pdf2json-0.52-source/splash/SplashTypes.h +132 -0
  254. data/pdf2json-0.52-source/splash/SplashXPath.cc +438 -0
  255. data/pdf2json-0.52-source/splash/SplashXPath.h +100 -0
  256. data/pdf2json-0.52-source/splash/SplashXPath.o +0 -0
  257. data/pdf2json-0.52-source/splash/SplashXPathScanner.cc +428 -0
  258. data/pdf2json-0.52-source/splash/SplashXPathScanner.h +87 -0
  259. data/pdf2json-0.52-source/splash/SplashXPathScanner.o +0 -0
  260. data/pdf2json-0.52-source/splash/libsplash.a +0 -0
  261. data/pdf2json-0.52-source/splash/vms_make.com +0 -0
  262. data/pdf2json-0.52-source/src/.DS_Store +0 -0
  263. data/pdf2json-0.52-source/src/GVector.h +101 -0
  264. data/pdf2json-0.52-source/src/ImgOutputDev.cc +1243 -0
  265. data/pdf2json-0.52-source/src/ImgOutputDev.h +307 -0
  266. data/pdf2json-0.52-source/src/ImgOutputDev.o +0 -0
  267. data/pdf2json-0.52-source/src/Makefile +68 -0
  268. data/pdf2json-0.52-source/src/Makefile.in +68 -0
  269. data/pdf2json-0.52-source/src/XmlFonts.cc +367 -0
  270. data/pdf2json-0.52-source/src/XmlFonts.h +91 -0
  271. data/pdf2json-0.52-source/src/XmlFonts.o +0 -0
  272. data/pdf2json-0.52-source/src/XmlLinks.cc +101 -0
  273. data/pdf2json-0.52-source/src/XmlLinks.h +54 -0
  274. data/pdf2json-0.52-source/src/XmlLinks.o +0 -0
  275. data/pdf2json-0.52-source/src/pdf2json +0 -0
  276. data/pdf2json-0.52-source/src/pdf2json.cc +343 -0
  277. data/pdf2json-0.52-source/src/pdf2json.o +0 -0
  278. data/pdf2json-0.52-source/src/pdf2xml.dtd +22 -0
  279. data/pdf2json-0.52-source/src/pdf2xmljson.dtd +9 -0
  280. data/pdf2json-0.52-source/xpdf/.DS_Store +0 -0
  281. data/pdf2json-0.52-source/xpdf/Annot.cc +1556 -0
  282. data/pdf2json-0.52-source/xpdf/Annot.h +142 -0
  283. data/pdf2json-0.52-source/xpdf/Annot.o +0 -0
  284. data/pdf2json-0.52-source/xpdf/Array.cc +73 -0
  285. data/pdf2json-0.52-source/xpdf/Array.h +58 -0
  286. data/pdf2json-0.52-source/xpdf/Array.o +0 -0
  287. data/pdf2json-0.52-source/xpdf/BuiltinFont.cc +65 -0
  288. data/pdf2json-0.52-source/xpdf/BuiltinFont.h +57 -0
  289. data/pdf2json-0.52-source/xpdf/BuiltinFont.o +0 -0
  290. data/pdf2json-0.52-source/xpdf/BuiltinFontTables.cc +4284 -0
  291. data/pdf2json-0.52-source/xpdf/BuiltinFontTables.h +23 -0
  292. data/pdf2json-0.52-source/xpdf/BuiltinFontTables.o +0 -0
  293. data/pdf2json-0.52-source/xpdf/CMap.cc +408 -0
  294. data/pdf2json-0.52-source/xpdf/CMap.h +102 -0
  295. data/pdf2json-0.52-source/xpdf/CMap.o +0 -0
  296. data/pdf2json-0.52-source/xpdf/Catalog.cc +374 -0
  297. data/pdf2json-0.52-source/xpdf/Catalog.h +97 -0
  298. data/pdf2json-0.52-source/xpdf/Catalog.o +0 -0
  299. data/pdf2json-0.52-source/xpdf/CharCodeToUnicode.cc +540 -0
  300. data/pdf2json-0.52-source/xpdf/CharCodeToUnicode.h +117 -0
  301. data/pdf2json-0.52-source/xpdf/CharCodeToUnicode.o +0 -0
  302. data/pdf2json-0.52-source/xpdf/CharTypes.h +24 -0
  303. data/pdf2json-0.52-source/xpdf/CompactFontTables.h +464 -0
  304. data/pdf2json-0.52-source/xpdf/CoreOutputDev.cc +61 -0
  305. data/pdf2json-0.52-source/xpdf/CoreOutputDev.h +61 -0
  306. data/pdf2json-0.52-source/xpdf/Decrypt.cc +776 -0
  307. data/pdf2json-0.52-source/xpdf/Decrypt.h +95 -0
  308. data/pdf2json-0.52-source/xpdf/Decrypt.o +0 -0
  309. data/pdf2json-0.52-source/xpdf/Dict.cc +95 -0
  310. data/pdf2json-0.52-source/xpdf/Dict.h +77 -0
  311. data/pdf2json-0.52-source/xpdf/Dict.o +0 -0
  312. data/pdf2json-0.52-source/xpdf/Error.cc +38 -0
  313. data/pdf2json-0.52-source/xpdf/Error.h +23 -0
  314. data/pdf2json-0.52-source/xpdf/Error.o +0 -0
  315. data/pdf2json-0.52-source/xpdf/ErrorCodes.h +36 -0
  316. data/pdf2json-0.52-source/xpdf/FontEncodingTables.cc +1824 -0
  317. data/pdf2json-0.52-source/xpdf/FontEncodingTables.h +20 -0
  318. data/pdf2json-0.52-source/xpdf/FontEncodingTables.o +0 -0
  319. data/pdf2json-0.52-source/xpdf/Function.cc +1573 -0
  320. data/pdf2json-0.52-source/xpdf/Function.h +229 -0
  321. data/pdf2json-0.52-source/xpdf/Function.o +0 -0
  322. data/pdf2json-0.52-source/xpdf/Gfx.cc +4187 -0
  323. data/pdf2json-0.52-source/xpdf/Gfx.h +312 -0
  324. data/pdf2json-0.52-source/xpdf/Gfx.o +0 -0
  325. data/pdf2json-0.52-source/xpdf/GfxFont.cc +1568 -0
  326. data/pdf2json-0.52-source/xpdf/GfxFont.h +320 -0
  327. data/pdf2json-0.52-source/xpdf/GfxFont.o +0 -0
  328. data/pdf2json-0.52-source/xpdf/GfxState.cc +4137 -0
  329. data/pdf2json-0.52-source/xpdf/GfxState.h +1244 -0
  330. data/pdf2json-0.52-source/xpdf/GfxState.o +0 -0
  331. data/pdf2json-0.52-source/xpdf/GlobalParams.cc +2924 -0
  332. data/pdf2json-0.52-source/xpdf/GlobalParams.cc.old +2908 -0
  333. data/pdf2json-0.52-source/xpdf/GlobalParams.h +466 -0
  334. data/pdf2json-0.52-source/xpdf/GlobalParams.h.old +463 -0
  335. data/pdf2json-0.52-source/xpdf/GlobalParams.o +0 -0
  336. data/pdf2json-0.52-source/xpdf/ImageOutputDev.cc +195 -0
  337. data/pdf2json-0.52-source/xpdf/ImageOutputDev.h +76 -0
  338. data/pdf2json-0.52-source/xpdf/ImageOutputDev.o +0 -0
  339. data/pdf2json-0.52-source/xpdf/JArithmeticDecoder.cc +322 -0
  340. data/pdf2json-0.52-source/xpdf/JArithmeticDecoder.h +109 -0
  341. data/pdf2json-0.52-source/xpdf/JArithmeticDecoder.o +0 -0
  342. data/pdf2json-0.52-source/xpdf/JBIG2Stream.cc +3413 -0
  343. data/pdf2json-0.52-source/xpdf/JBIG2Stream.h +145 -0
  344. data/pdf2json-0.52-source/xpdf/JBIG2Stream.o +0 -0
  345. data/pdf2json-0.52-source/xpdf/JPXStream.cc +3144 -0
  346. data/pdf2json-0.52-source/xpdf/JPXStream.h +351 -0
  347. data/pdf2json-0.52-source/xpdf/JPXStream.o +0 -0
  348. data/pdf2json-0.52-source/xpdf/Lexer.cc +485 -0
  349. data/pdf2json-0.52-source/xpdf/Lexer.h +80 -0
  350. data/pdf2json-0.52-source/xpdf/Lexer.o +0 -0
  351. data/pdf2json-0.52-source/xpdf/Link.cc +806 -0
  352. data/pdf2json-0.52-source/xpdf/Link.cc.old +784 -0
  353. data/pdf2json-0.52-source/xpdf/Link.h +415 -0
  354. data/pdf2json-0.52-source/xpdf/Link.h.old +369 -0
  355. data/pdf2json-0.52-source/xpdf/Link.o +0 -0
  356. data/pdf2json-0.52-source/xpdf/Makefile +232 -0
  357. data/pdf2json-0.52-source/xpdf/Makefile.dep +0 -0
  358. data/pdf2json-0.52-source/xpdf/Makefile.in +232 -0
  359. data/pdf2json-0.52-source/xpdf/NameToCharCode.cc +116 -0
  360. data/pdf2json-0.52-source/xpdf/NameToCharCode.h +42 -0
  361. data/pdf2json-0.52-source/xpdf/NameToCharCode.o +0 -0
  362. data/pdf2json-0.52-source/xpdf/NameToUnicodeTable.h +1097 -0
  363. data/pdf2json-0.52-source/xpdf/Object.cc +231 -0
  364. data/pdf2json-0.52-source/xpdf/Object.h +303 -0
  365. data/pdf2json-0.52-source/xpdf/Object.o +0 -0
  366. data/pdf2json-0.52-source/xpdf/Outline.cc +151 -0
  367. data/pdf2json-0.52-source/xpdf/Outline.h +76 -0
  368. data/pdf2json-0.52-source/xpdf/Outline.o +0 -0
  369. data/pdf2json-0.52-source/xpdf/OutputDev.cc +131 -0
  370. data/pdf2json-0.52-source/xpdf/OutputDev.h +253 -0
  371. data/pdf2json-0.52-source/xpdf/OutputDev.o +0 -0
  372. data/pdf2json-0.52-source/xpdf/PDFCore.cc +2044 -0
  373. data/pdf2json-0.52-source/xpdf/PDFCore.h +321 -0
  374. data/pdf2json-0.52-source/xpdf/PDFDoc.cc +404 -0
  375. data/pdf2json-0.52-source/xpdf/PDFDoc.h +183 -0
  376. data/pdf2json-0.52-source/xpdf/PDFDoc.o +0 -0
  377. data/pdf2json-0.52-source/xpdf/PDFDocEncoding.cc +44 -0
  378. data/pdf2json-0.52-source/xpdf/PDFDocEncoding.h +16 -0
  379. data/pdf2json-0.52-source/xpdf/PDFDocEncoding.o +0 -0
  380. data/pdf2json-0.52-source/xpdf/PSOutputDev.cc +6224 -0
  381. data/pdf2json-0.52-source/xpdf/PSOutputDev.h +395 -0
  382. data/pdf2json-0.52-source/xpdf/PSOutputDev.o +0 -0
  383. data/pdf2json-0.52-source/xpdf/PSTokenizer.cc +135 -0
  384. data/pdf2json-0.52-source/xpdf/PSTokenizer.h +41 -0
  385. data/pdf2json-0.52-source/xpdf/PSTokenizer.o +0 -0
  386. data/pdf2json-0.52-source/xpdf/Page.cc +454 -0
  387. data/pdf2json-0.52-source/xpdf/Page.h +187 -0
  388. data/pdf2json-0.52-source/xpdf/Page.o +0 -0
  389. data/pdf2json-0.52-source/xpdf/Parser.cc +227 -0
  390. data/pdf2json-0.52-source/xpdf/Parser.h +59 -0
  391. data/pdf2json-0.52-source/xpdf/Parser.o +0 -0
  392. data/pdf2json-0.52-source/xpdf/PreScanOutputDev.cc +257 -0
  393. data/pdf2json-0.52-source/xpdf/PreScanOutputDev.h +130 -0
  394. data/pdf2json-0.52-source/xpdf/PreScanOutputDev.o +0 -0
  395. data/pdf2json-0.52-source/xpdf/SecurityHandler.cc +390 -0
  396. data/pdf2json-0.52-source/xpdf/SecurityHandler.h +160 -0
  397. data/pdf2json-0.52-source/xpdf/SecurityHandler.o +0 -0
  398. data/pdf2json-0.52-source/xpdf/SplashOutputDev.cc +2845 -0
  399. data/pdf2json-0.52-source/xpdf/SplashOutputDev.h +247 -0
  400. data/pdf2json-0.52-source/xpdf/SplashOutputDev.o +0 -0
  401. data/pdf2json-0.52-source/xpdf/Stream-CCITT.h +459 -0
  402. data/pdf2json-0.52-source/xpdf/Stream.cc +4627 -0
  403. data/pdf2json-0.52-source/xpdf/Stream.h +858 -0
  404. data/pdf2json-0.52-source/xpdf/Stream.o +0 -0
  405. data/pdf2json-0.52-source/xpdf/TextOutputDev.cc +4090 -0
  406. data/pdf2json-0.52-source/xpdf/TextOutputDev.h +661 -0
  407. data/pdf2json-0.52-source/xpdf/TextOutputDev.o +0 -0
  408. data/pdf2json-0.52-source/xpdf/UTF8.h +56 -0
  409. data/pdf2json-0.52-source/xpdf/UnicodeMap.cc +302 -0
  410. data/pdf2json-0.52-source/xpdf/UnicodeMap.cc.old +293 -0
  411. data/pdf2json-0.52-source/xpdf/UnicodeMap.h +135 -0
  412. data/pdf2json-0.52-source/xpdf/UnicodeMap.h.old +123 -0
  413. data/pdf2json-0.52-source/xpdf/UnicodeMap.o +0 -0
  414. data/pdf2json-0.52-source/xpdf/UnicodeMapTables.h +361 -0
  415. data/pdf2json-0.52-source/xpdf/UnicodeTypeTable.cc +949 -0
  416. data/pdf2json-0.52-source/xpdf/UnicodeTypeTable.h +20 -0
  417. data/pdf2json-0.52-source/xpdf/UnicodeTypeTable.o +0 -0
  418. data/pdf2json-0.52-source/xpdf/XPDFApp.cc +447 -0
  419. data/pdf2json-0.52-source/xpdf/XPDFApp.h +114 -0
  420. data/pdf2json-0.52-source/xpdf/XPDFCore.cc +1655 -0
  421. data/pdf2json-0.52-source/xpdf/XPDFCore.h +251 -0
  422. data/pdf2json-0.52-source/xpdf/XPDFTree.cc +931 -0
  423. data/pdf2json-0.52-source/xpdf/XPDFTree.h +45 -0
  424. data/pdf2json-0.52-source/xpdf/XPDFTreeP.h +87 -0
  425. data/pdf2json-0.52-source/xpdf/XPDFViewer.cc +3488 -0
  426. data/pdf2json-0.52-source/xpdf/XPDFViewer.h +352 -0
  427. data/pdf2json-0.52-source/xpdf/XRef.cc +896 -0
  428. data/pdf2json-0.52-source/xpdf/XRef.h +133 -0
  429. data/pdf2json-0.52-source/xpdf/XRef.o +0 -0
  430. data/pdf2json-0.52-source/xpdf/XpdfPluginAPI.cc +262 -0
  431. data/pdf2json-0.52-source/xpdf/XpdfPluginAPI.h +341 -0
  432. data/pdf2json-0.52-source/xpdf/XpdfPluginAPI.o +0 -0
  433. data/pdf2json-0.52-source/xpdf/about-text.h +48 -0
  434. data/pdf2json-0.52-source/xpdf/about.xbm +6 -0
  435. data/pdf2json-0.52-source/xpdf/backArrow.xbm +6 -0
  436. data/pdf2json-0.52-source/xpdf/backArrowDis.xbm +6 -0
  437. data/pdf2json-0.52-source/xpdf/config.h +112 -0
  438. data/pdf2json-0.52-source/xpdf/dblLeftArrow.xbm +6 -0
  439. data/pdf2json-0.52-source/xpdf/dblLeftArrowDis.xbm +6 -0
  440. data/pdf2json-0.52-source/xpdf/dblRightArrow.xbm +6 -0
  441. data/pdf2json-0.52-source/xpdf/dblRightArrowDis.xbm +6 -0
  442. data/pdf2json-0.52-source/xpdf/find.xbm +6 -0
  443. data/pdf2json-0.52-source/xpdf/findDis.xbm +6 -0
  444. data/pdf2json-0.52-source/xpdf/forwardArrow.xbm +6 -0
  445. data/pdf2json-0.52-source/xpdf/forwardArrowDis.xbm +6 -0
  446. data/pdf2json-0.52-source/xpdf/leftArrow.xbm +5 -0
  447. data/pdf2json-0.52-source/xpdf/leftArrowDis.xbm +5 -0
  448. data/pdf2json-0.52-source/xpdf/libXpdf.a +0 -0
  449. data/pdf2json-0.52-source/xpdf/pdffonts +0 -0
  450. data/pdf2json-0.52-source/xpdf/pdffonts.cc +298 -0
  451. data/pdf2json-0.52-source/xpdf/pdffonts.o +0 -0
  452. data/pdf2json-0.52-source/xpdf/pdfimages +0 -0
  453. data/pdf2json-0.52-source/xpdf/pdfimages.cc +155 -0
  454. data/pdf2json-0.52-source/xpdf/pdfimages.o +0 -0
  455. data/pdf2json-0.52-source/xpdf/pdfinfo +0 -0
  456. data/pdf2json-0.52-source/xpdf/pdfinfo.cc +387 -0
  457. data/pdf2json-0.52-source/xpdf/pdfinfo.o +0 -0
  458. data/pdf2json-0.52-source/xpdf/pdftoppm.cc +203 -0
  459. data/pdf2json-0.52-source/xpdf/pdftops +0 -0
  460. data/pdf2json-0.52-source/xpdf/pdftops.cc +344 -0
  461. data/pdf2json-0.52-source/xpdf/pdftops.o +0 -0
  462. data/pdf2json-0.52-source/xpdf/pdftotext +0 -0
  463. data/pdf2json-0.52-source/xpdf/pdftotext.cc +333 -0
  464. data/pdf2json-0.52-source/xpdf/pdftotext.o +0 -0
  465. data/pdf2json-0.52-source/xpdf/print.xbm +6 -0
  466. data/pdf2json-0.52-source/xpdf/printDis.xbm +6 -0
  467. data/pdf2json-0.52-source/xpdf/rightArrow.xbm +5 -0
  468. data/pdf2json-0.52-source/xpdf/rightArrowDis.xbm +5 -0
  469. data/pdf2json-0.52-source/xpdf/vms_make.com +129 -0
  470. data/pdf2json-0.52-source/xpdf/xpdf.cc +344 -0
  471. data/pdf2json-0.52-source/xpdf/xpdfIcon.xpm +62 -0
  472. data/pdf2json.gemspec +29 -0
  473. metadata +518 -0
@@ -0,0 +1,145 @@
1
+ //========================================================================
2
+ //
3
+ // JBIG2Stream.h
4
+ //
5
+ // Copyright 2002-2003 Glyph & Cog, LLC
6
+ //
7
+ //========================================================================
8
+
9
+ #ifndef JBIG2STREAM_H
10
+ #define JBIG2STREAM_H
11
+
12
+ #include <aconf.h>
13
+
14
+ #ifdef USE_GCC_PRAGMAS
15
+ #pragma interface
16
+ #endif
17
+
18
+ #include "gtypes.h"
19
+ #include "Object.h"
20
+ #include "Stream.h"
21
+
22
+ class GList;
23
+ class JBIG2Segment;
24
+ class JBIG2Bitmap;
25
+ class JArithmeticDecoder;
26
+ class JArithmeticDecoderStats;
27
+ class JBIG2HuffmanDecoder;
28
+ struct JBIG2HuffmanTable;
29
+ class JBIG2MMRDecoder;
30
+
31
+ //------------------------------------------------------------------------
32
+
33
+ class JBIG2Stream: public FilterStream {
34
+ public:
35
+
36
+ JBIG2Stream(Stream *strA, Object *globalsStreamA);
37
+ virtual ~JBIG2Stream();
38
+ virtual StreamKind getKind() { return strJBIG2; }
39
+ virtual void reset();
40
+ virtual void close();
41
+ virtual int getChar();
42
+ virtual int lookChar();
43
+ virtual GString *getPSFilter(int psLevel, char *indent);
44
+ virtual GBool isBinary(GBool last = gTrue);
45
+
46
+ private:
47
+
48
+ void readSegments();
49
+ GBool readSymbolDictSeg(Guint segNum, Guint length,
50
+ Guint *refSegs, Guint nRefSegs);
51
+ void readTextRegionSeg(Guint segNum, GBool imm,
52
+ GBool lossless, Guint length,
53
+ Guint *refSegs, Guint nRefSegs);
54
+ JBIG2Bitmap *readTextRegion(GBool huff, GBool refine,
55
+ int w, int h,
56
+ Guint numInstances,
57
+ Guint logStrips,
58
+ int numSyms,
59
+ JBIG2HuffmanTable *symCodeTab,
60
+ Guint symCodeLen,
61
+ JBIG2Bitmap **syms,
62
+ Guint defPixel, Guint combOp,
63
+ Guint transposed, Guint refCorner,
64
+ int sOffset,
65
+ JBIG2HuffmanTable *huffFSTable,
66
+ JBIG2HuffmanTable *huffDSTable,
67
+ JBIG2HuffmanTable *huffDTTable,
68
+ JBIG2HuffmanTable *huffRDWTable,
69
+ JBIG2HuffmanTable *huffRDHTable,
70
+ JBIG2HuffmanTable *huffRDXTable,
71
+ JBIG2HuffmanTable *huffRDYTable,
72
+ JBIG2HuffmanTable *huffRSizeTable,
73
+ Guint templ,
74
+ int *atx, int *aty);
75
+ void readPatternDictSeg(Guint segNum, Guint length);
76
+ void readHalftoneRegionSeg(Guint segNum, GBool imm,
77
+ GBool lossless, Guint length,
78
+ Guint *refSegs, Guint nRefSegs);
79
+ void readGenericRegionSeg(Guint segNum, GBool imm,
80
+ GBool lossless, Guint length);
81
+ JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h,
82
+ int templ, GBool tpgdOn,
83
+ GBool useSkip, JBIG2Bitmap *skip,
84
+ int *atx, int *aty,
85
+ int mmrDataLength);
86
+ void readGenericRefinementRegionSeg(Guint segNum, GBool imm,
87
+ GBool lossless, Guint length,
88
+ Guint *refSegs,
89
+ Guint nRefSegs);
90
+ JBIG2Bitmap *readGenericRefinementRegion(int w, int h,
91
+ int templ, GBool tpgrOn,
92
+ JBIG2Bitmap *refBitmap,
93
+ int refDX, int refDY,
94
+ int *atx, int *aty);
95
+ void readPageInfoSeg(Guint length);
96
+ void readEndOfStripeSeg(Guint length);
97
+ void readProfilesSeg(Guint length);
98
+ void readCodeTableSeg(Guint segNum, Guint length);
99
+ void readExtensionSeg(Guint length);
100
+ JBIG2Segment *findSegment(Guint segNum);
101
+ void discardSegment(Guint segNum);
102
+ void resetGenericStats(Guint templ,
103
+ JArithmeticDecoderStats *prevStats);
104
+ void resetRefinementStats(Guint templ,
105
+ JArithmeticDecoderStats *prevStats);
106
+ void resetIntStats(int symCodeLen);
107
+ GBool readUByte(Guint *x);
108
+ GBool readByte(int *x);
109
+ GBool readUWord(Guint *x);
110
+ GBool readULong(Guint *x);
111
+ GBool readLong(int *x);
112
+
113
+ Object globalsStream;
114
+ Guint pageW, pageH, curPageH;
115
+ Guint pageDefPixel;
116
+ JBIG2Bitmap *pageBitmap;
117
+ Guint defCombOp;
118
+ GList *segments; // [JBIG2Segment]
119
+ GList *globalSegments; // [JBIG2Segment]
120
+ Stream *curStr;
121
+ Guchar *dataPtr;
122
+ Guchar *dataEnd;
123
+
124
+ JArithmeticDecoder *arithDecoder;
125
+ JArithmeticDecoderStats *genericRegionStats;
126
+ JArithmeticDecoderStats *refinementRegionStats;
127
+ JArithmeticDecoderStats *iadhStats;
128
+ JArithmeticDecoderStats *iadwStats;
129
+ JArithmeticDecoderStats *iaexStats;
130
+ JArithmeticDecoderStats *iaaiStats;
131
+ JArithmeticDecoderStats *iadtStats;
132
+ JArithmeticDecoderStats *iaitStats;
133
+ JArithmeticDecoderStats *iafsStats;
134
+ JArithmeticDecoderStats *iadsStats;
135
+ JArithmeticDecoderStats *iardxStats;
136
+ JArithmeticDecoderStats *iardyStats;
137
+ JArithmeticDecoderStats *iardwStats;
138
+ JArithmeticDecoderStats *iardhStats;
139
+ JArithmeticDecoderStats *iariStats;
140
+ JArithmeticDecoderStats *iaidStats;
141
+ JBIG2HuffmanDecoder *huffDecoder;
142
+ JBIG2MMRDecoder *mmrDecoder;
143
+ };
144
+
145
+ #endif
@@ -0,0 +1,3144 @@
1
+ //========================================================================
2
+ //
3
+ // JPXStream.cc
4
+ //
5
+ // Copyright 2002-2003 Glyph & Cog, LLC
6
+ //
7
+ //========================================================================
8
+
9
+ #include <aconf.h>
10
+
11
+ #ifdef USE_GCC_PRAGMAS
12
+ #pragma implementation
13
+ #endif
14
+
15
+ #include <limits.h>
16
+ #include "gmem.h"
17
+ #include "Error.h"
18
+ #include "JArithmeticDecoder.h"
19
+ #include "JPXStream.h"
20
+
21
+ //~ to do:
22
+ // - precincts
23
+ // - ROI
24
+ // - progression order changes
25
+ // - packed packet headers
26
+ // - support for palettes, channel maps, etc.
27
+ // - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
28
+ // - can we assume that QCC segments must come after the QCD segment?
29
+ // - skip EPH markers (readTilePartData)
30
+ // - handle tilePartToEOC in readTilePartData
31
+ // - deal with multiple codeword segments (readTilePartData,
32
+ // readCodeBlockData)
33
+ // - progression orders 2, 3, and 4
34
+ // - in coefficient decoding (readCodeBlockData):
35
+ // - termination pattern: terminate after every coding pass
36
+ // - error resilience segmentation symbol
37
+ // - selective arithmetic coding bypass
38
+ // - vertically causal context formation
39
+ // - coeffs longer than 31 bits (should just ignore the extra bits?)
40
+ // - handle boxes larger than 2^32 bytes
41
+ // - the fixed-point arithmetic won't handle 16-bit pixels
42
+
43
+ //------------------------------------------------------------------------
44
+
45
+ // number of contexts for the arithmetic decoder
46
+ #define jpxNContexts 19
47
+
48
+ #define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
49
+ #define jpxContextSign 9 // 9 - 13: sign
50
+ #define jpxContextMagRef 14 // 14 -16: magnitude refinement
51
+ #define jpxContextRunLength 17 // cleanup: run length
52
+ #define jpxContextUniform 18 // cleanup: first signif coeff
53
+
54
+ //------------------------------------------------------------------------
55
+
56
+ #define jpxPassSigProp 0
57
+ #define jpxPassMagRef 1
58
+ #define jpxPassCleanup 2
59
+
60
+ //------------------------------------------------------------------------
61
+
62
+ // arithmetic decoder context for the significance propagation and
63
+ // cleanup passes:
64
+ // [horiz][vert][diag][subband]
65
+ // where subband = 0 for HL
66
+ // = 1 for LH and LL
67
+ // = 2 for HH
68
+ static Guint sigPropContext[3][3][5][3] = {
69
+ {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
70
+ { 1, 1, 3 }, // horiz=0, vert=0, diag=1
71
+ { 2, 2, 6 }, // horiz=0, vert=0, diag=2
72
+ { 2, 2, 8 }, // horiz=0, vert=0, diag=3
73
+ { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
74
+ {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
75
+ { 6, 3, 4 }, // horiz=0, vert=1, diag=1
76
+ { 6, 3, 7 }, // horiz=0, vert=1, diag=2
77
+ { 6, 3, 8 }, // horiz=0, vert=1, diag=3
78
+ { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
79
+ {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
80
+ { 8, 4, 5 }, // horiz=0, vert=2, diag=1
81
+ { 8, 4, 7 }, // horiz=0, vert=2, diag=2
82
+ { 8, 4, 8 }, // horiz=0, vert=2, diag=3
83
+ { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
84
+ {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
85
+ { 3, 6, 4 }, // horiz=1, vert=0, diag=1
86
+ { 3, 6, 7 }, // horiz=1, vert=0, diag=2
87
+ { 3, 6, 8 }, // horiz=1, vert=0, diag=3
88
+ { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
89
+ {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
90
+ { 7, 7, 5 }, // horiz=1, vert=1, diag=1
91
+ { 7, 7, 7 }, // horiz=1, vert=1, diag=2
92
+ { 7, 7, 8 }, // horiz=1, vert=1, diag=3
93
+ { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
94
+ {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
95
+ { 8, 7, 5 }, // horiz=1, vert=2, diag=1
96
+ { 8, 7, 7 }, // horiz=1, vert=2, diag=2
97
+ { 8, 7, 8 }, // horiz=1, vert=2, diag=3
98
+ { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
99
+ {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
100
+ { 4, 8, 5 }, // horiz=2, vert=0, diag=1
101
+ { 4, 8, 7 }, // horiz=2, vert=0, diag=2
102
+ { 4, 8, 8 }, // horiz=2, vert=0, diag=3
103
+ { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
104
+ {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
105
+ { 7, 8, 5 }, // horiz=2, vert=1, diag=1
106
+ { 7, 8, 7 }, // horiz=2, vert=1, diag=2
107
+ { 7, 8, 8 }, // horiz=2, vert=1, diag=3
108
+ { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
109
+ {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
110
+ { 8, 8, 5 }, // horiz=2, vert=2, diag=1
111
+ { 8, 8, 7 }, // horiz=2, vert=2, diag=2
112
+ { 8, 8, 8 }, // horiz=2, vert=2, diag=3
113
+ { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
114
+ };
115
+
116
+ // arithmetic decoder context and xor bit for the sign bit in the
117
+ // significance propagation pass:
118
+ // [horiz][vert][k]
119
+ // where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
120
+ // and k = 0 for the context
121
+ // = 1 for the xor bit
122
+ static Guint signContext[5][5][2] = {
123
+ {{ 13, 1 }, // horiz=-2, vert=-2
124
+ { 13, 1 }, // horiz=-2, vert=-1
125
+ { 12, 1 }, // horiz=-2, vert= 0
126
+ { 11, 1 }, // horiz=-2, vert=+1
127
+ { 11, 1 }}, // horiz=-2, vert=+2
128
+ {{ 13, 1 }, // horiz=-1, vert=-2
129
+ { 13, 1 }, // horiz=-1, vert=-1
130
+ { 12, 1 }, // horiz=-1, vert= 0
131
+ { 11, 1 }, // horiz=-1, vert=+1
132
+ { 11, 1 }}, // horiz=-1, vert=+2
133
+ {{ 10, 1 }, // horiz= 0, vert=-2
134
+ { 10, 1 }, // horiz= 0, vert=-1
135
+ { 9, 0 }, // horiz= 0, vert= 0
136
+ { 10, 0 }, // horiz= 0, vert=+1
137
+ { 10, 0 }}, // horiz= 0, vert=+2
138
+ {{ 11, 0 }, // horiz=+1, vert=-2
139
+ { 11, 0 }, // horiz=+1, vert=-1
140
+ { 12, 0 }, // horiz=+1, vert= 0
141
+ { 13, 0 }, // horiz=+1, vert=+1
142
+ { 13, 0 }}, // horiz=+1, vert=+2
143
+ {{ 11, 0 }, // horiz=+2, vert=-2
144
+ { 11, 0 }, // horiz=+2, vert=-1
145
+ { 12, 0 }, // horiz=+2, vert= 0
146
+ { 13, 0 }, // horiz=+2, vert=+1
147
+ { 13, 0 }}, // horiz=+2, vert=+2
148
+ };
149
+
150
+ //------------------------------------------------------------------------
151
+
152
+ // constants used in the IDWT
153
+ #define idwtAlpha -1.586134342059924
154
+ #define idwtBeta -0.052980118572961
155
+ #define idwtGamma 0.882911075530934
156
+ #define idwtDelta 0.443506852043971
157
+ #define idwtKappa 1.230174104914001
158
+ #define idwtIKappa (1.0 / idwtKappa)
159
+
160
+ // number of bits to the right of the decimal point for the fixed
161
+ // point arithmetic used in the IDWT
162
+ #define fracBits 16
163
+
164
+ //------------------------------------------------------------------------
165
+
166
+ // floor(x / y)
167
+ #define jpxFloorDiv(x, y) ((x) / (y))
168
+
169
+ // floor(x / 2^y)
170
+ #define jpxFloorDivPow2(x, y) ((x) >> (y))
171
+
172
+ // ceil(x / y)
173
+ #define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
174
+
175
+ // ceil(x / 2^y)
176
+ #define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
177
+
178
+ //------------------------------------------------------------------------
179
+
180
+ #if 1 //----- disable coverage tracking
181
+
182
+ #define cover(idx)
183
+
184
+ #else //----- enable coverage tracking
185
+
186
+ class JPXCover {
187
+ public:
188
+
189
+ JPXCover(int sizeA);
190
+ ~JPXCover();
191
+ void incr(int idx);
192
+
193
+ private:
194
+
195
+ int size, used;
196
+ int *data;
197
+ };
198
+
199
+ JPXCover::JPXCover(int sizeA) {
200
+ size = sizeA;
201
+ used = -1;
202
+ data = (int *)gmallocn(size, sizeof(int));
203
+ memset(data, 0, size * sizeof(int));
204
+ }
205
+
206
+ JPXCover::~JPXCover() {
207
+ int i;
208
+
209
+ printf("JPX coverage:\n");
210
+ for (i = 0; i <= used; ++i) {
211
+ printf(" %4d: %8d\n", i, data[i]);
212
+ }
213
+ gfree(data);
214
+ }
215
+
216
+ void JPXCover::incr(int idx) {
217
+ if (idx < size) {
218
+ ++data[idx];
219
+ if (idx > used) {
220
+ used = idx;
221
+ }
222
+ }
223
+ }
224
+
225
+ JPXCover jpxCover(150);
226
+
227
+ #define cover(idx) jpxCover.incr(idx)
228
+
229
+ #endif //----- coverage tracking
230
+
231
+ //------------------------------------------------------------------------
232
+
233
+ JPXStream::JPXStream(Stream *strA):
234
+ FilterStream(strA)
235
+ {
236
+ nComps = 0;
237
+ bpc = NULL;
238
+ width = height = 0;
239
+ haveCS = gFalse;
240
+ havePalette = gFalse;
241
+ haveCompMap = gFalse;
242
+ haveChannelDefn = gFalse;
243
+
244
+ img.tiles = NULL;
245
+ bitBuf = 0;
246
+ bitBufLen = 0;
247
+ bitBufSkip = gFalse;
248
+ byteCount = 0;
249
+ }
250
+
251
+ JPXStream::~JPXStream() {
252
+ close();
253
+ delete str;
254
+ }
255
+
256
+ void JPXStream::reset() {
257
+ str->reset();
258
+ if (readBoxes()) {
259
+ curY = img.yOffset;
260
+ } else {
261
+ // readBoxes reported an error, so we go immediately to EOF
262
+ curY = img.ySize;
263
+ }
264
+ curX = img.xOffset;
265
+ curComp = 0;
266
+ readBufLen = 0;
267
+ }
268
+
269
+ void JPXStream::close() {
270
+ JPXTile *tile;
271
+ JPXTileComp *tileComp;
272
+ JPXResLevel *resLevel;
273
+ JPXPrecinct *precinct;
274
+ JPXSubband *subband;
275
+ JPXCodeBlock *cb;
276
+ Guint comp, i, k, r, pre, sb;
277
+
278
+ gfree(bpc);
279
+ bpc = NULL;
280
+ if (havePalette) {
281
+ gfree(palette.bpc);
282
+ gfree(palette.c);
283
+ havePalette = gFalse;
284
+ }
285
+ if (haveCompMap) {
286
+ gfree(compMap.comp);
287
+ gfree(compMap.type);
288
+ gfree(compMap.pComp);
289
+ haveCompMap = gFalse;
290
+ }
291
+ if (haveChannelDefn) {
292
+ gfree(channelDefn.idx);
293
+ gfree(channelDefn.type);
294
+ gfree(channelDefn.assoc);
295
+ haveChannelDefn = gFalse;
296
+ }
297
+
298
+ if (img.tiles) {
299
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
300
+ tile = &img.tiles[i];
301
+ if (tile->tileComps) {
302
+ for (comp = 0; comp < img.nComps; ++comp) {
303
+ tileComp = &tile->tileComps[comp];
304
+ gfree(tileComp->quantSteps);
305
+ gfree(tileComp->data);
306
+ gfree(tileComp->buf);
307
+ if (tileComp->resLevels) {
308
+ for (r = 0; r <= tileComp->nDecompLevels; ++r) {
309
+ resLevel = &tileComp->resLevels[r];
310
+ if (resLevel->precincts) {
311
+ for (pre = 0; pre < 1; ++pre) {
312
+ precinct = &resLevel->precincts[pre];
313
+ if (precinct->subbands) {
314
+ for (sb = 0; sb < (Guint)(r == 0 ? 1 : 3); ++sb) {
315
+ subband = &precinct->subbands[sb];
316
+ gfree(subband->inclusion);
317
+ gfree(subband->zeroBitPlane);
318
+ if (subband->cbs) {
319
+ for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
320
+ cb = &subband->cbs[k];
321
+ gfree(cb->coeffs);
322
+ if (cb->arithDecoder) {
323
+ delete cb->arithDecoder;
324
+ }
325
+ if (cb->stats) {
326
+ delete cb->stats;
327
+ }
328
+ }
329
+ gfree(subband->cbs);
330
+ }
331
+ }
332
+ gfree(precinct->subbands);
333
+ }
334
+ }
335
+ gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
336
+ }
337
+ }
338
+ gfree(img.tiles[i].tileComps[comp].resLevels);
339
+ }
340
+ }
341
+ gfree(img.tiles[i].tileComps);
342
+ }
343
+ }
344
+ gfree(img.tiles);
345
+ img.tiles = NULL;
346
+ }
347
+ FilterStream::close();
348
+ }
349
+
350
+ int JPXStream::getChar() {
351
+ int c;
352
+
353
+ if (readBufLen < 8) {
354
+ fillReadBuf();
355
+ }
356
+ if (readBufLen == 8) {
357
+ c = readBuf & 0xff;
358
+ readBufLen = 0;
359
+ } else if (readBufLen > 8) {
360
+ c = (readBuf >> (readBufLen - 8)) & 0xff;
361
+ readBufLen -= 8;
362
+ } else if (readBufLen == 0) {
363
+ c = EOF;
364
+ } else {
365
+ c = (readBuf << (8 - readBufLen)) & 0xff;
366
+ readBufLen = 0;
367
+ }
368
+ return c;
369
+ }
370
+
371
+ int JPXStream::lookChar() {
372
+ int c;
373
+
374
+ if (readBufLen < 8) {
375
+ fillReadBuf();
376
+ }
377
+ if (readBufLen == 8) {
378
+ c = readBuf & 0xff;
379
+ } else if (readBufLen > 8) {
380
+ c = (readBuf >> (readBufLen - 8)) & 0xff;
381
+ } else if (readBufLen == 0) {
382
+ c = EOF;
383
+ } else {
384
+ c = (readBuf << (8 - readBufLen)) & 0xff;
385
+ }
386
+ return c;
387
+ }
388
+
389
+ void JPXStream::fillReadBuf() {
390
+ JPXTileComp *tileComp;
391
+ Guint tileIdx, tx, ty;
392
+ int pix, pixBits;
393
+
394
+ do {
395
+ if (curY >= img.ySize) {
396
+ return;
397
+ }
398
+ tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles
399
+ + (curX - img.xTileOffset) / img.xTileSize;
400
+ #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
401
+ tileComp = &img.tiles[tileIdx].tileComps[curComp];
402
+ #else
403
+ tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
404
+ #endif
405
+ tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
406
+ ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
407
+ pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
408
+ pixBits = tileComp->prec;
409
+ #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
410
+ if (++curComp == img.nComps) {
411
+ #else
412
+ if (havePalette) {
413
+ if (pix >= 0 && pix < palette.nEntries) {
414
+ pix = palette.c[pix * palette.nComps + curComp];
415
+ } else {
416
+ pix =
417
+ pixBits = palette.bpc[curComp];
418
+ }
419
+ if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
420
+ #endif
421
+ curComp = 0;
422
+ if (++curX == img.xSize) {
423
+ curX = img.xOffset;
424
+ ++curY;
425
+ }
426
+ }
427
+ if (pixBits == 8) {
428
+ readBuf = (readBuf << 8) | (pix & 0xff);
429
+ } else {
430
+ readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
431
+ }
432
+ readBufLen += pixBits;
433
+ } while (readBufLen < 8);
434
+ }
435
+
436
+ GString *JPXStream::getPSFilter(int psLevel, char *indent) {
437
+ return NULL;
438
+ }
439
+
440
+ GBool JPXStream::isBinary(GBool last) {
441
+ return str->isBinary(gTrue);
442
+ }
443
+
444
+ void JPXStream::getImageParams(int *bitsPerComponent,
445
+ StreamColorSpaceMode *csMode) {
446
+ Guint boxType, boxLen, dataLen, csEnum;
447
+ Guint bpc1, dummy, i;
448
+ int csMeth, csPrec, csPrec1, dummy2;
449
+ StreamColorSpaceMode csMode1;
450
+ GBool haveBPC, haveCSMode;
451
+
452
+ csPrec = 0; // make gcc happy
453
+ haveBPC = haveCSMode = gFalse;
454
+ str->reset();
455
+ if (str->lookChar() == 0xff) {
456
+ getImageParams2(bitsPerComponent, csMode);
457
+ } else {
458
+ while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
459
+ if (boxType == 0x6a703268) { // JP2 header
460
+ cover(0);
461
+ // skip the superbox
462
+ } else if (boxType == 0x69686472) { // image header
463
+ cover(1);
464
+ if (readULong(&dummy) &&
465
+ readULong(&dummy) &&
466
+ readUWord(&dummy) &&
467
+ readUByte(&bpc1) &&
468
+ readUByte(&dummy) &&
469
+ readUByte(&dummy) &&
470
+ readUByte(&dummy)) {
471
+ *bitsPerComponent = bpc1 + 1;
472
+ haveBPC = gTrue;
473
+ }
474
+ } else if (boxType == 0x636F6C72) { // color specification
475
+ cover(2);
476
+ if (readByte(&csMeth) &&
477
+ readByte(&csPrec1) &&
478
+ readByte(&dummy2)) {
479
+ if (csMeth == 1) {
480
+ if (readULong(&csEnum)) {
481
+ csMode1 = streamCSNone;
482
+ if (csEnum == jpxCSBiLevel ||
483
+ csEnum == jpxCSGrayscale) {
484
+ csMode1 = streamCSDeviceGray;
485
+ } else if (csEnum == jpxCSCMYK) {
486
+ csMode1 = streamCSDeviceCMYK;
487
+ } else if (csEnum == jpxCSsRGB ||
488
+ csEnum == jpxCSCISesRGB ||
489
+ csEnum == jpxCSROMMRGB) {
490
+ csMode1 = streamCSDeviceRGB;
491
+ }
492
+ if (csMode1 != streamCSNone &&
493
+ (!haveCSMode || csPrec1 > csPrec)) {
494
+ *csMode = csMode1;
495
+ csPrec = csPrec1;
496
+ haveCSMode = gTrue;
497
+ }
498
+ for (i = 0; i < dataLen - 7; ++i) {
499
+ str->getChar();
500
+ }
501
+ }
502
+ } else {
503
+ for (i = 0; i < dataLen - 3; ++i) {
504
+ str->getChar();
505
+ }
506
+ }
507
+ }
508
+ } else if (boxType == 0x6A703263) { // codestream
509
+ cover(3);
510
+ if (!(haveBPC && haveCSMode)) {
511
+ getImageParams2(bitsPerComponent, csMode);
512
+ }
513
+ break;
514
+ } else {
515
+ cover(4);
516
+ for (i = 0; i < dataLen; ++i) {
517
+ str->getChar();
518
+ }
519
+ }
520
+ }
521
+ }
522
+ str->close();
523
+ }
524
+
525
+ // Get image parameters from the codestream.
526
+ void JPXStream::getImageParams2(int *bitsPerComponent,
527
+ StreamColorSpaceMode *csMode) {
528
+ int segType;
529
+ Guint segLen, nComps1, bpc1, dummy, i;
530
+
531
+ while (readMarkerHdr(&segType, &segLen)) {
532
+ if (segType == 0x51) { // SIZ - image and tile size
533
+ cover(5);
534
+ if (readUWord(&dummy) &&
535
+ readULong(&dummy) &&
536
+ readULong(&dummy) &&
537
+ readULong(&dummy) &&
538
+ readULong(&dummy) &&
539
+ readULong(&dummy) &&
540
+ readULong(&dummy) &&
541
+ readULong(&dummy) &&
542
+ readULong(&dummy) &&
543
+ readUWord(&nComps1) &&
544
+ readUByte(&bpc1)) {
545
+ *bitsPerComponent = (bpc1 & 0x7f) + 1;
546
+ // if there's no color space info, take a guess
547
+ if (nComps1 == 1) {
548
+ *csMode = streamCSDeviceGray;
549
+ } else if (nComps1 == 3) {
550
+ *csMode = streamCSDeviceRGB;
551
+ } else if (nComps1 == 4) {
552
+ *csMode = streamCSDeviceCMYK;
553
+ }
554
+ }
555
+ break;
556
+ } else {
557
+ cover(6);
558
+ if (segLen > 2) {
559
+ for (i = 0; i < segLen - 2; ++i) {
560
+ str->getChar();
561
+ }
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ GBool JPXStream::readBoxes() {
568
+ Guint boxType, boxLen, dataLen;
569
+ Guint bpc1, compression, unknownColorspace, ipr;
570
+ Guint i, j;
571
+
572
+ haveImgHdr = gFalse;
573
+
574
+ // check for a naked JPEG 2000 codestream (without the JP2/JPX
575
+ // wrapper) -- this appears to be a violation of the PDF spec, but
576
+ // Acrobat allows it
577
+ if (str->lookChar() == 0xff) {
578
+ cover(7);
579
+ error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
580
+ readCodestream(0);
581
+ nComps = img.nComps;
582
+ bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
583
+ for (i = 0; i < nComps; ++i) {
584
+ bpc[i] = img.tiles[0].tileComps[i].prec;
585
+ }
586
+ width = img.xSize - img.xOffset;
587
+ height = img.ySize - img.yOffset;
588
+ return gTrue;
589
+ }
590
+
591
+ while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
592
+ switch (boxType) {
593
+ case 0x6a703268: // JP2 header
594
+ // this is a grouping box ('superbox') which has no real
595
+ // contents and doesn't appear to be used consistently, i.e.,
596
+ // some things which should be subboxes of the JP2 header box
597
+ // show up outside of it - so we simply ignore the JP2 header
598
+ // box
599
+ cover(8);
600
+ break;
601
+ case 0x69686472: // image header
602
+ cover(9);
603
+ if (!readULong(&height) ||
604
+ !readULong(&width) ||
605
+ !readUWord(&nComps) ||
606
+ !readUByte(&bpc1) ||
607
+ !readUByte(&compression) ||
608
+ !readUByte(&unknownColorspace) ||
609
+ !readUByte(&ipr)) {
610
+ error(getPos(), "Unexpected EOF in JPX stream");
611
+ return gFalse;
612
+ }
613
+ if (compression != 7) {
614
+ error(getPos(), "Unknown compression type in JPX stream");
615
+ return gFalse;
616
+ }
617
+ bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
618
+ for (i = 0; i < nComps; ++i) {
619
+ bpc[i] = bpc1;
620
+ }
621
+ haveImgHdr = gTrue;
622
+ break;
623
+ case 0x62706363: // bits per component
624
+ cover(10);
625
+ if (!haveImgHdr) {
626
+ error(getPos(), "Found bits per component box before image header box in JPX stream");
627
+ return gFalse;
628
+ }
629
+ if (dataLen != nComps) {
630
+ error(getPos(), "Invalid bits per component box in JPX stream");
631
+ return gFalse;
632
+ }
633
+ for (i = 0; i < nComps; ++i) {
634
+ if (!readUByte(&bpc[i])) {
635
+ error(getPos(), "Unexpected EOF in JPX stream");
636
+ return gFalse;
637
+ }
638
+ }
639
+ break;
640
+ case 0x636F6C72: // color specification
641
+ cover(11);
642
+ if (!readColorSpecBox(dataLen)) {
643
+ return gFalse;
644
+ }
645
+ break;
646
+ case 0x70636c72: // palette
647
+ cover(12);
648
+ if (!readUWord(&palette.nEntries) ||
649
+ !readUByte(&palette.nComps)) {
650
+ error(getPos(), "Unexpected EOF in JPX stream");
651
+ return gFalse;
652
+ }
653
+ palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint));
654
+ palette.c =
655
+ (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int));
656
+ for (i = 0; i < palette.nComps; ++i) {
657
+ if (!readUByte(&palette.bpc[i])) {
658
+ error(getPos(), "Unexpected EOF in JPX stream");
659
+ return gFalse;
660
+ }
661
+ ++palette.bpc[i];
662
+ }
663
+ for (i = 0; i < palette.nEntries; ++i) {
664
+ for (j = 0; j < palette.nComps; ++j) {
665
+ if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
666
+ (palette.bpc[j] & 0x80) ? gTrue : gFalse,
667
+ &palette.c[i * palette.nComps + j])) {
668
+ error(getPos(), "Unexpected EOF in JPX stream");
669
+ return gFalse;
670
+ }
671
+ }
672
+ }
673
+ havePalette = gTrue;
674
+ break;
675
+ case 0x636d6170: // component mapping
676
+ cover(13);
677
+ compMap.nChannels = dataLen / 4;
678
+ compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
679
+ compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
680
+ compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
681
+ for (i = 0; i < compMap.nChannels; ++i) {
682
+ if (!readUWord(&compMap.comp[i]) ||
683
+ !readUByte(&compMap.type[i]) ||
684
+ !readUByte(&compMap.pComp[i])) {
685
+ error(getPos(), "Unexpected EOF in JPX stream");
686
+ return gFalse;
687
+ }
688
+ }
689
+ haveCompMap = gTrue;
690
+ break;
691
+ case 0x63646566: // channel definition
692
+ cover(14);
693
+ if (!readUWord(&channelDefn.nChannels)) {
694
+ error(getPos(), "Unexpected EOF in JPX stream");
695
+ return gFalse;
696
+ }
697
+ channelDefn.idx =
698
+ (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
699
+ channelDefn.type =
700
+ (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
701
+ channelDefn.assoc =
702
+ (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
703
+ for (i = 0; i < channelDefn.nChannels; ++i) {
704
+ if (!readUWord(&channelDefn.idx[i]) ||
705
+ !readUWord(&channelDefn.type[i]) ||
706
+ !readUWord(&channelDefn.assoc[i])) {
707
+ error(getPos(), "Unexpected EOF in JPX stream");
708
+ return gFalse;
709
+ }
710
+ }
711
+ haveChannelDefn = gTrue;
712
+ break;
713
+ case 0x6A703263: // contiguous codestream
714
+ cover(15);
715
+ if (!bpc) {
716
+ error(getPos(), "JPX stream is missing the image header box");
717
+ }
718
+ if (!haveCS) {
719
+ error(getPos(), "JPX stream has no supported color spec");
720
+ }
721
+ if (!readCodestream(dataLen)) {
722
+ return gFalse;
723
+ }
724
+ break;
725
+ default:
726
+ cover(16);
727
+ for (i = 0; i < dataLen; ++i) {
728
+ if (str->getChar() == EOF) {
729
+ error(getPos(), "Unexpected EOF in JPX stream");
730
+ return gFalse;
731
+ }
732
+ }
733
+ break;
734
+ }
735
+ }
736
+ return gTrue;
737
+ }
738
+
739
+ GBool JPXStream::readColorSpecBox(Guint dataLen) {
740
+ JPXColorSpec newCS;
741
+ Guint csApprox, csEnum;
742
+ Guint i;
743
+ GBool ok;
744
+
745
+ ok = gFalse;
746
+ if (!readUByte(&newCS.meth) ||
747
+ !readByte(&newCS.prec) ||
748
+ !readUByte(&csApprox)) {
749
+ goto err;
750
+ }
751
+ switch (newCS.meth) {
752
+ case 1: // enumerated colorspace
753
+ cover(17);
754
+ if (!readULong(&csEnum)) {
755
+ goto err;
756
+ }
757
+ newCS.enumerated.type = (JPXColorSpaceType)csEnum;
758
+ switch (newCS.enumerated.type) {
759
+ case jpxCSBiLevel:
760
+ ok = gTrue;
761
+ break;
762
+ case jpxCSYCbCr1:
763
+ ok = gTrue;
764
+ break;
765
+ case jpxCSYCbCr2:
766
+ ok = gTrue;
767
+ break;
768
+ case jpxCSYCBCr3:
769
+ ok = gTrue;
770
+ break;
771
+ case jpxCSPhotoYCC:
772
+ ok = gTrue;
773
+ break;
774
+ case jpxCSCMY:
775
+ ok = gTrue;
776
+ break;
777
+ case jpxCSCMYK:
778
+ ok = gTrue;
779
+ break;
780
+ case jpxCSYCCK:
781
+ ok = gTrue;
782
+ break;
783
+ case jpxCSCIELab:
784
+ if (dataLen == 7 + 7*4) {
785
+ if (!readULong(&newCS.enumerated.cieLab.rl) ||
786
+ !readULong(&newCS.enumerated.cieLab.ol) ||
787
+ !readULong(&newCS.enumerated.cieLab.ra) ||
788
+ !readULong(&newCS.enumerated.cieLab.oa) ||
789
+ !readULong(&newCS.enumerated.cieLab.rb) ||
790
+ !readULong(&newCS.enumerated.cieLab.ob) ||
791
+ !readULong(&newCS.enumerated.cieLab.il)) {
792
+ goto err;
793
+ }
794
+ } else if (dataLen == 7) {
795
+ //~ this assumes the 8-bit case
796
+ cover(92);
797
+ newCS.enumerated.cieLab.rl = 100;
798
+ newCS.enumerated.cieLab.ol = 0;
799
+ newCS.enumerated.cieLab.ra = 255;
800
+ newCS.enumerated.cieLab.oa = 128;
801
+ newCS.enumerated.cieLab.rb = 255;
802
+ newCS.enumerated.cieLab.ob = 96;
803
+ newCS.enumerated.cieLab.il = 0x00443530;
804
+ } else {
805
+ goto err;
806
+ }
807
+ ok = gTrue;
808
+ break;
809
+ case jpxCSsRGB:
810
+ ok = gTrue;
811
+ break;
812
+ case jpxCSGrayscale:
813
+ ok = gTrue;
814
+ break;
815
+ case jpxCSBiLevel2:
816
+ ok = gTrue;
817
+ break;
818
+ case jpxCSCIEJab:
819
+ // not allowed in PDF
820
+ goto err;
821
+ case jpxCSCISesRGB:
822
+ ok = gTrue;
823
+ break;
824
+ case jpxCSROMMRGB:
825
+ ok = gTrue;
826
+ break;
827
+ case jpxCSsRGBYCbCr:
828
+ ok = gTrue;
829
+ break;
830
+ case jpxCSYPbPr1125:
831
+ ok = gTrue;
832
+ break;
833
+ case jpxCSYPbPr1250:
834
+ ok = gTrue;
835
+ break;
836
+ default:
837
+ goto err;
838
+ }
839
+ break;
840
+ case 2: // restricted ICC profile
841
+ case 3: // any ICC profile (JPX)
842
+ case 4: // vendor color (JPX)
843
+ cover(18);
844
+ for (i = 0; i < dataLen - 3; ++i) {
845
+ if (str->getChar() == EOF) {
846
+ goto err;
847
+ }
848
+ }
849
+ break;
850
+ }
851
+
852
+ if (ok && (!haveCS || newCS.prec > cs.prec)) {
853
+ cs = newCS;
854
+ haveCS = gTrue;
855
+ }
856
+
857
+ return gTrue;
858
+
859
+ err:
860
+ error(getPos(), "Error in JPX color spec");
861
+ return gFalse;
862
+ }
863
+
864
+ GBool JPXStream::readCodestream(Guint len) {
865
+ JPXTile *tile;
866
+ JPXTileComp *tileComp;
867
+ int segType;
868
+ GBool haveSIZ, haveCOD, haveQCD, haveSOT;
869
+ Guint precinctSize, style;
870
+ Guint segLen, capabilities, comp, i, j, r;
871
+
872
+ //----- main header
873
+ haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
874
+ do {
875
+ if (!readMarkerHdr(&segType, &segLen)) {
876
+ error(getPos(), "Error in JPX codestream");
877
+ return gFalse;
878
+ }
879
+ switch (segType) {
880
+ case 0x4f: // SOC - start of codestream
881
+ // marker only
882
+ cover(19);
883
+ break;
884
+ case 0x51: // SIZ - image and tile size
885
+ cover(20);
886
+ if (!readUWord(&capabilities) ||
887
+ !readULong(&img.xSize) ||
888
+ !readULong(&img.ySize) ||
889
+ !readULong(&img.xOffset) ||
890
+ !readULong(&img.yOffset) ||
891
+ !readULong(&img.xTileSize) ||
892
+ !readULong(&img.yTileSize) ||
893
+ !readULong(&img.xTileOffset) ||
894
+ !readULong(&img.yTileOffset) ||
895
+ !readUWord(&img.nComps)) {
896
+ error(getPos(), "Error in JPX SIZ marker segment");
897
+ return gFalse;
898
+ }
899
+ if (haveImgHdr && img.nComps != nComps) {
900
+ error(getPos(), "Different number of components in JPX SIZ marker segment");
901
+ return gFalse;
902
+ }
903
+ img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
904
+ / img.xTileSize;
905
+ img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
906
+ / img.yTileSize;
907
+ // check for overflow before allocating memory
908
+ if (img.nXTiles <= 0 || img.nYTiles <= 0 ||
909
+ img.nXTiles >= INT_MAX / img.nYTiles) {
910
+ error(getPos(), "Bad tile count in JPX SIZ marker segment");
911
+ return gFalse;
912
+ }
913
+ img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles,
914
+ sizeof(JPXTile));
915
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
916
+ img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
917
+ sizeof(JPXTileComp));
918
+ for (comp = 0; comp < img.nComps; ++comp) {
919
+ img.tiles[i].tileComps[comp].quantSteps = NULL;
920
+ img.tiles[i].tileComps[comp].data = NULL;
921
+ img.tiles[i].tileComps[comp].buf = NULL;
922
+ img.tiles[i].tileComps[comp].resLevels = NULL;
923
+ }
924
+ }
925
+ for (comp = 0; comp < img.nComps; ++comp) {
926
+ if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
927
+ !readUByte(&img.tiles[0].tileComps[comp].hSep) ||
928
+ !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
929
+ error(getPos(), "Error in JPX SIZ marker segment");
930
+ return gFalse;
931
+ }
932
+ img.tiles[0].tileComps[comp].sgned =
933
+ (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse;
934
+ img.tiles[0].tileComps[comp].prec =
935
+ (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
936
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
937
+ img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
938
+ }
939
+ }
940
+ haveSIZ = gTrue;
941
+ break;
942
+ case 0x52: // COD - coding style default
943
+ cover(21);
944
+ if (!readUByte(&img.tiles[0].tileComps[0].style) ||
945
+ !readUByte(&img.tiles[0].progOrder) ||
946
+ !readUWord(&img.tiles[0].nLayers) ||
947
+ !readUByte(&img.tiles[0].multiComp) ||
948
+ !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) ||
949
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockW) ||
950
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
951
+ !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
952
+ !readUByte(&img.tiles[0].tileComps[0].transform)) {
953
+ error(getPos(), "Error in JPX COD marker segment");
954
+ return gFalse;
955
+ }
956
+ img.tiles[0].tileComps[0].codeBlockW += 2;
957
+ img.tiles[0].tileComps[0].codeBlockH += 2;
958
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
959
+ if (i != 0) {
960
+ img.tiles[i].progOrder = img.tiles[0].progOrder;
961
+ img.tiles[i].nLayers = img.tiles[0].nLayers;
962
+ img.tiles[i].multiComp = img.tiles[0].multiComp;
963
+ }
964
+ for (comp = 0; comp < img.nComps; ++comp) {
965
+ if (!(i == 0 && comp == 0)) {
966
+ img.tiles[i].tileComps[comp].style =
967
+ img.tiles[0].tileComps[0].style;
968
+ img.tiles[i].tileComps[comp].nDecompLevels =
969
+ img.tiles[0].tileComps[0].nDecompLevels;
970
+ img.tiles[i].tileComps[comp].codeBlockW =
971
+ img.tiles[0].tileComps[0].codeBlockW;
972
+ img.tiles[i].tileComps[comp].codeBlockH =
973
+ img.tiles[0].tileComps[0].codeBlockH;
974
+ img.tiles[i].tileComps[comp].codeBlockStyle =
975
+ img.tiles[0].tileComps[0].codeBlockStyle;
976
+ img.tiles[i].tileComps[comp].transform =
977
+ img.tiles[0].tileComps[0].transform;
978
+ }
979
+ img.tiles[i].tileComps[comp].resLevels =
980
+ (JPXResLevel *)gmallocn(
981
+ (img.tiles[i].tileComps[comp].nDecompLevels + 1),
982
+ sizeof(JPXResLevel));
983
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
984
+ img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
985
+ }
986
+ }
987
+ }
988
+ for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
989
+ if (img.tiles[0].tileComps[0].style & 0x01) {
990
+ cover(91);
991
+ if (!readUByte(&precinctSize)) {
992
+ error(getPos(), "Error in JPX COD marker segment");
993
+ return gFalse;
994
+ }
995
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
996
+ precinctSize & 0x0f;
997
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
998
+ (precinctSize >> 4) & 0x0f;
999
+ } else {
1000
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
1001
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
1002
+ }
1003
+ }
1004
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1005
+ for (comp = 0; comp < img.nComps; ++comp) {
1006
+ if (!(i == 0 && comp == 0)) {
1007
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1008
+ img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
1009
+ img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
1010
+ img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
1011
+ img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
1012
+ }
1013
+ }
1014
+ }
1015
+ }
1016
+ haveCOD = gTrue;
1017
+ break;
1018
+ case 0x53: // COC - coding style component
1019
+ cover(22);
1020
+ if (!haveCOD) {
1021
+ error(getPos(), "JPX COC marker segment before COD segment");
1022
+ return gFalse;
1023
+ }
1024
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1025
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1026
+ comp >= img.nComps ||
1027
+ !readUByte(&style) ||
1028
+ !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) ||
1029
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) ||
1030
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
1031
+ !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
1032
+ !readUByte(&img.tiles[0].tileComps[comp].transform)) {
1033
+ error(getPos(), "Error in JPX COC marker segment");
1034
+ return gFalse;
1035
+ }
1036
+ img.tiles[0].tileComps[comp].style =
1037
+ (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
1038
+ img.tiles[0].tileComps[comp].codeBlockW += 2;
1039
+ img.tiles[0].tileComps[comp].codeBlockH += 2;
1040
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1041
+ if (i != 0) {
1042
+ img.tiles[i].tileComps[comp].style =
1043
+ img.tiles[0].tileComps[comp].style;
1044
+ img.tiles[i].tileComps[comp].nDecompLevels =
1045
+ img.tiles[0].tileComps[comp].nDecompLevels;
1046
+ img.tiles[i].tileComps[comp].codeBlockW =
1047
+ img.tiles[0].tileComps[comp].codeBlockW;
1048
+ img.tiles[i].tileComps[comp].codeBlockH =
1049
+ img.tiles[0].tileComps[comp].codeBlockH;
1050
+ img.tiles[i].tileComps[comp].codeBlockStyle =
1051
+ img.tiles[0].tileComps[comp].codeBlockStyle;
1052
+ img.tiles[i].tileComps[comp].transform =
1053
+ img.tiles[0].tileComps[comp].transform;
1054
+ }
1055
+ img.tiles[i].tileComps[comp].resLevels =
1056
+ (JPXResLevel *)greallocn(
1057
+ img.tiles[i].tileComps[comp].resLevels,
1058
+ (img.tiles[i].tileComps[comp].nDecompLevels + 1),
1059
+ sizeof(JPXResLevel));
1060
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1061
+ img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
1062
+ }
1063
+ }
1064
+ for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
1065
+ if (img.tiles[0].tileComps[comp].style & 0x01) {
1066
+ if (!readUByte(&precinctSize)) {
1067
+ error(getPos(), "Error in JPX COD marker segment");
1068
+ return gFalse;
1069
+ }
1070
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
1071
+ precinctSize & 0x0f;
1072
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
1073
+ (precinctSize >> 4) & 0x0f;
1074
+ } else {
1075
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
1076
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
1077
+ }
1078
+ }
1079
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
1080
+ for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1081
+ img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
1082
+ img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
1083
+ img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
1084
+ img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
1085
+ }
1086
+ }
1087
+ break;
1088
+ case 0x5c: // QCD - quantization default
1089
+ cover(23);
1090
+ if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
1091
+ error(getPos(), "Error in JPX QCD marker segment");
1092
+ return gFalse;
1093
+ }
1094
+ if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
1095
+ img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
1096
+ img.tiles[0].tileComps[0].quantSteps =
1097
+ (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1098
+ img.tiles[0].tileComps[0].nQuantSteps,
1099
+ sizeof(Guint));
1100
+ for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1101
+ if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
1102
+ error(getPos(), "Error in JPX QCD marker segment");
1103
+ return gFalse;
1104
+ }
1105
+ }
1106
+ } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
1107
+ img.tiles[0].tileComps[0].nQuantSteps = 1;
1108
+ img.tiles[0].tileComps[0].quantSteps =
1109
+ (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1110
+ img.tiles[0].tileComps[0].nQuantSteps,
1111
+ sizeof(Guint));
1112
+ if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
1113
+ error(getPos(), "Error in JPX QCD marker segment");
1114
+ return gFalse;
1115
+ }
1116
+ } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
1117
+ img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1118
+ img.tiles[0].tileComps[0].quantSteps =
1119
+ (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1120
+ img.tiles[0].tileComps[0].nQuantSteps,
1121
+ sizeof(Guint));
1122
+ for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1123
+ if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
1124
+ error(getPos(), "Error in JPX QCD marker segment");
1125
+ return gFalse;
1126
+ }
1127
+ }
1128
+ } else {
1129
+ error(getPos(), "Error in JPX QCD marker segment");
1130
+ return gFalse;
1131
+ }
1132
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1133
+ for (comp = 0; comp < img.nComps; ++comp) {
1134
+ if (!(i == 0 && comp == 0)) {
1135
+ img.tiles[i].tileComps[comp].quantStyle =
1136
+ img.tiles[0].tileComps[0].quantStyle;
1137
+ img.tiles[i].tileComps[comp].nQuantSteps =
1138
+ img.tiles[0].tileComps[0].nQuantSteps;
1139
+ img.tiles[i].tileComps[comp].quantSteps =
1140
+ (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
1141
+ img.tiles[0].tileComps[0].nQuantSteps,
1142
+ sizeof(Guint));
1143
+ for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
1144
+ img.tiles[i].tileComps[comp].quantSteps[j] =
1145
+ img.tiles[0].tileComps[0].quantSteps[j];
1146
+ }
1147
+ }
1148
+ }
1149
+ }
1150
+ haveQCD = gTrue;
1151
+ break;
1152
+ case 0x5d: // QCC - quantization component
1153
+ cover(24);
1154
+ if (!haveQCD) {
1155
+ error(getPos(), "JPX QCC marker segment before QCD segment");
1156
+ return gFalse;
1157
+ }
1158
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1159
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1160
+ comp >= img.nComps ||
1161
+ !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
1162
+ error(getPos(), "Error in JPX QCC marker segment");
1163
+ return gFalse;
1164
+ }
1165
+ if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1166
+ img.tiles[0].tileComps[comp].nQuantSteps =
1167
+ segLen - (img.nComps > 256 ? 5 : 4);
1168
+ img.tiles[0].tileComps[comp].quantSteps =
1169
+ (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1170
+ img.tiles[0].tileComps[comp].nQuantSteps,
1171
+ sizeof(Guint));
1172
+ for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1173
+ if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1174
+ error(getPos(), "Error in JPX QCC marker segment");
1175
+ return gFalse;
1176
+ }
1177
+ }
1178
+ } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
1179
+ img.tiles[0].tileComps[comp].nQuantSteps = 1;
1180
+ img.tiles[0].tileComps[comp].quantSteps =
1181
+ (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1182
+ img.tiles[0].tileComps[comp].nQuantSteps,
1183
+ sizeof(Guint));
1184
+ if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
1185
+ error(getPos(), "Error in JPX QCC marker segment");
1186
+ return gFalse;
1187
+ }
1188
+ } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
1189
+ img.tiles[0].tileComps[comp].nQuantSteps =
1190
+ (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1191
+ img.tiles[0].tileComps[comp].quantSteps =
1192
+ (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1193
+ img.tiles[0].tileComps[comp].nQuantSteps,
1194
+ sizeof(Guint));
1195
+ for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1196
+ if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1197
+ error(getPos(), "Error in JPX QCD marker segment");
1198
+ return gFalse;
1199
+ }
1200
+ }
1201
+ } else {
1202
+ error(getPos(), "Error in JPX QCC marker segment");
1203
+ return gFalse;
1204
+ }
1205
+ for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
1206
+ img.tiles[i].tileComps[comp].quantStyle =
1207
+ img.tiles[0].tileComps[comp].quantStyle;
1208
+ img.tiles[i].tileComps[comp].nQuantSteps =
1209
+ img.tiles[0].tileComps[comp].nQuantSteps;
1210
+ img.tiles[i].tileComps[comp].quantSteps =
1211
+ (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
1212
+ img.tiles[0].tileComps[comp].nQuantSteps,
1213
+ sizeof(Guint));
1214
+ for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
1215
+ img.tiles[i].tileComps[comp].quantSteps[j] =
1216
+ img.tiles[0].tileComps[comp].quantSteps[j];
1217
+ }
1218
+ }
1219
+ break;
1220
+ case 0x5e: // RGN - region of interest
1221
+ cover(25);
1222
+ #if 1 //~ ROI is unimplemented
1223
+ fprintf(stderr, "RGN\n");
1224
+ for (i = 0; i < segLen - 2; ++i) {
1225
+ if (str->getChar() == EOF) {
1226
+ error(getPos(), "Error in JPX PPM marker segment");
1227
+ return gFalse;
1228
+ }
1229
+ }
1230
+ #else
1231
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1232
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1233
+ comp >= img.nComps ||
1234
+ !readUByte(&compInfo[comp].defROI.style) ||
1235
+ !readUByte(&compInfo[comp].defROI.shift)) {
1236
+ error(getPos(), "Error in JPX RGN marker segment");
1237
+ return gFalse;
1238
+ }
1239
+ #endif
1240
+ break;
1241
+ case 0x5f: // POC - progression order change
1242
+ cover(26);
1243
+ #if 1 //~ progression order changes are unimplemented
1244
+ fprintf(stderr, "POC\n");
1245
+ for (i = 0; i < segLen - 2; ++i) {
1246
+ if (str->getChar() == EOF) {
1247
+ error(getPos(), "Error in JPX PPM marker segment");
1248
+ return gFalse;
1249
+ }
1250
+ }
1251
+ #else
1252
+ nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1253
+ progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder));
1254
+ for (i = 0; i < nProgs; ++i) {
1255
+ if (!readUByte(&progs[i].startRes) ||
1256
+ !(img.nComps > 256 && readUWord(&progs[i].startComp)) ||
1257
+ !(img.nComps <= 256 && readUByte(&progs[i].startComp)) ||
1258
+ !readUWord(&progs[i].endLayer) ||
1259
+ !readUByte(&progs[i].endRes) ||
1260
+ !(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
1261
+ !(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
1262
+ !readUByte(&progs[i].progOrder)) {
1263
+ error(getPos(), "Error in JPX POC marker segment");
1264
+ return gFalse;
1265
+ }
1266
+ }
1267
+ #endif
1268
+ break;
1269
+ case 0x60: // PPM - packed packet headers, main header
1270
+ cover(27);
1271
+ #if 1 //~ packed packet headers are unimplemented
1272
+ fprintf(stderr, "PPM\n");
1273
+ for (i = 0; i < segLen - 2; ++i) {
1274
+ if (str->getChar() == EOF) {
1275
+ error(getPos(), "Error in JPX PPM marker segment");
1276
+ return gFalse;
1277
+ }
1278
+ }
1279
+ #endif
1280
+ break;
1281
+ case 0x55: // TLM - tile-part lengths
1282
+ // skipped
1283
+ cover(28);
1284
+ for (i = 0; i < segLen - 2; ++i) {
1285
+ if (str->getChar() == EOF) {
1286
+ error(getPos(), "Error in JPX TLM marker segment");
1287
+ return gFalse;
1288
+ }
1289
+ }
1290
+ break;
1291
+ case 0x57: // PLM - packet length, main header
1292
+ // skipped
1293
+ cover(29);
1294
+ for (i = 0; i < segLen - 2; ++i) {
1295
+ if (str->getChar() == EOF) {
1296
+ error(getPos(), "Error in JPX PLM marker segment");
1297
+ return gFalse;
1298
+ }
1299
+ }
1300
+ break;
1301
+ case 0x63: // CRG - component registration
1302
+ // skipped
1303
+ cover(30);
1304
+ for (i = 0; i < segLen - 2; ++i) {
1305
+ if (str->getChar() == EOF) {
1306
+ error(getPos(), "Error in JPX CRG marker segment");
1307
+ return gFalse;
1308
+ }
1309
+ }
1310
+ break;
1311
+ case 0x64: // COM - comment
1312
+ // skipped
1313
+ cover(31);
1314
+ for (i = 0; i < segLen - 2; ++i) {
1315
+ if (str->getChar() == EOF) {
1316
+ error(getPos(), "Error in JPX COM marker segment");
1317
+ return gFalse;
1318
+ }
1319
+ }
1320
+ break;
1321
+ case 0x90: // SOT - start of tile
1322
+ cover(32);
1323
+ haveSOT = gTrue;
1324
+ break;
1325
+ default:
1326
+ cover(33);
1327
+ error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
1328
+ for (i = 0; i < segLen - 2; ++i) {
1329
+ if (str->getChar() == EOF) {
1330
+ break;
1331
+ }
1332
+ }
1333
+ break;
1334
+ }
1335
+ } while (!haveSOT);
1336
+
1337
+ if (!haveSIZ) {
1338
+ error(getPos(), "Missing SIZ marker segment in JPX stream");
1339
+ return gFalse;
1340
+ }
1341
+ if (!haveCOD) {
1342
+ error(getPos(), "Missing COD marker segment in JPX stream");
1343
+ return gFalse;
1344
+ }
1345
+ if (!haveQCD) {
1346
+ error(getPos(), "Missing QCD marker segment in JPX stream");
1347
+ return gFalse;
1348
+ }
1349
+
1350
+ //----- read the tile-parts
1351
+ while (1) {
1352
+ if (!readTilePart()) {
1353
+ return gFalse;
1354
+ }
1355
+ if (!readMarkerHdr(&segType, &segLen)) {
1356
+ error(getPos(), "Error in JPX codestream");
1357
+ return gFalse;
1358
+ }
1359
+ if (segType != 0x90) { // SOT - start of tile
1360
+ break;
1361
+ }
1362
+ }
1363
+
1364
+ if (segType != 0xd9) { // EOC - end of codestream
1365
+ error(getPos(), "Missing EOC marker in JPX codestream");
1366
+ return gFalse;
1367
+ }
1368
+
1369
+ //----- finish decoding the image
1370
+ for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1371
+ tile = &img.tiles[i];
1372
+ for (comp = 0; comp < img.nComps; ++comp) {
1373
+ tileComp = &tile->tileComps[comp];
1374
+ inverseTransform(tileComp);
1375
+ }
1376
+ if (!inverseMultiCompAndDC(tile)) {
1377
+ return gFalse;
1378
+ }
1379
+ }
1380
+
1381
+ //~ can free memory below tileComps here, and also tileComp.buf
1382
+
1383
+ return gTrue;
1384
+ }
1385
+
1386
+ GBool JPXStream::readTilePart() {
1387
+ JPXTile *tile;
1388
+ JPXTileComp *tileComp;
1389
+ JPXResLevel *resLevel;
1390
+ JPXPrecinct *precinct;
1391
+ JPXSubband *subband;
1392
+ JPXCodeBlock *cb;
1393
+ GBool haveSOD;
1394
+ Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
1395
+ GBool tilePartToEOC;
1396
+ Guint precinctSize, style;
1397
+ Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
1398
+ Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
1399
+ int segType, level;
1400
+
1401
+ // process the SOT marker segment
1402
+ if (!readUWord(&tileIdx) ||
1403
+ !readULong(&tilePartLen) ||
1404
+ !readUByte(&tilePartIdx) ||
1405
+ !readUByte(&nTileParts)) {
1406
+ error(getPos(), "Error in JPX SOT marker segment");
1407
+ return gFalse;
1408
+ }
1409
+
1410
+ if (tileIdx >= img.nXTiles * img.nYTiles) {
1411
+ error(getPos(), "Weird tile index in JPX stream");
1412
+ return gFalse;
1413
+ }
1414
+
1415
+ tilePartToEOC = tilePartLen == 0;
1416
+ tilePartLen -= 12; // subtract size of SOT segment
1417
+
1418
+ haveSOD = gFalse;
1419
+ do {
1420
+ if (!readMarkerHdr(&segType, &segLen)) {
1421
+ error(getPos(), "Error in JPX tile-part codestream");
1422
+ return gFalse;
1423
+ }
1424
+ tilePartLen -= 2 + segLen;
1425
+ switch (segType) {
1426
+ case 0x52: // COD - coding style default
1427
+ cover(34);
1428
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
1429
+ !readUByte(&img.tiles[tileIdx].progOrder) ||
1430
+ !readUWord(&img.tiles[tileIdx].nLayers) ||
1431
+ !readUByte(&img.tiles[tileIdx].multiComp) ||
1432
+ !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) ||
1433
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) ||
1434
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
1435
+ !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
1436
+ !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
1437
+ error(getPos(), "Error in JPX COD marker segment");
1438
+ return gFalse;
1439
+ }
1440
+ img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
1441
+ img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
1442
+ for (comp = 0; comp < img.nComps; ++comp) {
1443
+ if (comp != 0) {
1444
+ img.tiles[tileIdx].tileComps[comp].style =
1445
+ img.tiles[tileIdx].tileComps[0].style;
1446
+ img.tiles[tileIdx].tileComps[comp].nDecompLevels =
1447
+ img.tiles[tileIdx].tileComps[0].nDecompLevels;
1448
+ img.tiles[tileIdx].tileComps[comp].codeBlockW =
1449
+ img.tiles[tileIdx].tileComps[0].codeBlockW;
1450
+ img.tiles[tileIdx].tileComps[comp].codeBlockH =
1451
+ img.tiles[tileIdx].tileComps[0].codeBlockH;
1452
+ img.tiles[tileIdx].tileComps[comp].codeBlockStyle =
1453
+ img.tiles[tileIdx].tileComps[0].codeBlockStyle;
1454
+ img.tiles[tileIdx].tileComps[comp].transform =
1455
+ img.tiles[tileIdx].tileComps[0].transform;
1456
+ }
1457
+ img.tiles[tileIdx].tileComps[comp].resLevels =
1458
+ (JPXResLevel *)greallocn(
1459
+ img.tiles[tileIdx].tileComps[comp].resLevels,
1460
+ (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
1461
+ sizeof(JPXResLevel));
1462
+ for (r = 0;
1463
+ r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1464
+ ++r) {
1465
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1466
+ }
1467
+ }
1468
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
1469
+ if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
1470
+ if (!readUByte(&precinctSize)) {
1471
+ error(getPos(), "Error in JPX COD marker segment");
1472
+ return gFalse;
1473
+ }
1474
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
1475
+ precinctSize & 0x0f;
1476
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
1477
+ (precinctSize >> 4) & 0x0f;
1478
+ } else {
1479
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
1480
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
1481
+ }
1482
+ }
1483
+ for (comp = 1; comp < img.nComps; ++comp) {
1484
+ for (r = 0;
1485
+ r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1486
+ ++r) {
1487
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1488
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
1489
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1490
+ img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
1491
+ }
1492
+ }
1493
+ break;
1494
+ case 0x53: // COC - coding style component
1495
+ cover(35);
1496
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1497
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1498
+ comp >= img.nComps ||
1499
+ !readUByte(&style) ||
1500
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) ||
1501
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) ||
1502
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
1503
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
1504
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
1505
+ error(getPos(), "Error in JPX COC marker segment");
1506
+ return gFalse;
1507
+ }
1508
+ img.tiles[tileIdx].tileComps[comp].style =
1509
+ (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
1510
+ img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
1511
+ img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
1512
+ img.tiles[tileIdx].tileComps[comp].resLevels =
1513
+ (JPXResLevel *)greallocn(
1514
+ img.tiles[tileIdx].tileComps[comp].resLevels,
1515
+ (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
1516
+ sizeof(JPXResLevel));
1517
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1518
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1519
+ }
1520
+ for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1521
+ if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
1522
+ if (!readUByte(&precinctSize)) {
1523
+ error(getPos(), "Error in JPX COD marker segment");
1524
+ return gFalse;
1525
+ }
1526
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1527
+ precinctSize & 0x0f;
1528
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1529
+ (precinctSize >> 4) & 0x0f;
1530
+ } else {
1531
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
1532
+ img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
1533
+ }
1534
+ }
1535
+ break;
1536
+ case 0x5c: // QCD - quantization default
1537
+ cover(36);
1538
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
1539
+ error(getPos(), "Error in JPX QCD marker segment");
1540
+ return gFalse;
1541
+ }
1542
+ if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
1543
+ img.tiles[tileIdx].tileComps[0].nQuantSteps =
1544
+ segLen - 3;
1545
+ img.tiles[tileIdx].tileComps[0].quantSteps =
1546
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1547
+ img.tiles[tileIdx].tileComps[0].nQuantSteps,
1548
+ sizeof(Guint));
1549
+ for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1550
+ if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1551
+ error(getPos(), "Error in JPX QCD marker segment");
1552
+ return gFalse;
1553
+ }
1554
+ }
1555
+ } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
1556
+ img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
1557
+ img.tiles[tileIdx].tileComps[0].quantSteps =
1558
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1559
+ img.tiles[tileIdx].tileComps[0].nQuantSteps,
1560
+ sizeof(Guint));
1561
+ if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
1562
+ error(getPos(), "Error in JPX QCD marker segment");
1563
+ return gFalse;
1564
+ }
1565
+ } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
1566
+ img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1567
+ img.tiles[tileIdx].tileComps[0].quantSteps =
1568
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1569
+ img.tiles[tileIdx].tileComps[0].nQuantSteps,
1570
+ sizeof(Guint));
1571
+ for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1572
+ if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1573
+ error(getPos(), "Error in JPX QCD marker segment");
1574
+ return gFalse;
1575
+ }
1576
+ }
1577
+ } else {
1578
+ error(getPos(), "Error in JPX QCD marker segment");
1579
+ return gFalse;
1580
+ }
1581
+ for (comp = 1; comp < img.nComps; ++comp) {
1582
+ img.tiles[tileIdx].tileComps[comp].quantStyle =
1583
+ img.tiles[tileIdx].tileComps[0].quantStyle;
1584
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1585
+ img.tiles[tileIdx].tileComps[0].nQuantSteps;
1586
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
1587
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1588
+ img.tiles[tileIdx].tileComps[0].nQuantSteps,
1589
+ sizeof(Guint));
1590
+ for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
1591
+ img.tiles[tileIdx].tileComps[comp].quantSteps[j] =
1592
+ img.tiles[tileIdx].tileComps[0].quantSteps[j];
1593
+ }
1594
+ }
1595
+ break;
1596
+ case 0x5d: // QCC - quantization component
1597
+ cover(37);
1598
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1599
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1600
+ comp >= img.nComps ||
1601
+ !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
1602
+ error(getPos(), "Error in JPX QCC marker segment");
1603
+ return gFalse;
1604
+ }
1605
+ if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1606
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1607
+ segLen - (img.nComps > 256 ? 5 : 4);
1608
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
1609
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1610
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1611
+ sizeof(Guint));
1612
+ for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1613
+ if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1614
+ error(getPos(), "Error in JPX QCC marker segment");
1615
+ return gFalse;
1616
+ }
1617
+ }
1618
+ } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1619
+ == 0x01) {
1620
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
1621
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
1622
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1623
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1624
+ sizeof(Guint));
1625
+ if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
1626
+ error(getPos(), "Error in JPX QCC marker segment");
1627
+ return gFalse;
1628
+ }
1629
+ } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1630
+ == 0x02) {
1631
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1632
+ (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1633
+ img.tiles[tileIdx].tileComps[comp].quantSteps =
1634
+ (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1635
+ img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1636
+ sizeof(Guint));
1637
+ for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1638
+ if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1639
+ error(getPos(), "Error in JPX QCD marker segment");
1640
+ return gFalse;
1641
+ }
1642
+ }
1643
+ } else {
1644
+ error(getPos(), "Error in JPX QCC marker segment");
1645
+ return gFalse;
1646
+ }
1647
+ break;
1648
+ case 0x5e: // RGN - region of interest
1649
+ cover(38);
1650
+ #if 1 //~ ROI is unimplemented
1651
+ fprintf(stderr, "RGN\n");
1652
+ for (i = 0; i < segLen - 2; ++i) {
1653
+ if (str->getChar() == EOF) {
1654
+ error(getPos(), "Error in JPX PPM marker segment");
1655
+ return gFalse;
1656
+ }
1657
+ }
1658
+ #else
1659
+ if ((img.nComps > 256 && !readUWord(&comp)) ||
1660
+ (img.nComps <= 256 && !readUByte(&comp)) ||
1661
+ comp >= img.nComps ||
1662
+ !readUByte(&compInfo[comp].roi.style) ||
1663
+ !readUByte(&compInfo[comp].roi.shift)) {
1664
+ error(getPos(), "Error in JPX RGN marker segment");
1665
+ return gFalse;
1666
+ }
1667
+ #endif
1668
+ break;
1669
+ case 0x5f: // POC - progression order change
1670
+ cover(39);
1671
+ #if 1 //~ progression order changes are unimplemented
1672
+ fprintf(stderr, "POC\n");
1673
+ for (i = 0; i < segLen - 2; ++i) {
1674
+ if (str->getChar() == EOF) {
1675
+ error(getPos(), "Error in JPX PPM marker segment");
1676
+ return gFalse;
1677
+ }
1678
+ }
1679
+ #else
1680
+ nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1681
+ tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder));
1682
+ for (i = 0; i < nTileProgs; ++i) {
1683
+ if (!readUByte(&tileProgs[i].startRes) ||
1684
+ !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) ||
1685
+ !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) ||
1686
+ !readUWord(&tileProgs[i].endLayer) ||
1687
+ !readUByte(&tileProgs[i].endRes) ||
1688
+ !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
1689
+ !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
1690
+ !readUByte(&tileProgs[i].progOrder)) {
1691
+ error(getPos(), "Error in JPX POC marker segment");
1692
+ return gFalse;
1693
+ }
1694
+ }
1695
+ #endif
1696
+ break;
1697
+ case 0x61: // PPT - packed packet headers, tile-part hdr
1698
+ cover(40);
1699
+ #if 1 //~ packed packet headers are unimplemented
1700
+ fprintf(stderr, "PPT\n");
1701
+ for (i = 0; i < segLen - 2; ++i) {
1702
+ if (str->getChar() == EOF) {
1703
+ error(getPos(), "Error in JPX PPT marker segment");
1704
+ return gFalse;
1705
+ }
1706
+ }
1707
+ #endif
1708
+ case 0x58: // PLT - packet length, tile-part header
1709
+ // skipped
1710
+ cover(41);
1711
+ for (i = 0; i < segLen - 2; ++i) {
1712
+ if (str->getChar() == EOF) {
1713
+ error(getPos(), "Error in JPX PLT marker segment");
1714
+ return gFalse;
1715
+ }
1716
+ }
1717
+ break;
1718
+ case 0x64: // COM - comment
1719
+ // skipped
1720
+ cover(42);
1721
+ for (i = 0; i < segLen - 2; ++i) {
1722
+ if (str->getChar() == EOF) {
1723
+ error(getPos(), "Error in JPX COM marker segment");
1724
+ return gFalse;
1725
+ }
1726
+ }
1727
+ break;
1728
+ case 0x93: // SOD - start of data
1729
+ cover(43);
1730
+ haveSOD = gTrue;
1731
+ break;
1732
+ default:
1733
+ cover(44);
1734
+ error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
1735
+ segType);
1736
+ for (i = 0; i < segLen - 2; ++i) {
1737
+ if (str->getChar() == EOF) {
1738
+ break;
1739
+ }
1740
+ }
1741
+ break;
1742
+ }
1743
+ } while (!haveSOD);
1744
+
1745
+ //----- initialize the tile, precincts, and code-blocks
1746
+ if (tilePartIdx == 0) {
1747
+ tile = &img.tiles[tileIdx];
1748
+ i = tileIdx / img.nXTiles;
1749
+ j = tileIdx % img.nXTiles;
1750
+ if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
1751
+ tile->x0 = img.xOffset;
1752
+ }
1753
+ if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
1754
+ tile->y0 = img.yOffset;
1755
+ }
1756
+ if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
1757
+ tile->x1 = img.xSize;
1758
+ }
1759
+ if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
1760
+ tile->y1 = img.ySize;
1761
+ }
1762
+ tile->comp = 0;
1763
+ tile->res = 0;
1764
+ tile->precinct = 0;
1765
+ tile->layer = 0;
1766
+ tile->maxNDecompLevels = 0;
1767
+ for (comp = 0; comp < img.nComps; ++comp) {
1768
+ tileComp = &tile->tileComps[comp];
1769
+ if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
1770
+ tile->maxNDecompLevels = tileComp->nDecompLevels;
1771
+ }
1772
+ tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
1773
+ tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
1774
+ tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
1775
+ tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
1776
+ tileComp->cbW = 1 << tileComp->codeBlockW;
1777
+ tileComp->cbH = 1 << tileComp->codeBlockH;
1778
+ tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) *
1779
+ (tileComp->y1 - tileComp->y0),
1780
+ sizeof(int));
1781
+ if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
1782
+ n = tileComp->x1 - tileComp->x0;
1783
+ } else {
1784
+ n = tileComp->y1 - tileComp->y0;
1785
+ }
1786
+ tileComp->buf = (int *)gmallocn(n + 8, sizeof(int));
1787
+ for (r = 0; r <= tileComp->nDecompLevels; ++r) {
1788
+ resLevel = &tileComp->resLevels[r];
1789
+ k = r == 0 ? tileComp->nDecompLevels
1790
+ : tileComp->nDecompLevels - r + 1;
1791
+ resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
1792
+ resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
1793
+ resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
1794
+ resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
1795
+ if (r == 0) {
1796
+ resLevel->bx0[0] = resLevel->x0;
1797
+ resLevel->by0[0] = resLevel->y0;
1798
+ resLevel->bx1[0] = resLevel->x1;
1799
+ resLevel->by1[0] = resLevel->y1;
1800
+ } else {
1801
+ resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1802
+ resLevel->by0[0] = resLevel->y0;
1803
+ resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1804
+ resLevel->by1[0] = resLevel->y1;
1805
+ resLevel->bx0[1] = resLevel->x0;
1806
+ resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1807
+ resLevel->bx1[1] = resLevel->x1;
1808
+ resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1809
+ resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1810
+ resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1811
+ resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1812
+ resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1813
+ }
1814
+ resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct));
1815
+ for (pre = 0; pre < 1; ++pre) {
1816
+ precinct = &resLevel->precincts[pre];
1817
+ precinct->x0 = resLevel->x0;
1818
+ precinct->y0 = resLevel->y0;
1819
+ precinct->x1 = resLevel->x1;
1820
+ precinct->y1 = resLevel->y1;
1821
+ nSBs = r == 0 ? 1 : 3;
1822
+ precinct->subbands =
1823
+ (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband));
1824
+ for (sb = 0; sb < nSBs; ++sb) {
1825
+ subband = &precinct->subbands[sb];
1826
+ subband->x0 = resLevel->bx0[sb];
1827
+ subband->y0 = resLevel->by0[sb];
1828
+ subband->x1 = resLevel->bx1[sb];
1829
+ subband->y1 = resLevel->by1[sb];
1830
+ subband->nXCBs = jpxCeilDivPow2(subband->x1,
1831
+ tileComp->codeBlockW)
1832
+ - jpxFloorDivPow2(subband->x0,
1833
+ tileComp->codeBlockW);
1834
+ subband->nYCBs = jpxCeilDivPow2(subband->y1,
1835
+ tileComp->codeBlockH)
1836
+ - jpxFloorDivPow2(subband->y0,
1837
+ tileComp->codeBlockH);
1838
+ n = subband->nXCBs > subband->nYCBs ? subband->nXCBs
1839
+ : subband->nYCBs;
1840
+ for (subband->maxTTLevel = 0, --n;
1841
+ n;
1842
+ ++subband->maxTTLevel, n >>= 1) ;
1843
+ n = 0;
1844
+ for (level = subband->maxTTLevel; level >= 0; --level) {
1845
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
1846
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
1847
+ n += nx * ny;
1848
+ }
1849
+ subband->inclusion =
1850
+ (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1851
+ subband->zeroBitPlane =
1852
+ (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1853
+ for (k = 0; k < n; ++k) {
1854
+ subband->inclusion[k].finished = gFalse;
1855
+ subband->inclusion[k].val = 0;
1856
+ subband->zeroBitPlane[k].finished = gFalse;
1857
+ subband->zeroBitPlane[k].val = 0;
1858
+ }
1859
+ subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs *
1860
+ subband->nYCBs,
1861
+ sizeof(JPXCodeBlock));
1862
+ sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
1863
+ sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
1864
+ cb = subband->cbs;
1865
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1866
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1867
+ cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
1868
+ cb->x1 = cb->x0 + tileComp->cbW;
1869
+ if (subband->x0 > cb->x0) {
1870
+ cb->x0 = subband->x0;
1871
+ }
1872
+ if (subband->x1 < cb->x1) {
1873
+ cb->x1 = subband->x1;
1874
+ }
1875
+ cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
1876
+ cb->y1 = cb->y0 + tileComp->cbH;
1877
+ if (subband->y0 > cb->y0) {
1878
+ cb->y0 = subband->y0;
1879
+ }
1880
+ if (subband->y1 < cb->y1) {
1881
+ cb->y1 = subband->y1;
1882
+ }
1883
+ cb->seen = gFalse;
1884
+ cb->lBlock = 3;
1885
+ cb->nextPass = jpxPassCleanup;
1886
+ cb->nZeroBitPlanes = 0;
1887
+ cb->coeffs =
1888
+ (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW
1889
+ + tileComp->codeBlockH)),
1890
+ sizeof(JPXCoeff));
1891
+ for (cbi = 0;
1892
+ cbi < (Guint)(1 << (tileComp->codeBlockW
1893
+ + tileComp->codeBlockH));
1894
+ ++cbi) {
1895
+ cb->coeffs[cbi].flags = 0;
1896
+ cb->coeffs[cbi].len = 0;
1897
+ cb->coeffs[cbi].mag = 0;
1898
+ }
1899
+ cb->arithDecoder = NULL;
1900
+ cb->stats = NULL;
1901
+ ++cb;
1902
+ }
1903
+ }
1904
+ }
1905
+ }
1906
+ }
1907
+ }
1908
+ }
1909
+
1910
+ return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
1911
+ }
1912
+
1913
+ GBool JPXStream::readTilePartData(Guint tileIdx,
1914
+ Guint tilePartLen, GBool tilePartToEOC) {
1915
+ JPXTile *tile;
1916
+ JPXTileComp *tileComp;
1917
+ JPXResLevel *resLevel;
1918
+ JPXPrecinct *precinct;
1919
+ JPXSubband *subband;
1920
+ JPXCodeBlock *cb;
1921
+ Guint ttVal;
1922
+ Guint bits, cbX, cbY, nx, ny, i, j, n, sb;
1923
+ int level;
1924
+
1925
+ tile = &img.tiles[tileIdx];
1926
+
1927
+ // read all packets from this tile-part
1928
+ while (1) {
1929
+ if (tilePartToEOC) {
1930
+ //~ peek for an EOC marker
1931
+ cover(93);
1932
+ } else if (tilePartLen == 0) {
1933
+ break;
1934
+ }
1935
+
1936
+ tileComp = &tile->tileComps[tile->comp];
1937
+ resLevel = &tileComp->resLevels[tile->res];
1938
+ precinct = &resLevel->precincts[tile->precinct];
1939
+
1940
+ //----- packet header
1941
+
1942
+ // setup
1943
+ startBitBuf(tilePartLen);
1944
+
1945
+ // zero-length flag
1946
+ if (!readBits(1, &bits)) {
1947
+ goto err;
1948
+ }
1949
+ if (!bits) {
1950
+ // packet is empty -- clear all code-block inclusion flags
1951
+ cover(45);
1952
+ for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
1953
+ subband = &precinct->subbands[sb];
1954
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1955
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1956
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1957
+ cb->included = gFalse;
1958
+ }
1959
+ }
1960
+ }
1961
+ } else {
1962
+
1963
+ for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
1964
+ subband = &precinct->subbands[sb];
1965
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1966
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1967
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1968
+
1969
+ // skip code-blocks with no coefficients
1970
+ if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
1971
+ cover(46);
1972
+ cb->included = gFalse;
1973
+ continue;
1974
+ }
1975
+
1976
+ // code-block inclusion
1977
+ if (cb->seen) {
1978
+ cover(47);
1979
+ if (!readBits(1, &cb->included)) {
1980
+ goto err;
1981
+ }
1982
+ } else {
1983
+ cover(48);
1984
+ ttVal = 0;
1985
+ i = 0;
1986
+ for (level = subband->maxTTLevel; level >= 0; --level) {
1987
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
1988
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
1989
+ j = i + (cbY >> level) * nx + (cbX >> level);
1990
+ if (!subband->inclusion[j].finished &&
1991
+ !subband->inclusion[j].val) {
1992
+ subband->inclusion[j].val = ttVal;
1993
+ } else {
1994
+ ttVal = subband->inclusion[j].val;
1995
+ }
1996
+ while (!subband->inclusion[j].finished &&
1997
+ ttVal <= tile->layer) {
1998
+ if (!readBits(1, &bits)) {
1999
+ goto err;
2000
+ }
2001
+ if (bits == 1) {
2002
+ subband->inclusion[j].finished = gTrue;
2003
+ } else {
2004
+ ++ttVal;
2005
+ }
2006
+ }
2007
+ subband->inclusion[j].val = ttVal;
2008
+ if (ttVal > tile->layer) {
2009
+ break;
2010
+ }
2011
+ i += nx * ny;
2012
+ }
2013
+ cb->included = level < 0;
2014
+ }
2015
+
2016
+ if (cb->included) {
2017
+ cover(49);
2018
+
2019
+ // zero bit-plane count
2020
+ if (!cb->seen) {
2021
+ cover(50);
2022
+ ttVal = 0;
2023
+ i = 0;
2024
+ for (level = subband->maxTTLevel; level >= 0; --level) {
2025
+ nx = jpxCeilDivPow2(subband->nXCBs, level);
2026
+ ny = jpxCeilDivPow2(subband->nYCBs, level);
2027
+ j = i + (cbY >> level) * nx + (cbX >> level);
2028
+ if (!subband->zeroBitPlane[j].finished &&
2029
+ !subband->zeroBitPlane[j].val) {
2030
+ subband->zeroBitPlane[j].val = ttVal;
2031
+ } else {
2032
+ ttVal = subband->zeroBitPlane[j].val;
2033
+ }
2034
+ while (!subband->zeroBitPlane[j].finished) {
2035
+ if (!readBits(1, &bits)) {
2036
+ goto err;
2037
+ }
2038
+ if (bits == 1) {
2039
+ subband->zeroBitPlane[j].finished = gTrue;
2040
+ } else {
2041
+ ++ttVal;
2042
+ }
2043
+ }
2044
+ subband->zeroBitPlane[j].val = ttVal;
2045
+ i += nx * ny;
2046
+ }
2047
+ cb->nZeroBitPlanes = ttVal;
2048
+ }
2049
+
2050
+ // number of coding passes
2051
+ if (!readBits(1, &bits)) {
2052
+ goto err;
2053
+ }
2054
+ if (bits == 0) {
2055
+ cover(51);
2056
+ cb->nCodingPasses = 1;
2057
+ } else {
2058
+ if (!readBits(1, &bits)) {
2059
+ goto err;
2060
+ }
2061
+ if (bits == 0) {
2062
+ cover(52);
2063
+ cb->nCodingPasses = 2;
2064
+ } else {
2065
+ cover(53);
2066
+ if (!readBits(2, &bits)) {
2067
+ goto err;
2068
+ }
2069
+ if (bits < 3) {
2070
+ cover(54);
2071
+ cb->nCodingPasses = 3 + bits;
2072
+ } else {
2073
+ cover(55);
2074
+ if (!readBits(5, &bits)) {
2075
+ goto err;
2076
+ }
2077
+ if (bits < 31) {
2078
+ cover(56);
2079
+ cb->nCodingPasses = 6 + bits;
2080
+ } else {
2081
+ cover(57);
2082
+ if (!readBits(7, &bits)) {
2083
+ goto err;
2084
+ }
2085
+ cb->nCodingPasses = 37 + bits;
2086
+ }
2087
+ }
2088
+ }
2089
+ }
2090
+
2091
+ // update Lblock
2092
+ while (1) {
2093
+ if (!readBits(1, &bits)) {
2094
+ goto err;
2095
+ }
2096
+ if (!bits) {
2097
+ break;
2098
+ }
2099
+ ++cb->lBlock;
2100
+ }
2101
+
2102
+ // length of compressed data
2103
+ //~ deal with multiple codeword segments
2104
+ for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
2105
+ i;
2106
+ ++n, i >>= 1) ;
2107
+ if (!readBits(n, &cb->dataLen)) {
2108
+ goto err;
2109
+ }
2110
+ }
2111
+ }
2112
+ }
2113
+ }
2114
+ }
2115
+ tilePartLen = finishBitBuf();
2116
+
2117
+ //----- packet data
2118
+
2119
+ for (sb = 0; sb < (Guint)(tile->res == 0 ? 1 : 3); ++sb) {
2120
+ subband = &precinct->subbands[sb];
2121
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2122
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2123
+ cb = &subband->cbs[cbY * subband->nXCBs + cbX];
2124
+ if (cb->included) {
2125
+ if (!readCodeBlockData(tileComp, resLevel, precinct, subband,
2126
+ tile->res, sb, cb)) {
2127
+ return gFalse;
2128
+ }
2129
+ tilePartLen -= cb->dataLen;
2130
+ cb->seen = gTrue;
2131
+ }
2132
+ }
2133
+ }
2134
+ }
2135
+
2136
+ //----- next packet
2137
+
2138
+ switch (tile->progOrder) {
2139
+ case 0: // layer, resolution level, component, precinct
2140
+ cover(58);
2141
+ if (++tile->comp == img.nComps) {
2142
+ tile->comp = 0;
2143
+ if (++tile->res == tile->maxNDecompLevels + 1) {
2144
+ tile->res = 0;
2145
+ if (++tile->layer == tile->nLayers) {
2146
+ tile->layer = 0;
2147
+ }
2148
+ }
2149
+ }
2150
+ break;
2151
+ case 1: // resolution level, layer, component, precinct
2152
+ cover(59);
2153
+ if (++tile->comp == img.nComps) {
2154
+ tile->comp = 0;
2155
+ if (++tile->layer == tile->nLayers) {
2156
+ tile->layer = 0;
2157
+ if (++tile->res == tile->maxNDecompLevels + 1) {
2158
+ tile->res = 0;
2159
+ }
2160
+ }
2161
+ }
2162
+ break;
2163
+ case 2: // resolution level, precinct, component, layer
2164
+ //~ this isn't correct -- see B.12.1.3
2165
+ cover(60);
2166
+ if (++tile->layer == tile->nLayers) {
2167
+ tile->layer = 0;
2168
+ if (++tile->comp == img.nComps) {
2169
+ tile->comp = 0;
2170
+ if (++tile->res == tile->maxNDecompLevels + 1) {
2171
+ tile->res = 0;
2172
+ }
2173
+ }
2174
+ }
2175
+ break;
2176
+ case 3: // precinct, component, resolution level, layer
2177
+ //~ this isn't correct -- see B.12.1.4
2178
+ cover(61);
2179
+ if (++tile->layer == tile->nLayers) {
2180
+ tile->layer = 0;
2181
+ if (++tile->res == tile->maxNDecompLevels + 1) {
2182
+ tile->res = 0;
2183
+ if (++tile->comp == img.nComps) {
2184
+ tile->comp = 0;
2185
+ }
2186
+ }
2187
+ }
2188
+ break;
2189
+ case 4: // component, precinct, resolution level, layer
2190
+ //~ this isn't correct -- see B.12.1.5
2191
+ cover(62);
2192
+ if (++tile->layer == tile->nLayers) {
2193
+ tile->layer = 0;
2194
+ if (++tile->res == tile->maxNDecompLevels + 1) {
2195
+ tile->res = 0;
2196
+ if (++tile->comp == img.nComps) {
2197
+ tile->comp = 0;
2198
+ }
2199
+ }
2200
+ }
2201
+ break;
2202
+ }
2203
+ }
2204
+
2205
+ return gTrue;
2206
+
2207
+ err:
2208
+ error(getPos(), "Error in JPX stream");
2209
+ return gFalse;
2210
+ }
2211
+
2212
+ GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
2213
+ JPXResLevel *resLevel,
2214
+ JPXPrecinct *precinct,
2215
+ JPXSubband *subband,
2216
+ Guint res, Guint sb,
2217
+ JPXCodeBlock *cb) {
2218
+ JPXCoeff *coeff0, *coeff1, *coeff;
2219
+ Guint horiz, vert, diag, all, cx, xorBit;
2220
+ int horizSign, vertSign;
2221
+ Guint i, x, y0, y1, y2;
2222
+
2223
+ if (cb->arithDecoder) {
2224
+ cover(63);
2225
+ cb->arithDecoder->restart(cb->dataLen);
2226
+ } else {
2227
+ cover(64);
2228
+ cb->arithDecoder = new JArithmeticDecoder();
2229
+ cb->arithDecoder->setStream(str, cb->dataLen);
2230
+ cb->arithDecoder->start();
2231
+ cb->stats = new JArithmeticDecoderStats(jpxNContexts);
2232
+ cb->stats->setEntry(jpxContextSigProp, 4, 0);
2233
+ cb->stats->setEntry(jpxContextRunLength, 3, 0);
2234
+ cb->stats->setEntry(jpxContextUniform, 46, 0);
2235
+ }
2236
+
2237
+ for (i = 0; i < cb->nCodingPasses; ++i) {
2238
+ switch (cb->nextPass) {
2239
+
2240
+ //----- significance propagation pass
2241
+ case jpxPassSigProp:
2242
+ cover(65);
2243
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
2244
+ y0 < cb->y1;
2245
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2246
+ for (x = cb->x0, coeff1 = coeff0;
2247
+ x < cb->x1;
2248
+ ++x, ++coeff1) {
2249
+ for (y1 = 0, coeff = coeff1;
2250
+ y1 < 4 && y0+y1 < cb->y1;
2251
+ ++y1, coeff += tileComp->cbW) {
2252
+ if (!(coeff->flags & jpxCoeffSignificant)) {
2253
+ horiz = vert = diag = 0;
2254
+ horizSign = vertSign = 2;
2255
+ if (x > cb->x0) {
2256
+ if (coeff[-1].flags & jpxCoeffSignificant) {
2257
+ ++horiz;
2258
+ horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
2259
+ }
2260
+ if (y0+y1 > cb->y0) {
2261
+ diag += (coeff[-(int)tileComp->cbW - 1].flags
2262
+ >> jpxCoeffSignificantB) & 1;
2263
+ }
2264
+ if (y0+y1 < cb->y1 - 1) {
2265
+ diag += (coeff[tileComp->cbW - 1].flags
2266
+ >> jpxCoeffSignificantB) & 1;
2267
+ }
2268
+ }
2269
+ if (x < cb->x1 - 1) {
2270
+ if (coeff[1].flags & jpxCoeffSignificant) {
2271
+ ++horiz;
2272
+ horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2273
+ }
2274
+ if (y0+y1 > cb->y0) {
2275
+ diag += (coeff[-(int)tileComp->cbW + 1].flags
2276
+ >> jpxCoeffSignificantB) & 1;
2277
+ }
2278
+ if (y0+y1 < cb->y1 - 1) {
2279
+ diag += (coeff[tileComp->cbW + 1].flags
2280
+ >> jpxCoeffSignificantB) & 1;
2281
+ }
2282
+ }
2283
+ if (y0+y1 > cb->y0) {
2284
+ if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
2285
+ ++vert;
2286
+ vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
2287
+ ? -1 : 1;
2288
+ }
2289
+ }
2290
+ if (y0+y1 < cb->y1 - 1) {
2291
+ if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2292
+ ++vert;
2293
+ vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2294
+ ? -1 : 1;
2295
+ }
2296
+ }
2297
+ cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2298
+ if (cx != 0) {
2299
+ if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2300
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2301
+ coeff->mag = (coeff->mag << 1) | 1;
2302
+ cx = signContext[horizSign][vertSign][0];
2303
+ xorBit = signContext[horizSign][vertSign][1];
2304
+ if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2305
+ coeff->flags |= jpxCoeffSign;
2306
+ }
2307
+ }
2308
+ ++coeff->len;
2309
+ coeff->flags |= jpxCoeffTouched;
2310
+ }
2311
+ }
2312
+ }
2313
+ }
2314
+ }
2315
+ ++cb->nextPass;
2316
+ break;
2317
+
2318
+ //----- magnitude refinement pass
2319
+ case jpxPassMagRef:
2320
+ cover(66);
2321
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
2322
+ y0 < cb->y1;
2323
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2324
+ for (x = cb->x0, coeff1 = coeff0;
2325
+ x < cb->x1;
2326
+ ++x, ++coeff1) {
2327
+ for (y1 = 0, coeff = coeff1;
2328
+ y1 < 4 && y0+y1 < cb->y1;
2329
+ ++y1, coeff += tileComp->cbW) {
2330
+ if ((coeff->flags & jpxCoeffSignificant) &&
2331
+ !(coeff->flags & jpxCoeffTouched)) {
2332
+ if (coeff->flags & jpxCoeffFirstMagRef) {
2333
+ all = 0;
2334
+ if (x > cb->x0) {
2335
+ all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
2336
+ if (y0+y1 > cb->y0) {
2337
+ all += (coeff[-(int)tileComp->cbW - 1].flags
2338
+ >> jpxCoeffSignificantB) & 1;
2339
+ }
2340
+ if (y0+y1 < cb->y1 - 1) {
2341
+ all += (coeff[tileComp->cbW - 1].flags
2342
+ >> jpxCoeffSignificantB) & 1;
2343
+ }
2344
+ }
2345
+ if (x < cb->x1 - 1) {
2346
+ all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
2347
+ if (y0+y1 > cb->y0) {
2348
+ all += (coeff[-(int)tileComp->cbW + 1].flags
2349
+ >> jpxCoeffSignificantB) & 1;
2350
+ }
2351
+ if (y0+y1 < cb->y1 - 1) {
2352
+ all += (coeff[tileComp->cbW + 1].flags
2353
+ >> jpxCoeffSignificantB) & 1;
2354
+ }
2355
+ }
2356
+ if (y0+y1 > cb->y0) {
2357
+ all += (coeff[-(int)tileComp->cbW].flags
2358
+ >> jpxCoeffSignificantB) & 1;
2359
+ }
2360
+ if (y0+y1 < cb->y1 - 1) {
2361
+ all += (coeff[tileComp->cbW].flags
2362
+ >> jpxCoeffSignificantB) & 1;
2363
+ }
2364
+ cx = all ? 15 : 14;
2365
+ } else {
2366
+ cx = 16;
2367
+ }
2368
+ coeff->mag = (coeff->mag << 1) |
2369
+ cb->arithDecoder->decodeBit(cx, cb->stats);
2370
+ ++coeff->len;
2371
+ coeff->flags |= jpxCoeffTouched;
2372
+ coeff->flags &= ~jpxCoeffFirstMagRef;
2373
+ }
2374
+ }
2375
+ }
2376
+ }
2377
+ ++cb->nextPass;
2378
+ break;
2379
+
2380
+ //----- cleanup pass
2381
+ case jpxPassCleanup:
2382
+ cover(67);
2383
+ for (y0 = cb->y0, coeff0 = cb->coeffs;
2384
+ y0 < cb->y1;
2385
+ y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2386
+ for (x = cb->x0, coeff1 = coeff0;
2387
+ x < cb->x1;
2388
+ ++x, ++coeff1) {
2389
+ y1 = 0;
2390
+ if (y0 + 3 < cb->y1 &&
2391
+ !(coeff1->flags & jpxCoeffTouched) &&
2392
+ !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
2393
+ !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
2394
+ !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
2395
+ (x == cb->x0 || y0 == cb->y0 ||
2396
+ !(coeff1[-(int)tileComp->cbW - 1].flags
2397
+ & jpxCoeffSignificant)) &&
2398
+ (y0 == cb->y0 ||
2399
+ !(coeff1[-(int)tileComp->cbW].flags
2400
+ & jpxCoeffSignificant)) &&
2401
+ (x == cb->x1 - 1 || y0 == cb->y0 ||
2402
+ !(coeff1[-(int)tileComp->cbW + 1].flags
2403
+ & jpxCoeffSignificant)) &&
2404
+ (x == cb->x0 ||
2405
+ (!(coeff1[-1].flags & jpxCoeffSignificant) &&
2406
+ !(coeff1[tileComp->cbW - 1].flags
2407
+ & jpxCoeffSignificant) &&
2408
+ !(coeff1[2 * tileComp->cbW - 1].flags
2409
+ & jpxCoeffSignificant) &&
2410
+ !(coeff1[3 * tileComp->cbW - 1].flags
2411
+ & jpxCoeffSignificant))) &&
2412
+ (x == cb->x1 - 1 ||
2413
+ (!(coeff1[1].flags & jpxCoeffSignificant) &&
2414
+ !(coeff1[tileComp->cbW + 1].flags
2415
+ & jpxCoeffSignificant) &&
2416
+ !(coeff1[2 * tileComp->cbW + 1].flags
2417
+ & jpxCoeffSignificant) &&
2418
+ !(coeff1[3 * tileComp->cbW + 1].flags
2419
+ & jpxCoeffSignificant))) &&
2420
+ (x == cb->x0 || y0+4 == cb->y1 ||
2421
+ !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
2422
+ (y0+4 == cb->y1 ||
2423
+ !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
2424
+ (x == cb->x1 - 1 || y0+4 == cb->y1 ||
2425
+ !(coeff1[4 * tileComp->cbW + 1].flags
2426
+ & jpxCoeffSignificant))) {
2427
+ if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
2428
+ y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2429
+ y1 = (y1 << 1) |
2430
+ cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2431
+ for (y2 = 0, coeff = coeff1;
2432
+ y2 < y1;
2433
+ ++y2, coeff += tileComp->cbW) {
2434
+ ++coeff->len;
2435
+ }
2436
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2437
+ coeff->mag = (coeff->mag << 1) | 1;
2438
+ ++coeff->len;
2439
+ cx = signContext[2][2][0];
2440
+ xorBit = signContext[2][2][1];
2441
+ if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2442
+ coeff->flags |= jpxCoeffSign;
2443
+ }
2444
+ ++y1;
2445
+ } else {
2446
+ for (y1 = 0, coeff = coeff1;
2447
+ y1 < 4;
2448
+ ++y1, coeff += tileComp->cbW) {
2449
+ ++coeff->len;
2450
+ }
2451
+ y1 = 4;
2452
+ }
2453
+ }
2454
+ for (coeff = &coeff1[y1 << tileComp->codeBlockW];
2455
+ y1 < 4 && y0 + y1 < cb->y1;
2456
+ ++y1, coeff += tileComp->cbW) {
2457
+ if (!(coeff->flags & jpxCoeffTouched)) {
2458
+ horiz = vert = diag = 0;
2459
+ horizSign = vertSign = 2;
2460
+ if (x > cb->x0) {
2461
+ if (coeff[-1].flags & jpxCoeffSignificant) {
2462
+ ++horiz;
2463
+ horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
2464
+ }
2465
+ if (y0+y1 > cb->y0) {
2466
+ diag += (coeff[-(int)tileComp->cbW - 1].flags
2467
+ >> jpxCoeffSignificantB) & 1;
2468
+ }
2469
+ if (y0+y1 < cb->y1 - 1) {
2470
+ diag += (coeff[tileComp->cbW - 1].flags
2471
+ >> jpxCoeffSignificantB) & 1;
2472
+ }
2473
+ }
2474
+ if (x < cb->x1 - 1) {
2475
+ if (coeff[1].flags & jpxCoeffSignificant) {
2476
+ ++horiz;
2477
+ horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2478
+ }
2479
+ if (y0+y1 > cb->y0) {
2480
+ diag += (coeff[-(int)tileComp->cbW + 1].flags
2481
+ >> jpxCoeffSignificantB) & 1;
2482
+ }
2483
+ if (y0+y1 < cb->y1 - 1) {
2484
+ diag += (coeff[tileComp->cbW + 1].flags
2485
+ >> jpxCoeffSignificantB) & 1;
2486
+ }
2487
+ }
2488
+ if (y0+y1 > cb->y0) {
2489
+ if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
2490
+ ++vert;
2491
+ vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
2492
+ ? -1 : 1;
2493
+ }
2494
+ }
2495
+ if (y0+y1 < cb->y1 - 1) {
2496
+ if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2497
+ ++vert;
2498
+ vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2499
+ ? -1 : 1;
2500
+ }
2501
+ }
2502
+ cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2503
+ if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2504
+ coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2505
+ coeff->mag = (coeff->mag << 1) | 1;
2506
+ cx = signContext[horizSign][vertSign][0];
2507
+ xorBit = signContext[horizSign][vertSign][1];
2508
+ if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2509
+ coeff->flags |= jpxCoeffSign;
2510
+ }
2511
+ }
2512
+ ++coeff->len;
2513
+ } else {
2514
+ coeff->flags &= ~jpxCoeffTouched;
2515
+ }
2516
+ }
2517
+ }
2518
+ }
2519
+ cb->nextPass = jpxPassSigProp;
2520
+ break;
2521
+ }
2522
+ }
2523
+
2524
+ cb->arithDecoder->cleanup();
2525
+ return gTrue;
2526
+ }
2527
+
2528
+ // Inverse quantization, and wavelet transform (IDWT). This also does
2529
+ // the initial shift to convert to fixed point format.
2530
+ void JPXStream::inverseTransform(JPXTileComp *tileComp) {
2531
+ JPXResLevel *resLevel;
2532
+ JPXPrecinct *precinct;
2533
+ JPXSubband *subband;
2534
+ JPXCodeBlock *cb;
2535
+ JPXCoeff *coeff0, *coeff;
2536
+ Guint qStyle, guard, eps, shift;
2537
+ int shift2;
2538
+ double mu;
2539
+ int val;
2540
+ int *dataPtr;
2541
+ Guint nx0, ny0, nx1, ny1;
2542
+ Guint r, cbX, cbY, x, y;
2543
+
2544
+ cover(68);
2545
+
2546
+ //----- (NL)LL subband (resolution level 0)
2547
+
2548
+ resLevel = &tileComp->resLevels[0];
2549
+ precinct = &resLevel->precincts[0];
2550
+ subband = &precinct->subbands[0];
2551
+
2552
+ // i-quant parameters
2553
+ qStyle = tileComp->quantStyle & 0x1f;
2554
+ guard = (tileComp->quantStyle >> 5) & 7;
2555
+ if (qStyle == 0) {
2556
+ cover(69);
2557
+ eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
2558
+ shift = guard + eps - 1;
2559
+ mu = 0; // make gcc happy
2560
+ } else {
2561
+ cover(70);
2562
+ shift = guard - 1 + tileComp->prec;
2563
+ mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
2564
+ }
2565
+ if (tileComp->transform == 0) {
2566
+ cover(71);
2567
+ shift += fracBits;
2568
+ }
2569
+
2570
+ // copy (NL)LL into the upper-left corner of the data array, doing
2571
+ // the fixed point adjustment and dequantization along the way
2572
+ cb = subband->cbs;
2573
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2574
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2575
+ for (y = cb->y0, coeff0 = cb->coeffs;
2576
+ y < cb->y1;
2577
+ ++y, coeff0 += tileComp->cbW) {
2578
+ dataPtr = &tileComp->data[(y - subband->y0)
2579
+ * (tileComp->x1 - tileComp->x0)
2580
+ + (cb->x0 - subband->x0)];
2581
+ for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2582
+ val = (int)coeff->mag;
2583
+ if (val != 0) {
2584
+ shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2585
+ if (shift2 > 0) {
2586
+ cover(94);
2587
+ val = (val << shift2) + (1 << (shift2 - 1));
2588
+ } else {
2589
+ cover(95);
2590
+ val >>= -shift2;
2591
+ }
2592
+ if (qStyle == 0) {
2593
+ cover(96);
2594
+ if (tileComp->transform == 0) {
2595
+ cover(97);
2596
+ val &= -1 << fracBits;
2597
+ }
2598
+ } else {
2599
+ cover(98);
2600
+ val = (int)((double)val * mu);
2601
+ }
2602
+ if (coeff->flags & jpxCoeffSign) {
2603
+ cover(99);
2604
+ val = -val;
2605
+ }
2606
+ }
2607
+ *dataPtr++ = val;
2608
+ }
2609
+ }
2610
+ ++cb;
2611
+ }
2612
+ }
2613
+
2614
+ //----- IDWT for each level
2615
+
2616
+ for (r = 1; r <= tileComp->nDecompLevels; ++r) {
2617
+ resLevel = &tileComp->resLevels[r];
2618
+
2619
+ // (n)LL is already in the upper-left corner of the
2620
+ // tile-component data array -- interleave with (n)HL/LH/HH
2621
+ // and inverse transform to get (n-1)LL, which will be stored
2622
+ // in the upper-left corner of the tile-component data array
2623
+ if (r == tileComp->nDecompLevels) {
2624
+ cover(72);
2625
+ nx0 = tileComp->x0;
2626
+ ny0 = tileComp->y0;
2627
+ nx1 = tileComp->x1;
2628
+ ny1 = tileComp->y1;
2629
+ } else {
2630
+ cover(73);
2631
+ nx0 = tileComp->resLevels[r+1].x0;
2632
+ ny0 = tileComp->resLevels[r+1].y0;
2633
+ nx1 = tileComp->resLevels[r+1].x1;
2634
+ ny1 = tileComp->resLevels[r+1].y1;
2635
+ }
2636
+ inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
2637
+ }
2638
+ }
2639
+
2640
+ // Do one level of the inverse transform:
2641
+ // - take (n)LL from the tile-component data array
2642
+ // - take (n)HL/LH/HH from <resLevel>
2643
+ // - leave the resulting (n-1)LL in the tile-component data array
2644
+ void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
2645
+ Guint r, JPXResLevel *resLevel,
2646
+ Guint nx0, Guint ny0,
2647
+ Guint nx1, Guint ny1) {
2648
+ JPXPrecinct *precinct;
2649
+ JPXSubband *subband;
2650
+ JPXCodeBlock *cb;
2651
+ JPXCoeff *coeff0, *coeff;
2652
+ Guint qStyle, guard, eps, shift, t;
2653
+ int shift2;
2654
+ double mu;
2655
+ int val;
2656
+ int *dataPtr;
2657
+ Guint xo, yo;
2658
+ Guint x, y, sb, cbX, cbY;
2659
+ int xx, yy;
2660
+
2661
+ //----- interleave
2662
+
2663
+ // spread out LL
2664
+ for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
2665
+ for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
2666
+ tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
2667
+ + (2 * xx - nx0)] =
2668
+ tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
2669
+ + (xx - resLevel->x0)];
2670
+ }
2671
+ }
2672
+
2673
+ // i-quant parameters
2674
+ qStyle = tileComp->quantStyle & 0x1f;
2675
+ guard = (tileComp->quantStyle >> 5) & 7;
2676
+
2677
+ // interleave HL/LH/HH
2678
+ precinct = &resLevel->precincts[0];
2679
+ for (sb = 0; sb < 3; ++sb) {
2680
+
2681
+ // i-quant parameters
2682
+ if (qStyle == 0) {
2683
+ cover(100);
2684
+ eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
2685
+ shift = guard + eps - 1;
2686
+ mu = 0; // make gcc happy
2687
+ } else {
2688
+ cover(101);
2689
+ shift = guard + tileComp->prec;
2690
+ if (sb == 2) {
2691
+ cover(102);
2692
+ ++shift;
2693
+ }
2694
+ t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
2695
+ mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
2696
+ }
2697
+ if (tileComp->transform == 0) {
2698
+ cover(103);
2699
+ shift += fracBits;
2700
+ }
2701
+
2702
+ // copy the subband coefficients into the data array, doing the
2703
+ // fixed point adjustment and dequantization along the way
2704
+ xo = (sb & 1) ? 0 : 1;
2705
+ yo = (sb > 0) ? 1 : 0;
2706
+ subband = &precinct->subbands[sb];
2707
+ cb = subband->cbs;
2708
+ for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2709
+ for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2710
+ for (y = cb->y0, coeff0 = cb->coeffs;
2711
+ y < cb->y1;
2712
+ ++y, coeff0 += tileComp->cbW) {
2713
+ dataPtr = &tileComp->data[(2 * y + yo - ny0)
2714
+ * (tileComp->x1 - tileComp->x0)
2715
+ + (2 * cb->x0 + xo - nx0)];
2716
+ for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2717
+ val = (int)coeff->mag;
2718
+ if (val != 0) {
2719
+ shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2720
+ if (shift2 > 0) {
2721
+ cover(74);
2722
+ val = (val << shift2) + (1 << (shift2 - 1));
2723
+ } else {
2724
+ cover(75);
2725
+ val >>= -shift2;
2726
+ }
2727
+ if (qStyle == 0) {
2728
+ cover(76);
2729
+ if (tileComp->transform == 0) {
2730
+ val &= -1 << fracBits;
2731
+ }
2732
+ } else {
2733
+ cover(77);
2734
+ val = (int)((double)val * mu);
2735
+ }
2736
+ if (coeff->flags & jpxCoeffSign) {
2737
+ cover(78);
2738
+ val = -val;
2739
+ }
2740
+ }
2741
+ *dataPtr = val;
2742
+ dataPtr += 2;
2743
+ }
2744
+ }
2745
+ ++cb;
2746
+ }
2747
+ }
2748
+ }
2749
+
2750
+ //----- horizontal (row) transforms
2751
+ dataPtr = tileComp->data;
2752
+ for (y = 0; y < ny1 - ny0; ++y) {
2753
+ inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
2754
+ dataPtr += tileComp->x1 - tileComp->x0;
2755
+ }
2756
+
2757
+ //----- vertical (column) transforms
2758
+ dataPtr = tileComp->data;
2759
+ for (x = 0; x < nx1 - nx0; ++x) {
2760
+ inverseTransform1D(tileComp, dataPtr,
2761
+ tileComp->x1 - tileComp->x0, ny0, ny1);
2762
+ ++dataPtr;
2763
+ }
2764
+ }
2765
+
2766
+ void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
2767
+ int *data, Guint stride,
2768
+ Guint i0, Guint i1) {
2769
+ int *buf;
2770
+ Guint offset, end, i;
2771
+
2772
+ //----- special case for length = 1
2773
+ if (i1 - i0 == 1) {
2774
+ cover(79);
2775
+ if (i0 & 1) {
2776
+ cover(104);
2777
+ *data >>= 1;
2778
+ }
2779
+
2780
+ } else {
2781
+ cover(80);
2782
+
2783
+ // choose an offset: this makes even buf[] indexes correspond to
2784
+ // odd values of i, and vice versa
2785
+ offset = 3 + (i0 & 1);
2786
+ end = offset + i1 - i0;
2787
+
2788
+ //----- gather
2789
+ buf = tileComp->buf;
2790
+ for (i = 0; i < i1 - i0; ++i) {
2791
+ buf[offset + i] = data[i * stride];
2792
+ }
2793
+
2794
+ //----- extend right
2795
+ buf[end] = buf[end - 2];
2796
+ if (i1 - i0 == 2) {
2797
+ cover(81);
2798
+ buf[end+1] = buf[offset + 1];
2799
+ buf[end+2] = buf[offset];
2800
+ buf[end+3] = buf[offset + 1];
2801
+ } else {
2802
+ cover(82);
2803
+ buf[end+1] = buf[end - 3];
2804
+ if (i1 - i0 == 3) {
2805
+ cover(105);
2806
+ buf[end+2] = buf[offset + 1];
2807
+ buf[end+3] = buf[offset + 2];
2808
+ } else {
2809
+ cover(106);
2810
+ buf[end+2] = buf[end - 4];
2811
+ if (i1 - i0 == 4) {
2812
+ cover(107);
2813
+ buf[end+3] = buf[offset + 1];
2814
+ } else {
2815
+ cover(108);
2816
+ buf[end+3] = buf[end - 5];
2817
+ }
2818
+ }
2819
+ }
2820
+
2821
+ //----- extend left
2822
+ buf[offset - 1] = buf[offset + 1];
2823
+ buf[offset - 2] = buf[offset + 2];
2824
+ buf[offset - 3] = buf[offset + 3];
2825
+ if (offset == 4) {
2826
+ cover(83);
2827
+ buf[0] = buf[offset + 4];
2828
+ }
2829
+
2830
+ //----- 9-7 irreversible filter
2831
+
2832
+ if (tileComp->transform == 0) {
2833
+ cover(84);
2834
+ // step 1 (even)
2835
+ for (i = 1; i <= end + 2; i += 2) {
2836
+ buf[i] = (int)(idwtKappa * buf[i]);
2837
+ }
2838
+ // step 2 (odd)
2839
+ for (i = 0; i <= end + 3; i += 2) {
2840
+ buf[i] = (int)(idwtIKappa * buf[i]);
2841
+ }
2842
+ // step 3 (even)
2843
+ for (i = 1; i <= end + 2; i += 2) {
2844
+ buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
2845
+ }
2846
+ // step 4 (odd)
2847
+ for (i = 2; i <= end + 1; i += 2) {
2848
+ buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
2849
+ }
2850
+ // step 5 (even)
2851
+ for (i = 3; i <= end; i += 2) {
2852
+ buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
2853
+ }
2854
+ // step 6 (odd)
2855
+ for (i = 4; i <= end - 1; i += 2) {
2856
+ buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
2857
+ }
2858
+
2859
+ //----- 5-3 reversible filter
2860
+
2861
+ } else {
2862
+ cover(85);
2863
+ // step 1 (even)
2864
+ for (i = 3; i <= end; i += 2) {
2865
+ buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
2866
+ }
2867
+ // step 2 (odd)
2868
+ for (i = 4; i < end; i += 2) {
2869
+ buf[i] += (buf[i-1] + buf[i+1]) >> 1;
2870
+ }
2871
+ }
2872
+
2873
+ //----- scatter
2874
+ for (i = 0; i < i1 - i0; ++i) {
2875
+ data[i * stride] = buf[offset + i];
2876
+ }
2877
+ }
2878
+ }
2879
+
2880
+ // Inverse multi-component transform and DC level shift. This also
2881
+ // converts fixed point samples back to integers.
2882
+ GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
2883
+ JPXTileComp *tileComp;
2884
+ int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal;
2885
+ int *dataPtr;
2886
+ Guint j, comp, x, y;
2887
+
2888
+ //----- inverse multi-component transform
2889
+
2890
+ if (tile->multiComp == 1) {
2891
+ cover(86);
2892
+ if (img.nComps < 3 ||
2893
+ tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
2894
+ tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
2895
+ tile->tileComps[1].hSep != tile->tileComps[2].hSep ||
2896
+ tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
2897
+ return gFalse;
2898
+ }
2899
+
2900
+ // inverse irreversible multiple component transform
2901
+ if (tile->tileComps[0].transform == 0) {
2902
+ cover(87);
2903
+ j = 0;
2904
+ for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2905
+ for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2906
+ d0 = tile->tileComps[0].data[j];
2907
+ d1 = tile->tileComps[1].data[j];
2908
+ d2 = tile->tileComps[2].data[j];
2909
+ tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
2910
+ tile->tileComps[1].data[j] =
2911
+ (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
2912
+ tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
2913
+ ++j;
2914
+ }
2915
+ }
2916
+
2917
+ // inverse reversible multiple component transform
2918
+ } else {
2919
+ cover(88);
2920
+ j = 0;
2921
+ for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2922
+ for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2923
+ d0 = tile->tileComps[0].data[j];
2924
+ d1 = tile->tileComps[1].data[j];
2925
+ d2 = tile->tileComps[2].data[j];
2926
+ tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2);
2927
+ tile->tileComps[0].data[j] = d2 + t;
2928
+ tile->tileComps[2].data[j] = d1 + t;
2929
+ ++j;
2930
+ }
2931
+ }
2932
+ }
2933
+ }
2934
+
2935
+ //----- DC level shift
2936
+ for (comp = 0; comp < img.nComps; ++comp) {
2937
+ tileComp = &tile->tileComps[comp];
2938
+
2939
+ // signed: clip
2940
+ if (tileComp->sgned) {
2941
+ cover(89);
2942
+ minVal = -(1 << (tileComp->prec - 1));
2943
+ maxVal = (1 << (tileComp->prec - 1)) - 1;
2944
+ dataPtr = tileComp->data;
2945
+ for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2946
+ for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2947
+ coeff = *dataPtr;
2948
+ if (tileComp->transform == 0) {
2949
+ cover(109);
2950
+ coeff >>= fracBits;
2951
+ }
2952
+ if (coeff < minVal) {
2953
+ cover(110);
2954
+ coeff = minVal;
2955
+ } else if (coeff > maxVal) {
2956
+ cover(111);
2957
+ coeff = maxVal;
2958
+ }
2959
+ *dataPtr++ = coeff;
2960
+ }
2961
+ }
2962
+
2963
+ // unsigned: inverse DC level shift and clip
2964
+ } else {
2965
+ cover(90);
2966
+ maxVal = (1 << tileComp->prec) - 1;
2967
+ zeroVal = 1 << (tileComp->prec - 1);
2968
+ dataPtr = tileComp->data;
2969
+ for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2970
+ for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2971
+ coeff = *dataPtr;
2972
+ if (tileComp->transform == 0) {
2973
+ cover(112);
2974
+ coeff >>= fracBits;
2975
+ }
2976
+ coeff += zeroVal;
2977
+ if (coeff < 0) {
2978
+ cover(113);
2979
+ coeff = 0;
2980
+ } else if (coeff > maxVal) {
2981
+ cover(114);
2982
+ coeff = maxVal;
2983
+ }
2984
+ *dataPtr++ = coeff;
2985
+ }
2986
+ }
2987
+ }
2988
+ }
2989
+
2990
+ return gTrue;
2991
+ }
2992
+
2993
+ GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
2994
+ Guint len, lenH;
2995
+
2996
+ if (!readULong(&len) ||
2997
+ !readULong(boxType)) {
2998
+ return gFalse;
2999
+ }
3000
+ if (len == 1) {
3001
+ if (!readULong(&lenH) || !readULong(&len)) {
3002
+ return gFalse;
3003
+ }
3004
+ if (lenH) {
3005
+ error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
3006
+ return gFalse;
3007
+ }
3008
+ *boxLen = len;
3009
+ *dataLen = len - 16;
3010
+ } else if (len == 0) {
3011
+ *boxLen = 0;
3012
+ *dataLen = 0;
3013
+ } else {
3014
+ *boxLen = len;
3015
+ *dataLen = len - 8;
3016
+ }
3017
+ return gTrue;
3018
+ }
3019
+
3020
+ int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
3021
+ int c;
3022
+
3023
+ do {
3024
+ do {
3025
+ if ((c = str->getChar()) == EOF) {
3026
+ return gFalse;
3027
+ }
3028
+ } while (c != 0xff);
3029
+ do {
3030
+ if ((c = str->getChar()) == EOF) {
3031
+ return gFalse;
3032
+ }
3033
+ } while (c == 0xff);
3034
+ } while (c == 0x00);
3035
+ *segType = c;
3036
+ if ((c >= 0x30 && c <= 0x3f) ||
3037
+ c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
3038
+ *segLen = 0;
3039
+ return gTrue;
3040
+ }
3041
+ return readUWord(segLen);
3042
+ }
3043
+
3044
+ GBool JPXStream::readUByte(Guint *x) {
3045
+ int c0;
3046
+
3047
+ if ((c0 = str->getChar()) == EOF) {
3048
+ return gFalse;
3049
+ }
3050
+ *x = (Guint)c0;
3051
+ return gTrue;
3052
+ }
3053
+
3054
+ GBool JPXStream::readByte(int *x) {
3055
+ int c0;
3056
+
3057
+ if ((c0 = str->getChar()) == EOF) {
3058
+ return gFalse;
3059
+ }
3060
+ *x = c0;
3061
+ if (c0 & 0x80) {
3062
+ *x |= -1 - 0xff;
3063
+ }
3064
+ return gTrue;
3065
+ }
3066
+
3067
+ GBool JPXStream::readUWord(Guint *x) {
3068
+ int c0, c1;
3069
+
3070
+ if ((c0 = str->getChar()) == EOF ||
3071
+ (c1 = str->getChar()) == EOF) {
3072
+ return gFalse;
3073
+ }
3074
+ *x = (Guint)((c0 << 8) | c1);
3075
+ return gTrue;
3076
+ }
3077
+
3078
+ GBool JPXStream::readULong(Guint *x) {
3079
+ int c0, c1, c2, c3;
3080
+
3081
+ if ((c0 = str->getChar()) == EOF ||
3082
+ (c1 = str->getChar()) == EOF ||
3083
+ (c2 = str->getChar()) == EOF ||
3084
+ (c3 = str->getChar()) == EOF) {
3085
+ return gFalse;
3086
+ }
3087
+ *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3088
+ return gTrue;
3089
+ }
3090
+
3091
+ GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
3092
+ int y, c, i;
3093
+
3094
+ y = 0;
3095
+ for (i = 0; i < nBytes; ++i) {
3096
+ if ((c = str->getChar()) == EOF) {
3097
+ return gFalse;
3098
+ }
3099
+ y = (y << 8) + c;
3100
+ }
3101
+ if (signd) {
3102
+ if (y & (1 << (8 * nBytes - 1))) {
3103
+ y |= -1 << (8 * nBytes);
3104
+ }
3105
+ }
3106
+ *x = y;
3107
+ return gTrue;
3108
+ }
3109
+
3110
+ GBool JPXStream::readBits(int nBits, Guint *x) {
3111
+ int c;
3112
+
3113
+ while (bitBufLen < nBits) {
3114
+ if (byteCount == 0 || (c = str->getChar()) == EOF) {
3115
+ return gFalse;
3116
+ }
3117
+ --byteCount;
3118
+ if (bitBufSkip) {
3119
+ bitBuf = (bitBuf << 7) | (c & 0x7f);
3120
+ bitBufLen += 7;
3121
+ } else {
3122
+ bitBuf = (bitBuf << 8) | (c & 0xff);
3123
+ bitBufLen += 8;
3124
+ }
3125
+ bitBufSkip = c == 0xff;
3126
+ }
3127
+ *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
3128
+ bitBufLen -= nBits;
3129
+ return gTrue;
3130
+ }
3131
+
3132
+ void JPXStream::startBitBuf(Guint byteCountA) {
3133
+ bitBufLen = 0;
3134
+ bitBufSkip = gFalse;
3135
+ byteCount = byteCountA;
3136
+ }
3137
+
3138
+ Guint JPXStream::finishBitBuf() {
3139
+ if (bitBufSkip) {
3140
+ str->getChar();
3141
+ --byteCount;
3142
+ }
3143
+ return byteCount;
3144
+ }