jbig2.js 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576
  1. /* Copyright 2012 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { BaseException, shadow } from "../shared/util.js";
  16. import { log2, readInt8, readUint16, readUint32 } from "./core_utils.js";
  17. import { ArithmeticDecoder } from "./arithmetic_decoder.js";
  18. import { CCITTFaxDecoder } from "./ccitt.js";
  19. class Jbig2Error extends BaseException {
  20. constructor(msg) {
  21. super(`JBIG2 error: ${msg}`, "Jbig2Error");
  22. }
  23. }
  24. // Utility data structures
  25. class ContextCache {
  26. getContexts(id) {
  27. if (id in this) {
  28. return this[id];
  29. }
  30. return (this[id] = new Int8Array(1 << 16));
  31. }
  32. }
  33. class DecodingContext {
  34. constructor(data, start, end) {
  35. this.data = data;
  36. this.start = start;
  37. this.end = end;
  38. }
  39. get decoder() {
  40. const decoder = new ArithmeticDecoder(this.data, this.start, this.end);
  41. return shadow(this, "decoder", decoder);
  42. }
  43. get contextCache() {
  44. const cache = new ContextCache();
  45. return shadow(this, "contextCache", cache);
  46. }
  47. }
  48. // Annex A. Arithmetic Integer Decoding Procedure
  49. // A.2 Procedure for decoding values
  50. function decodeInteger(contextCache, procedure, decoder) {
  51. const contexts = contextCache.getContexts(procedure);
  52. let prev = 1;
  53. function readBits(length) {
  54. let v = 0;
  55. for (let i = 0; i < length; i++) {
  56. const bit = decoder.readBit(contexts, prev);
  57. prev = prev < 256 ? (prev << 1) | bit : (((prev << 1) | bit) & 511) | 256;
  58. v = (v << 1) | bit;
  59. }
  60. return v >>> 0;
  61. }
  62. const sign = readBits(1);
  63. // prettier-ignore
  64. /* eslint-disable no-nested-ternary */
  65. const value = readBits(1) ?
  66. (readBits(1) ?
  67. (readBits(1) ?
  68. (readBits(1) ?
  69. (readBits(1) ?
  70. (readBits(32) + 4436) :
  71. readBits(12) + 340) :
  72. readBits(8) + 84) :
  73. readBits(6) + 20) :
  74. readBits(4) + 4) :
  75. readBits(2);
  76. /* eslint-enable no-nested-ternary */
  77. if (sign === 0) {
  78. return value;
  79. } else if (value > 0) {
  80. return -value;
  81. }
  82. return null;
  83. }
  84. // A.3 The IAID decoding procedure
  85. function decodeIAID(contextCache, decoder, codeLength) {
  86. const contexts = contextCache.getContexts("IAID");
  87. let prev = 1;
  88. for (let i = 0; i < codeLength; i++) {
  89. const bit = decoder.readBit(contexts, prev);
  90. prev = (prev << 1) | bit;
  91. }
  92. if (codeLength < 31) {
  93. return prev & ((1 << codeLength) - 1);
  94. }
  95. return prev & 0x7fffffff;
  96. }
  97. // 7.3 Segment types
  98. const SegmentTypes = [
  99. "SymbolDictionary",
  100. null,
  101. null,
  102. null,
  103. "IntermediateTextRegion",
  104. null,
  105. "ImmediateTextRegion",
  106. "ImmediateLosslessTextRegion",
  107. null,
  108. null,
  109. null,
  110. null,
  111. null,
  112. null,
  113. null,
  114. null,
  115. "PatternDictionary",
  116. null,
  117. null,
  118. null,
  119. "IntermediateHalftoneRegion",
  120. null,
  121. "ImmediateHalftoneRegion",
  122. "ImmediateLosslessHalftoneRegion",
  123. null,
  124. null,
  125. null,
  126. null,
  127. null,
  128. null,
  129. null,
  130. null,
  131. null,
  132. null,
  133. null,
  134. null,
  135. "IntermediateGenericRegion",
  136. null,
  137. "ImmediateGenericRegion",
  138. "ImmediateLosslessGenericRegion",
  139. "IntermediateGenericRefinementRegion",
  140. null,
  141. "ImmediateGenericRefinementRegion",
  142. "ImmediateLosslessGenericRefinementRegion",
  143. null,
  144. null,
  145. null,
  146. null,
  147. "PageInformation",
  148. "EndOfPage",
  149. "EndOfStripe",
  150. "EndOfFile",
  151. "Profiles",
  152. "Tables",
  153. null,
  154. null,
  155. null,
  156. null,
  157. null,
  158. null,
  159. null,
  160. null,
  161. "Extension",
  162. ];
  163. const CodingTemplates = [
  164. [
  165. { x: -1, y: -2 },
  166. { x: 0, y: -2 },
  167. { x: 1, y: -2 },
  168. { x: -2, y: -1 },
  169. { x: -1, y: -1 },
  170. { x: 0, y: -1 },
  171. { x: 1, y: -1 },
  172. { x: 2, y: -1 },
  173. { x: -4, y: 0 },
  174. { x: -3, y: 0 },
  175. { x: -2, y: 0 },
  176. { x: -1, y: 0 },
  177. ],
  178. [
  179. { x: -1, y: -2 },
  180. { x: 0, y: -2 },
  181. { x: 1, y: -2 },
  182. { x: 2, y: -2 },
  183. { x: -2, y: -1 },
  184. { x: -1, y: -1 },
  185. { x: 0, y: -1 },
  186. { x: 1, y: -1 },
  187. { x: 2, y: -1 },
  188. { x: -3, y: 0 },
  189. { x: -2, y: 0 },
  190. { x: -1, y: 0 },
  191. ],
  192. [
  193. { x: -1, y: -2 },
  194. { x: 0, y: -2 },
  195. { x: 1, y: -2 },
  196. { x: -2, y: -1 },
  197. { x: -1, y: -1 },
  198. { x: 0, y: -1 },
  199. { x: 1, y: -1 },
  200. { x: -2, y: 0 },
  201. { x: -1, y: 0 },
  202. ],
  203. [
  204. { x: -3, y: -1 },
  205. { x: -2, y: -1 },
  206. { x: -1, y: -1 },
  207. { x: 0, y: -1 },
  208. { x: 1, y: -1 },
  209. { x: -4, y: 0 },
  210. { x: -3, y: 0 },
  211. { x: -2, y: 0 },
  212. { x: -1, y: 0 },
  213. ],
  214. ];
  215. const RefinementTemplates = [
  216. {
  217. coding: [
  218. { x: 0, y: -1 },
  219. { x: 1, y: -1 },
  220. { x: -1, y: 0 },
  221. ],
  222. reference: [
  223. { x: 0, y: -1 },
  224. { x: 1, y: -1 },
  225. { x: -1, y: 0 },
  226. { x: 0, y: 0 },
  227. { x: 1, y: 0 },
  228. { x: -1, y: 1 },
  229. { x: 0, y: 1 },
  230. { x: 1, y: 1 },
  231. ],
  232. },
  233. {
  234. coding: [
  235. { x: -1, y: -1 },
  236. { x: 0, y: -1 },
  237. { x: 1, y: -1 },
  238. { x: -1, y: 0 },
  239. ],
  240. reference: [
  241. { x: 0, y: -1 },
  242. { x: -1, y: 0 },
  243. { x: 0, y: 0 },
  244. { x: 1, y: 0 },
  245. { x: 0, y: 1 },
  246. { x: 1, y: 1 },
  247. ],
  248. },
  249. ];
  250. // See 6.2.5.7 Decoding the bitmap.
  251. const ReusedContexts = [
  252. 0x9b25, // 10011 0110010 0101
  253. 0x0795, // 0011 110010 101
  254. 0x00e5, // 001 11001 01
  255. 0x0195, // 011001 0101
  256. ];
  257. const RefinementReusedContexts = [
  258. 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
  259. 0x0008, // '0000' + '001000'
  260. ];
  261. function decodeBitmapTemplate0(width, height, decodingContext) {
  262. const decoder = decodingContext.decoder;
  263. const contexts = decodingContext.contextCache.getContexts("GB");
  264. const bitmap = [];
  265. let contextLabel, i, j, pixel, row, row1, row2;
  266. // ...ooooo....
  267. // ..ooooooo... Context template for current pixel (X)
  268. // .ooooX...... (concatenate values of 'o'-pixels to get contextLabel)
  269. const OLD_PIXEL_MASK = 0x7bf7; // 01111 0111111 0111
  270. for (i = 0; i < height; i++) {
  271. row = bitmap[i] = new Uint8Array(width);
  272. row1 = i < 1 ? row : bitmap[i - 1];
  273. row2 = i < 2 ? row : bitmap[i - 2];
  274. // At the beginning of each row:
  275. // Fill contextLabel with pixels that are above/right of (X)
  276. contextLabel =
  277. (row2[0] << 13) |
  278. (row2[1] << 12) |
  279. (row2[2] << 11) |
  280. (row1[0] << 7) |
  281. (row1[1] << 6) |
  282. (row1[2] << 5) |
  283. (row1[3] << 4);
  284. for (j = 0; j < width; j++) {
  285. row[j] = pixel = decoder.readBit(contexts, contextLabel);
  286. // At each pixel: Clear contextLabel pixels that are shifted
  287. // out of the context, then add new ones.
  288. contextLabel =
  289. ((contextLabel & OLD_PIXEL_MASK) << 1) |
  290. (j + 3 < width ? row2[j + 3] << 11 : 0) |
  291. (j + 4 < width ? row1[j + 4] << 4 : 0) |
  292. pixel;
  293. }
  294. }
  295. return bitmap;
  296. }
  297. // 6.2 Generic Region Decoding Procedure
  298. function decodeBitmap(
  299. mmr,
  300. width,
  301. height,
  302. templateIndex,
  303. prediction,
  304. skip,
  305. at,
  306. decodingContext
  307. ) {
  308. if (mmr) {
  309. const input = new Reader(
  310. decodingContext.data,
  311. decodingContext.start,
  312. decodingContext.end
  313. );
  314. return decodeMMRBitmap(input, width, height, false);
  315. }
  316. // Use optimized version for the most common case
  317. if (
  318. templateIndex === 0 &&
  319. !skip &&
  320. !prediction &&
  321. at.length === 4 &&
  322. at[0].x === 3 &&
  323. at[0].y === -1 &&
  324. at[1].x === -3 &&
  325. at[1].y === -1 &&
  326. at[2].x === 2 &&
  327. at[2].y === -2 &&
  328. at[3].x === -2 &&
  329. at[3].y === -2
  330. ) {
  331. return decodeBitmapTemplate0(width, height, decodingContext);
  332. }
  333. const useskip = !!skip;
  334. const template = CodingTemplates[templateIndex].concat(at);
  335. // Sorting is non-standard, and it is not required. But sorting increases
  336. // the number of template bits that can be reused from the previous
  337. // contextLabel in the main loop.
  338. template.sort(function (a, b) {
  339. return a.y - b.y || a.x - b.x;
  340. });
  341. const templateLength = template.length;
  342. const templateX = new Int8Array(templateLength);
  343. const templateY = new Int8Array(templateLength);
  344. const changingTemplateEntries = [];
  345. let reuseMask = 0,
  346. minX = 0,
  347. maxX = 0,
  348. minY = 0;
  349. let c, k;
  350. for (k = 0; k < templateLength; k++) {
  351. templateX[k] = template[k].x;
  352. templateY[k] = template[k].y;
  353. minX = Math.min(minX, template[k].x);
  354. maxX = Math.max(maxX, template[k].x);
  355. minY = Math.min(minY, template[k].y);
  356. // Check if the template pixel appears in two consecutive context labels,
  357. // so it can be reused. Otherwise, we add it to the list of changing
  358. // template entries.
  359. if (
  360. k < templateLength - 1 &&
  361. template[k].y === template[k + 1].y &&
  362. template[k].x === template[k + 1].x - 1
  363. ) {
  364. reuseMask |= 1 << (templateLength - 1 - k);
  365. } else {
  366. changingTemplateEntries.push(k);
  367. }
  368. }
  369. const changingEntriesLength = changingTemplateEntries.length;
  370. const changingTemplateX = new Int8Array(changingEntriesLength);
  371. const changingTemplateY = new Int8Array(changingEntriesLength);
  372. const changingTemplateBit = new Uint16Array(changingEntriesLength);
  373. for (c = 0; c < changingEntriesLength; c++) {
  374. k = changingTemplateEntries[c];
  375. changingTemplateX[c] = template[k].x;
  376. changingTemplateY[c] = template[k].y;
  377. changingTemplateBit[c] = 1 << (templateLength - 1 - k);
  378. }
  379. // Get the safe bounding box edges from the width, height, minX, maxX, minY
  380. const sbb_left = -minX;
  381. const sbb_top = -minY;
  382. const sbb_right = width - maxX;
  383. const pseudoPixelContext = ReusedContexts[templateIndex];
  384. let row = new Uint8Array(width);
  385. const bitmap = [];
  386. const decoder = decodingContext.decoder;
  387. const contexts = decodingContext.contextCache.getContexts("GB");
  388. let ltp = 0,
  389. j,
  390. i0,
  391. j0,
  392. contextLabel = 0,
  393. bit,
  394. shift;
  395. for (let i = 0; i < height; i++) {
  396. if (prediction) {
  397. const sltp = decoder.readBit(contexts, pseudoPixelContext);
  398. ltp ^= sltp;
  399. if (ltp) {
  400. bitmap.push(row); // duplicate previous row
  401. continue;
  402. }
  403. }
  404. row = new Uint8Array(row);
  405. bitmap.push(row);
  406. for (j = 0; j < width; j++) {
  407. if (useskip && skip[i][j]) {
  408. row[j] = 0;
  409. continue;
  410. }
  411. // Are we in the middle of a scanline, so we can reuse contextLabel
  412. // bits?
  413. if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
  414. // If yes, we can just shift the bits that are reusable and only
  415. // fetch the remaining ones.
  416. contextLabel = (contextLabel << 1) & reuseMask;
  417. for (k = 0; k < changingEntriesLength; k++) {
  418. i0 = i + changingTemplateY[k];
  419. j0 = j + changingTemplateX[k];
  420. bit = bitmap[i0][j0];
  421. if (bit) {
  422. bit = changingTemplateBit[k];
  423. contextLabel |= bit;
  424. }
  425. }
  426. } else {
  427. // compute the contextLabel from scratch
  428. contextLabel = 0;
  429. shift = templateLength - 1;
  430. for (k = 0; k < templateLength; k++, shift--) {
  431. j0 = j + templateX[k];
  432. if (j0 >= 0 && j0 < width) {
  433. i0 = i + templateY[k];
  434. if (i0 >= 0) {
  435. bit = bitmap[i0][j0];
  436. if (bit) {
  437. contextLabel |= bit << shift;
  438. }
  439. }
  440. }
  441. }
  442. }
  443. const pixel = decoder.readBit(contexts, contextLabel);
  444. row[j] = pixel;
  445. }
  446. }
  447. return bitmap;
  448. }
  449. // 6.3.2 Generic Refinement Region Decoding Procedure
  450. function decodeRefinement(
  451. width,
  452. height,
  453. templateIndex,
  454. referenceBitmap,
  455. offsetX,
  456. offsetY,
  457. prediction,
  458. at,
  459. decodingContext
  460. ) {
  461. let codingTemplate = RefinementTemplates[templateIndex].coding;
  462. if (templateIndex === 0) {
  463. codingTemplate = codingTemplate.concat([at[0]]);
  464. }
  465. const codingTemplateLength = codingTemplate.length;
  466. const codingTemplateX = new Int32Array(codingTemplateLength);
  467. const codingTemplateY = new Int32Array(codingTemplateLength);
  468. let k;
  469. for (k = 0; k < codingTemplateLength; k++) {
  470. codingTemplateX[k] = codingTemplate[k].x;
  471. codingTemplateY[k] = codingTemplate[k].y;
  472. }
  473. let referenceTemplate = RefinementTemplates[templateIndex].reference;
  474. if (templateIndex === 0) {
  475. referenceTemplate = referenceTemplate.concat([at[1]]);
  476. }
  477. const referenceTemplateLength = referenceTemplate.length;
  478. const referenceTemplateX = new Int32Array(referenceTemplateLength);
  479. const referenceTemplateY = new Int32Array(referenceTemplateLength);
  480. for (k = 0; k < referenceTemplateLength; k++) {
  481. referenceTemplateX[k] = referenceTemplate[k].x;
  482. referenceTemplateY[k] = referenceTemplate[k].y;
  483. }
  484. const referenceWidth = referenceBitmap[0].length;
  485. const referenceHeight = referenceBitmap.length;
  486. const pseudoPixelContext = RefinementReusedContexts[templateIndex];
  487. const bitmap = [];
  488. const decoder = decodingContext.decoder;
  489. const contexts = decodingContext.contextCache.getContexts("GR");
  490. let ltp = 0;
  491. for (let i = 0; i < height; i++) {
  492. if (prediction) {
  493. const sltp = decoder.readBit(contexts, pseudoPixelContext);
  494. ltp ^= sltp;
  495. if (ltp) {
  496. throw new Jbig2Error("prediction is not supported");
  497. }
  498. }
  499. const row = new Uint8Array(width);
  500. bitmap.push(row);
  501. for (let j = 0; j < width; j++) {
  502. let i0, j0;
  503. let contextLabel = 0;
  504. for (k = 0; k < codingTemplateLength; k++) {
  505. i0 = i + codingTemplateY[k];
  506. j0 = j + codingTemplateX[k];
  507. if (i0 < 0 || j0 < 0 || j0 >= width) {
  508. contextLabel <<= 1; // out of bound pixel
  509. } else {
  510. contextLabel = (contextLabel << 1) | bitmap[i0][j0];
  511. }
  512. }
  513. for (k = 0; k < referenceTemplateLength; k++) {
  514. i0 = i + referenceTemplateY[k] - offsetY;
  515. j0 = j + referenceTemplateX[k] - offsetX;
  516. if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
  517. contextLabel <<= 1; // out of bound pixel
  518. } else {
  519. contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
  520. }
  521. }
  522. const pixel = decoder.readBit(contexts, contextLabel);
  523. row[j] = pixel;
  524. }
  525. }
  526. return bitmap;
  527. }
  528. // 6.5.5 Decoding the symbol dictionary
  529. function decodeSymbolDictionary(
  530. huffman,
  531. refinement,
  532. symbols,
  533. numberOfNewSymbols,
  534. numberOfExportedSymbols,
  535. huffmanTables,
  536. templateIndex,
  537. at,
  538. refinementTemplateIndex,
  539. refinementAt,
  540. decodingContext,
  541. huffmanInput
  542. ) {
  543. if (huffman && refinement) {
  544. throw new Jbig2Error("symbol refinement with Huffman is not supported");
  545. }
  546. const newSymbols = [];
  547. let currentHeight = 0;
  548. let symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
  549. const decoder = decodingContext.decoder;
  550. const contextCache = decodingContext.contextCache;
  551. let tableB1, symbolWidths;
  552. if (huffman) {
  553. tableB1 = getStandardTable(1); // standard table B.1
  554. symbolWidths = [];
  555. symbolCodeLength = Math.max(symbolCodeLength, 1); // 6.5.8.2.3
  556. }
  557. while (newSymbols.length < numberOfNewSymbols) {
  558. const deltaHeight = huffman
  559. ? huffmanTables.tableDeltaHeight.decode(huffmanInput)
  560. : decodeInteger(contextCache, "IADH", decoder); // 6.5.6
  561. currentHeight += deltaHeight;
  562. let currentWidth = 0,
  563. totalWidth = 0;
  564. const firstSymbol = huffman ? symbolWidths.length : 0;
  565. while (true) {
  566. const deltaWidth = huffman
  567. ? huffmanTables.tableDeltaWidth.decode(huffmanInput)
  568. : decodeInteger(contextCache, "IADW", decoder); // 6.5.7
  569. if (deltaWidth === null) {
  570. break; // OOB
  571. }
  572. currentWidth += deltaWidth;
  573. totalWidth += currentWidth;
  574. let bitmap;
  575. if (refinement) {
  576. // 6.5.8.2 Refinement/aggregate-coded symbol bitmap
  577. const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder);
  578. if (numberOfInstances > 1) {
  579. bitmap = decodeTextRegion(
  580. huffman,
  581. refinement,
  582. currentWidth,
  583. currentHeight,
  584. 0,
  585. numberOfInstances,
  586. 1, // strip size
  587. symbols.concat(newSymbols),
  588. symbolCodeLength,
  589. 0, // transposed
  590. 0, // ds offset
  591. 1, // top left 7.4.3.1.1
  592. 0, // OR operator
  593. huffmanTables,
  594. refinementTemplateIndex,
  595. refinementAt,
  596. decodingContext,
  597. 0,
  598. huffmanInput
  599. );
  600. } else {
  601. const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
  602. const rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
  603. const rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
  604. const symbol =
  605. symbolId < symbols.length
  606. ? symbols[symbolId]
  607. : newSymbols[symbolId - symbols.length];
  608. bitmap = decodeRefinement(
  609. currentWidth,
  610. currentHeight,
  611. refinementTemplateIndex,
  612. symbol,
  613. rdx,
  614. rdy,
  615. false,
  616. refinementAt,
  617. decodingContext
  618. );
  619. }
  620. newSymbols.push(bitmap);
  621. } else if (huffman) {
  622. // Store only symbol width and decode a collective bitmap when the
  623. // height class is done.
  624. symbolWidths.push(currentWidth);
  625. } else {
  626. // 6.5.8.1 Direct-coded symbol bitmap
  627. bitmap = decodeBitmap(
  628. false,
  629. currentWidth,
  630. currentHeight,
  631. templateIndex,
  632. false,
  633. null,
  634. at,
  635. decodingContext
  636. );
  637. newSymbols.push(bitmap);
  638. }
  639. }
  640. if (huffman && !refinement) {
  641. // 6.5.9 Height class collective bitmap
  642. const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
  643. huffmanInput.byteAlign();
  644. let collectiveBitmap;
  645. if (bitmapSize === 0) {
  646. // Uncompressed collective bitmap
  647. collectiveBitmap = readUncompressedBitmap(
  648. huffmanInput,
  649. totalWidth,
  650. currentHeight
  651. );
  652. } else {
  653. // MMR collective bitmap
  654. const originalEnd = huffmanInput.end;
  655. const bitmapEnd = huffmanInput.position + bitmapSize;
  656. huffmanInput.end = bitmapEnd;
  657. collectiveBitmap = decodeMMRBitmap(
  658. huffmanInput,
  659. totalWidth,
  660. currentHeight,
  661. false
  662. );
  663. huffmanInput.end = originalEnd;
  664. huffmanInput.position = bitmapEnd;
  665. }
  666. const numberOfSymbolsDecoded = symbolWidths.length;
  667. if (firstSymbol === numberOfSymbolsDecoded - 1) {
  668. // collectiveBitmap is a single symbol.
  669. newSymbols.push(collectiveBitmap);
  670. } else {
  671. // Divide collectiveBitmap into symbols.
  672. let i,
  673. y,
  674. xMin = 0,
  675. xMax,
  676. bitmapWidth,
  677. symbolBitmap;
  678. for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) {
  679. bitmapWidth = symbolWidths[i];
  680. xMax = xMin + bitmapWidth;
  681. symbolBitmap = [];
  682. for (y = 0; y < currentHeight; y++) {
  683. symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
  684. }
  685. newSymbols.push(symbolBitmap);
  686. xMin = xMax;
  687. }
  688. }
  689. }
  690. }
  691. // 6.5.10 Exported symbols
  692. const exportedSymbols = [],
  693. flags = [];
  694. let currentFlag = false,
  695. i,
  696. ii;
  697. const totalSymbolsLength = symbols.length + numberOfNewSymbols;
  698. while (flags.length < totalSymbolsLength) {
  699. let runLength = huffman
  700. ? tableB1.decode(huffmanInput)
  701. : decodeInteger(contextCache, "IAEX", decoder);
  702. while (runLength--) {
  703. flags.push(currentFlag);
  704. }
  705. currentFlag = !currentFlag;
  706. }
  707. for (i = 0, ii = symbols.length; i < ii; i++) {
  708. if (flags[i]) {
  709. exportedSymbols.push(symbols[i]);
  710. }
  711. }
  712. for (let j = 0; j < numberOfNewSymbols; i++, j++) {
  713. if (flags[i]) {
  714. exportedSymbols.push(newSymbols[j]);
  715. }
  716. }
  717. return exportedSymbols;
  718. }
  719. function decodeTextRegion(
  720. huffman,
  721. refinement,
  722. width,
  723. height,
  724. defaultPixelValue,
  725. numberOfSymbolInstances,
  726. stripSize,
  727. inputSymbols,
  728. symbolCodeLength,
  729. transposed,
  730. dsOffset,
  731. referenceCorner,
  732. combinationOperator,
  733. huffmanTables,
  734. refinementTemplateIndex,
  735. refinementAt,
  736. decodingContext,
  737. logStripSize,
  738. huffmanInput
  739. ) {
  740. if (huffman && refinement) {
  741. throw new Jbig2Error("refinement with Huffman is not supported");
  742. }
  743. // Prepare bitmap
  744. const bitmap = [];
  745. let i, row;
  746. for (i = 0; i < height; i++) {
  747. row = new Uint8Array(width);
  748. if (defaultPixelValue) {
  749. for (let j = 0; j < width; j++) {
  750. row[j] = defaultPixelValue;
  751. }
  752. }
  753. bitmap.push(row);
  754. }
  755. const decoder = decodingContext.decoder;
  756. const contextCache = decodingContext.contextCache;
  757. let stripT = huffman
  758. ? -huffmanTables.tableDeltaT.decode(huffmanInput)
  759. : -decodeInteger(contextCache, "IADT", decoder); // 6.4.6
  760. let firstS = 0;
  761. i = 0;
  762. while (i < numberOfSymbolInstances) {
  763. const deltaT = huffman
  764. ? huffmanTables.tableDeltaT.decode(huffmanInput)
  765. : decodeInteger(contextCache, "IADT", decoder); // 6.4.6
  766. stripT += deltaT;
  767. const deltaFirstS = huffman
  768. ? huffmanTables.tableFirstS.decode(huffmanInput)
  769. : decodeInteger(contextCache, "IAFS", decoder); // 6.4.7
  770. firstS += deltaFirstS;
  771. let currentS = firstS;
  772. do {
  773. let currentT = 0; // 6.4.9
  774. if (stripSize > 1) {
  775. currentT = huffman
  776. ? huffmanInput.readBits(logStripSize)
  777. : decodeInteger(contextCache, "IAIT", decoder);
  778. }
  779. const t = stripSize * stripT + currentT;
  780. const symbolId = huffman
  781. ? huffmanTables.symbolIDTable.decode(huffmanInput)
  782. : decodeIAID(contextCache, decoder, symbolCodeLength);
  783. const applyRefinement =
  784. refinement &&
  785. (huffman
  786. ? huffmanInput.readBit()
  787. : decodeInteger(contextCache, "IARI", decoder));
  788. let symbolBitmap = inputSymbols[symbolId];
  789. let symbolWidth = symbolBitmap[0].length;
  790. let symbolHeight = symbolBitmap.length;
  791. if (applyRefinement) {
  792. const rdw = decodeInteger(contextCache, "IARDW", decoder); // 6.4.11.1
  793. const rdh = decodeInteger(contextCache, "IARDH", decoder); // 6.4.11.2
  794. const rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
  795. const rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
  796. symbolWidth += rdw;
  797. symbolHeight += rdh;
  798. symbolBitmap = decodeRefinement(
  799. symbolWidth,
  800. symbolHeight,
  801. refinementTemplateIndex,
  802. symbolBitmap,
  803. (rdw >> 1) + rdx,
  804. (rdh >> 1) + rdy,
  805. false,
  806. refinementAt,
  807. decodingContext
  808. );
  809. }
  810. const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
  811. const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
  812. let s2, t2, symbolRow;
  813. if (transposed) {
  814. // Place Symbol Bitmap from T1,S1
  815. for (s2 = 0; s2 < symbolHeight; s2++) {
  816. row = bitmap[offsetS + s2];
  817. if (!row) {
  818. continue;
  819. }
  820. symbolRow = symbolBitmap[s2];
  821. // To ignore Parts of Symbol bitmap which goes
  822. // outside bitmap region
  823. const maxWidth = Math.min(width - offsetT, symbolWidth);
  824. switch (combinationOperator) {
  825. case 0: // OR
  826. for (t2 = 0; t2 < maxWidth; t2++) {
  827. row[offsetT + t2] |= symbolRow[t2];
  828. }
  829. break;
  830. case 2: // XOR
  831. for (t2 = 0; t2 < maxWidth; t2++) {
  832. row[offsetT + t2] ^= symbolRow[t2];
  833. }
  834. break;
  835. default:
  836. throw new Jbig2Error(
  837. `operator ${combinationOperator} is not supported`
  838. );
  839. }
  840. }
  841. currentS += symbolHeight - 1;
  842. } else {
  843. for (t2 = 0; t2 < symbolHeight; t2++) {
  844. row = bitmap[offsetT + t2];
  845. if (!row) {
  846. continue;
  847. }
  848. symbolRow = symbolBitmap[t2];
  849. switch (combinationOperator) {
  850. case 0: // OR
  851. for (s2 = 0; s2 < symbolWidth; s2++) {
  852. row[offsetS + s2] |= symbolRow[s2];
  853. }
  854. break;
  855. case 2: // XOR
  856. for (s2 = 0; s2 < symbolWidth; s2++) {
  857. row[offsetS + s2] ^= symbolRow[s2];
  858. }
  859. break;
  860. default:
  861. throw new Jbig2Error(
  862. `operator ${combinationOperator} is not supported`
  863. );
  864. }
  865. }
  866. currentS += symbolWidth - 1;
  867. }
  868. i++;
  869. const deltaS = huffman
  870. ? huffmanTables.tableDeltaS.decode(huffmanInput)
  871. : decodeInteger(contextCache, "IADS", decoder); // 6.4.8
  872. if (deltaS === null) {
  873. break; // OOB
  874. }
  875. currentS += deltaS + dsOffset;
  876. } while (true);
  877. }
  878. return bitmap;
  879. }
  880. function decodePatternDictionary(
  881. mmr,
  882. patternWidth,
  883. patternHeight,
  884. maxPatternIndex,
  885. template,
  886. decodingContext
  887. ) {
  888. const at = [];
  889. if (!mmr) {
  890. at.push({
  891. x: -patternWidth,
  892. y: 0,
  893. });
  894. if (template === 0) {
  895. at.push(
  896. {
  897. x: -3,
  898. y: -1,
  899. },
  900. {
  901. x: 2,
  902. y: -2,
  903. },
  904. {
  905. x: -2,
  906. y: -2,
  907. }
  908. );
  909. }
  910. }
  911. const collectiveWidth = (maxPatternIndex + 1) * patternWidth;
  912. const collectiveBitmap = decodeBitmap(
  913. mmr,
  914. collectiveWidth,
  915. patternHeight,
  916. template,
  917. false,
  918. null,
  919. at,
  920. decodingContext
  921. );
  922. // Divide collective bitmap into patterns.
  923. const patterns = [];
  924. for (let i = 0; i <= maxPatternIndex; i++) {
  925. const patternBitmap = [];
  926. const xMin = patternWidth * i;
  927. const xMax = xMin + patternWidth;
  928. for (let y = 0; y < patternHeight; y++) {
  929. patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
  930. }
  931. patterns.push(patternBitmap);
  932. }
  933. return patterns;
  934. }
  935. function decodeHalftoneRegion(
  936. mmr,
  937. patterns,
  938. template,
  939. regionWidth,
  940. regionHeight,
  941. defaultPixelValue,
  942. enableSkip,
  943. combinationOperator,
  944. gridWidth,
  945. gridHeight,
  946. gridOffsetX,
  947. gridOffsetY,
  948. gridVectorX,
  949. gridVectorY,
  950. decodingContext
  951. ) {
  952. const skip = null;
  953. if (enableSkip) {
  954. throw new Jbig2Error("skip is not supported");
  955. }
  956. if (combinationOperator !== 0) {
  957. throw new Jbig2Error(
  958. `operator "${combinationOperator}" is not supported in halftone region`
  959. );
  960. }
  961. // Prepare bitmap.
  962. const regionBitmap = [];
  963. let i, j, row;
  964. for (i = 0; i < regionHeight; i++) {
  965. row = new Uint8Array(regionWidth);
  966. if (defaultPixelValue) {
  967. for (j = 0; j < regionWidth; j++) {
  968. row[j] = defaultPixelValue;
  969. }
  970. }
  971. regionBitmap.push(row);
  972. }
  973. const numberOfPatterns = patterns.length;
  974. const pattern0 = patterns[0];
  975. const patternWidth = pattern0[0].length,
  976. patternHeight = pattern0.length;
  977. const bitsPerValue = log2(numberOfPatterns);
  978. const at = [];
  979. if (!mmr) {
  980. at.push({
  981. x: template <= 1 ? 3 : 2,
  982. y: -1,
  983. });
  984. if (template === 0) {
  985. at.push(
  986. {
  987. x: -3,
  988. y: -1,
  989. },
  990. {
  991. x: 2,
  992. y: -2,
  993. },
  994. {
  995. x: -2,
  996. y: -2,
  997. }
  998. );
  999. }
  1000. }
  1001. // Annex C. Gray-scale Image Decoding Procedure.
  1002. const grayScaleBitPlanes = [];
  1003. let mmrInput, bitmap;
  1004. if (mmr) {
  1005. // MMR bit planes are in one continuous stream. Only EOFB codes indicate
  1006. // the end of each bitmap, so EOFBs must be decoded.
  1007. mmrInput = new Reader(
  1008. decodingContext.data,
  1009. decodingContext.start,
  1010. decodingContext.end
  1011. );
  1012. }
  1013. for (i = bitsPerValue - 1; i >= 0; i--) {
  1014. if (mmr) {
  1015. bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
  1016. } else {
  1017. bitmap = decodeBitmap(
  1018. false,
  1019. gridWidth,
  1020. gridHeight,
  1021. template,
  1022. false,
  1023. skip,
  1024. at,
  1025. decodingContext
  1026. );
  1027. }
  1028. grayScaleBitPlanes[i] = bitmap;
  1029. }
  1030. // 6.6.5.2 Rendering the patterns.
  1031. let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow;
  1032. for (mg = 0; mg < gridHeight; mg++) {
  1033. for (ng = 0; ng < gridWidth; ng++) {
  1034. bit = 0;
  1035. patternIndex = 0;
  1036. for (j = bitsPerValue - 1; j >= 0; j--) {
  1037. bit ^= grayScaleBitPlanes[j][mg][ng]; // Gray decoding
  1038. patternIndex |= bit << j;
  1039. }
  1040. patternBitmap = patterns[patternIndex];
  1041. x = (gridOffsetX + mg * gridVectorY + ng * gridVectorX) >> 8;
  1042. y = (gridOffsetY + mg * gridVectorX - ng * gridVectorY) >> 8;
  1043. // Draw patternBitmap at (x, y).
  1044. if (
  1045. x >= 0 &&
  1046. x + patternWidth <= regionWidth &&
  1047. y >= 0 &&
  1048. y + patternHeight <= regionHeight
  1049. ) {
  1050. for (i = 0; i < patternHeight; i++) {
  1051. regionRow = regionBitmap[y + i];
  1052. patternRow = patternBitmap[i];
  1053. for (j = 0; j < patternWidth; j++) {
  1054. regionRow[x + j] |= patternRow[j];
  1055. }
  1056. }
  1057. } else {
  1058. let regionX, regionY;
  1059. for (i = 0; i < patternHeight; i++) {
  1060. regionY = y + i;
  1061. if (regionY < 0 || regionY >= regionHeight) {
  1062. continue;
  1063. }
  1064. regionRow = regionBitmap[regionY];
  1065. patternRow = patternBitmap[i];
  1066. for (j = 0; j < patternWidth; j++) {
  1067. regionX = x + j;
  1068. if (regionX >= 0 && regionX < regionWidth) {
  1069. regionRow[regionX] |= patternRow[j];
  1070. }
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. return regionBitmap;
  1077. }
  1078. function readSegmentHeader(data, start) {
  1079. const segmentHeader = {};
  1080. segmentHeader.number = readUint32(data, start);
  1081. const flags = data[start + 4];
  1082. const segmentType = flags & 0x3f;
  1083. if (!SegmentTypes[segmentType]) {
  1084. throw new Jbig2Error("invalid segment type: " + segmentType);
  1085. }
  1086. segmentHeader.type = segmentType;
  1087. segmentHeader.typeName = SegmentTypes[segmentType];
  1088. segmentHeader.deferredNonRetain = !!(flags & 0x80);
  1089. const pageAssociationFieldSize = !!(flags & 0x40);
  1090. const referredFlags = data[start + 5];
  1091. let referredToCount = (referredFlags >> 5) & 7;
  1092. const retainBits = [referredFlags & 31];
  1093. let position = start + 6;
  1094. if (referredFlags === 7) {
  1095. referredToCount = readUint32(data, position - 1) & 0x1fffffff;
  1096. position += 3;
  1097. let bytes = (referredToCount + 7) >> 3;
  1098. retainBits[0] = data[position++];
  1099. while (--bytes > 0) {
  1100. retainBits.push(data[position++]);
  1101. }
  1102. } else if (referredFlags === 5 || referredFlags === 6) {
  1103. throw new Jbig2Error("invalid referred-to flags");
  1104. }
  1105. segmentHeader.retainBits = retainBits;
  1106. let referredToSegmentNumberSize = 4;
  1107. if (segmentHeader.number <= 256) {
  1108. referredToSegmentNumberSize = 1;
  1109. } else if (segmentHeader.number <= 65536) {
  1110. referredToSegmentNumberSize = 2;
  1111. }
  1112. const referredTo = [];
  1113. let i, ii;
  1114. for (i = 0; i < referredToCount; i++) {
  1115. let number;
  1116. if (referredToSegmentNumberSize === 1) {
  1117. number = data[position];
  1118. } else if (referredToSegmentNumberSize === 2) {
  1119. number = readUint16(data, position);
  1120. } else {
  1121. number = readUint32(data, position);
  1122. }
  1123. referredTo.push(number);
  1124. position += referredToSegmentNumberSize;
  1125. }
  1126. segmentHeader.referredTo = referredTo;
  1127. if (!pageAssociationFieldSize) {
  1128. segmentHeader.pageAssociation = data[position++];
  1129. } else {
  1130. segmentHeader.pageAssociation = readUint32(data, position);
  1131. position += 4;
  1132. }
  1133. segmentHeader.length = readUint32(data, position);
  1134. position += 4;
  1135. if (segmentHeader.length === 0xffffffff) {
  1136. // 7.2.7 Segment data length, unknown segment length
  1137. if (segmentType === 38) {
  1138. // ImmediateGenericRegion
  1139. const genericRegionInfo = readRegionSegmentInformation(data, position);
  1140. const genericRegionSegmentFlags =
  1141. data[position + RegionSegmentInformationFieldLength];
  1142. const genericRegionMmr = !!(genericRegionSegmentFlags & 1);
  1143. // searching for the segment end
  1144. const searchPatternLength = 6;
  1145. const searchPattern = new Uint8Array(searchPatternLength);
  1146. if (!genericRegionMmr) {
  1147. searchPattern[0] = 0xff;
  1148. searchPattern[1] = 0xac;
  1149. }
  1150. searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xff;
  1151. searchPattern[3] = (genericRegionInfo.height >> 16) & 0xff;
  1152. searchPattern[4] = (genericRegionInfo.height >> 8) & 0xff;
  1153. searchPattern[5] = genericRegionInfo.height & 0xff;
  1154. for (i = position, ii = data.length; i < ii; i++) {
  1155. let j = 0;
  1156. while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
  1157. j++;
  1158. }
  1159. if (j === searchPatternLength) {
  1160. segmentHeader.length = i + searchPatternLength;
  1161. break;
  1162. }
  1163. }
  1164. if (segmentHeader.length === 0xffffffff) {
  1165. throw new Jbig2Error("segment end was not found");
  1166. }
  1167. } else {
  1168. throw new Jbig2Error("invalid unknown segment length");
  1169. }
  1170. }
  1171. segmentHeader.headerEnd = position;
  1172. return segmentHeader;
  1173. }
  1174. function readSegments(header, data, start, end) {
  1175. const segments = [];
  1176. let position = start;
  1177. while (position < end) {
  1178. const segmentHeader = readSegmentHeader(data, position);
  1179. position = segmentHeader.headerEnd;
  1180. const segment = {
  1181. header: segmentHeader,
  1182. data,
  1183. };
  1184. if (!header.randomAccess) {
  1185. segment.start = position;
  1186. position += segmentHeader.length;
  1187. segment.end = position;
  1188. }
  1189. segments.push(segment);
  1190. if (segmentHeader.type === 51) {
  1191. break; // end of file is found
  1192. }
  1193. }
  1194. if (header.randomAccess) {
  1195. for (let i = 0, ii = segments.length; i < ii; i++) {
  1196. segments[i].start = position;
  1197. position += segments[i].header.length;
  1198. segments[i].end = position;
  1199. }
  1200. }
  1201. return segments;
  1202. }
  1203. // 7.4.1 Region segment information field
  1204. function readRegionSegmentInformation(data, start) {
  1205. return {
  1206. width: readUint32(data, start),
  1207. height: readUint32(data, start + 4),
  1208. x: readUint32(data, start + 8),
  1209. y: readUint32(data, start + 12),
  1210. combinationOperator: data[start + 16] & 7,
  1211. };
  1212. }
  1213. const RegionSegmentInformationFieldLength = 17;
  1214. function processSegment(segment, visitor) {
  1215. const header = segment.header;
  1216. const data = segment.data,
  1217. end = segment.end;
  1218. let position = segment.start;
  1219. let args, at, i, atLength;
  1220. switch (header.type) {
  1221. case 0: // SymbolDictionary
  1222. // 7.4.2 Symbol dictionary segment syntax
  1223. const dictionary = {};
  1224. const dictionaryFlags = readUint16(data, position); // 7.4.2.1.1
  1225. dictionary.huffman = !!(dictionaryFlags & 1);
  1226. dictionary.refinement = !!(dictionaryFlags & 2);
  1227. dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3;
  1228. dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3;
  1229. dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1;
  1230. dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1;
  1231. dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
  1232. dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
  1233. dictionary.template = (dictionaryFlags >> 10) & 3;
  1234. dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1;
  1235. position += 2;
  1236. if (!dictionary.huffman) {
  1237. atLength = dictionary.template === 0 ? 4 : 1;
  1238. at = [];
  1239. for (i = 0; i < atLength; i++) {
  1240. at.push({
  1241. x: readInt8(data, position),
  1242. y: readInt8(data, position + 1),
  1243. });
  1244. position += 2;
  1245. }
  1246. dictionary.at = at;
  1247. }
  1248. if (dictionary.refinement && !dictionary.refinementTemplate) {
  1249. at = [];
  1250. for (i = 0; i < 2; i++) {
  1251. at.push({
  1252. x: readInt8(data, position),
  1253. y: readInt8(data, position + 1),
  1254. });
  1255. position += 2;
  1256. }
  1257. dictionary.refinementAt = at;
  1258. }
  1259. dictionary.numberOfExportedSymbols = readUint32(data, position);
  1260. position += 4;
  1261. dictionary.numberOfNewSymbols = readUint32(data, position);
  1262. position += 4;
  1263. args = [
  1264. dictionary,
  1265. header.number,
  1266. header.referredTo,
  1267. data,
  1268. position,
  1269. end,
  1270. ];
  1271. break;
  1272. case 6: // ImmediateTextRegion
  1273. case 7: // ImmediateLosslessTextRegion
  1274. const textRegion = {};
  1275. textRegion.info = readRegionSegmentInformation(data, position);
  1276. position += RegionSegmentInformationFieldLength;
  1277. const textRegionSegmentFlags = readUint16(data, position);
  1278. position += 2;
  1279. textRegion.huffman = !!(textRegionSegmentFlags & 1);
  1280. textRegion.refinement = !!(textRegionSegmentFlags & 2);
  1281. textRegion.logStripSize = (textRegionSegmentFlags >> 2) & 3;
  1282. textRegion.stripSize = 1 << textRegion.logStripSize;
  1283. textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3;
  1284. textRegion.transposed = !!(textRegionSegmentFlags & 64);
  1285. textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3;
  1286. textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1;
  1287. textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27;
  1288. textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1;
  1289. if (textRegion.huffman) {
  1290. const textRegionHuffmanFlags = readUint16(data, position);
  1291. position += 2;
  1292. textRegion.huffmanFS = textRegionHuffmanFlags & 3;
  1293. textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3;
  1294. textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3;
  1295. textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3;
  1296. textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3;
  1297. textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3;
  1298. textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3;
  1299. textRegion.huffmanRefinementSizeSelector = !!(
  1300. textRegionHuffmanFlags & 0x4000
  1301. );
  1302. }
  1303. if (textRegion.refinement && !textRegion.refinementTemplate) {
  1304. at = [];
  1305. for (i = 0; i < 2; i++) {
  1306. at.push({
  1307. x: readInt8(data, position),
  1308. y: readInt8(data, position + 1),
  1309. });
  1310. position += 2;
  1311. }
  1312. textRegion.refinementAt = at;
  1313. }
  1314. textRegion.numberOfSymbolInstances = readUint32(data, position);
  1315. position += 4;
  1316. args = [textRegion, header.referredTo, data, position, end];
  1317. break;
  1318. case 16: // PatternDictionary
  1319. // 7.4.4. Pattern dictionary segment syntax
  1320. const patternDictionary = {};
  1321. const patternDictionaryFlags = data[position++];
  1322. patternDictionary.mmr = !!(patternDictionaryFlags & 1);
  1323. patternDictionary.template = (patternDictionaryFlags >> 1) & 3;
  1324. patternDictionary.patternWidth = data[position++];
  1325. patternDictionary.patternHeight = data[position++];
  1326. patternDictionary.maxPatternIndex = readUint32(data, position);
  1327. position += 4;
  1328. args = [patternDictionary, header.number, data, position, end];
  1329. break;
  1330. case 22: // ImmediateHalftoneRegion
  1331. case 23: // ImmediateLosslessHalftoneRegion
  1332. // 7.4.5 Halftone region segment syntax
  1333. const halftoneRegion = {};
  1334. halftoneRegion.info = readRegionSegmentInformation(data, position);
  1335. position += RegionSegmentInformationFieldLength;
  1336. const halftoneRegionFlags = data[position++];
  1337. halftoneRegion.mmr = !!(halftoneRegionFlags & 1);
  1338. halftoneRegion.template = (halftoneRegionFlags >> 1) & 3;
  1339. halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);
  1340. halftoneRegion.combinationOperator = (halftoneRegionFlags >> 4) & 7;
  1341. halftoneRegion.defaultPixelValue = (halftoneRegionFlags >> 7) & 1;
  1342. halftoneRegion.gridWidth = readUint32(data, position);
  1343. position += 4;
  1344. halftoneRegion.gridHeight = readUint32(data, position);
  1345. position += 4;
  1346. halftoneRegion.gridOffsetX = readUint32(data, position) & 0xffffffff;
  1347. position += 4;
  1348. halftoneRegion.gridOffsetY = readUint32(data, position) & 0xffffffff;
  1349. position += 4;
  1350. halftoneRegion.gridVectorX = readUint16(data, position);
  1351. position += 2;
  1352. halftoneRegion.gridVectorY = readUint16(data, position);
  1353. position += 2;
  1354. args = [halftoneRegion, header.referredTo, data, position, end];
  1355. break;
  1356. case 38: // ImmediateGenericRegion
  1357. case 39: // ImmediateLosslessGenericRegion
  1358. const genericRegion = {};
  1359. genericRegion.info = readRegionSegmentInformation(data, position);
  1360. position += RegionSegmentInformationFieldLength;
  1361. const genericRegionSegmentFlags = data[position++];
  1362. genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
  1363. genericRegion.template = (genericRegionSegmentFlags >> 1) & 3;
  1364. genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
  1365. if (!genericRegion.mmr) {
  1366. atLength = genericRegion.template === 0 ? 4 : 1;
  1367. at = [];
  1368. for (i = 0; i < atLength; i++) {
  1369. at.push({
  1370. x: readInt8(data, position),
  1371. y: readInt8(data, position + 1),
  1372. });
  1373. position += 2;
  1374. }
  1375. genericRegion.at = at;
  1376. }
  1377. args = [genericRegion, data, position, end];
  1378. break;
  1379. case 48: // PageInformation
  1380. const pageInfo = {
  1381. width: readUint32(data, position),
  1382. height: readUint32(data, position + 4),
  1383. resolutionX: readUint32(data, position + 8),
  1384. resolutionY: readUint32(data, position + 12),
  1385. };
  1386. if (pageInfo.height === 0xffffffff) {
  1387. delete pageInfo.height;
  1388. }
  1389. const pageSegmentFlags = data[position + 16];
  1390. readUint16(data, position + 17); // pageStripingInformation
  1391. pageInfo.lossless = !!(pageSegmentFlags & 1);
  1392. pageInfo.refinement = !!(pageSegmentFlags & 2);
  1393. pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
  1394. pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
  1395. pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
  1396. pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
  1397. args = [pageInfo];
  1398. break;
  1399. case 49: // EndOfPage
  1400. break;
  1401. case 50: // EndOfStripe
  1402. break;
  1403. case 51: // EndOfFile
  1404. break;
  1405. case 53: // Tables
  1406. args = [header.number, data, position, end];
  1407. break;
  1408. case 62: // 7.4.15 defines 2 extension types which
  1409. // are comments and can be ignored.
  1410. break;
  1411. default:
  1412. throw new Jbig2Error(
  1413. `segment type ${header.typeName}(${header.type}) is not implemented`
  1414. );
  1415. }
  1416. const callbackName = "on" + header.typeName;
  1417. if (callbackName in visitor) {
  1418. // eslint-disable-next-line prefer-spread
  1419. visitor[callbackName].apply(visitor, args);
  1420. }
  1421. }
  1422. function processSegments(segments, visitor) {
  1423. for (let i = 0, ii = segments.length; i < ii; i++) {
  1424. processSegment(segments[i], visitor);
  1425. }
  1426. }
  1427. function parseJbig2Chunks(chunks) {
  1428. const visitor = new SimpleSegmentVisitor();
  1429. for (let i = 0, ii = chunks.length; i < ii; i++) {
  1430. const chunk = chunks[i];
  1431. const segments = readSegments({}, chunk.data, chunk.start, chunk.end);
  1432. processSegments(segments, visitor);
  1433. }
  1434. return visitor.buffer;
  1435. }
  1436. function parseJbig2(data) {
  1437. if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("IMAGE_DECODERS")) {
  1438. throw new Error("Not implemented: parseJbig2");
  1439. }
  1440. const end = data.length;
  1441. let position = 0;
  1442. if (
  1443. data[position] !== 0x97 ||
  1444. data[position + 1] !== 0x4a ||
  1445. data[position + 2] !== 0x42 ||
  1446. data[position + 3] !== 0x32 ||
  1447. data[position + 4] !== 0x0d ||
  1448. data[position + 5] !== 0x0a ||
  1449. data[position + 6] !== 0x1a ||
  1450. data[position + 7] !== 0x0a
  1451. ) {
  1452. throw new Jbig2Error("parseJbig2 - invalid header.");
  1453. }
  1454. const header = Object.create(null);
  1455. position += 8;
  1456. const flags = data[position++];
  1457. header.randomAccess = !(flags & 1);
  1458. if (!(flags & 2)) {
  1459. header.numberOfPages = readUint32(data, position);
  1460. position += 4;
  1461. }
  1462. const segments = readSegments(header, data, position, end);
  1463. const visitor = new SimpleSegmentVisitor();
  1464. processSegments(segments, visitor);
  1465. const { width, height } = visitor.currentPageInfo;
  1466. const bitPacked = visitor.buffer;
  1467. const imgData = new Uint8ClampedArray(width * height);
  1468. let q = 0,
  1469. k = 0;
  1470. for (let i = 0; i < height; i++) {
  1471. let mask = 0,
  1472. buffer;
  1473. for (let j = 0; j < width; j++) {
  1474. if (!mask) {
  1475. mask = 128;
  1476. buffer = bitPacked[k++];
  1477. }
  1478. imgData[q++] = buffer & mask ? 0 : 255;
  1479. mask >>= 1;
  1480. }
  1481. }
  1482. return { imgData, width, height };
  1483. }
  1484. class SimpleSegmentVisitor {
  1485. onPageInformation(info) {
  1486. this.currentPageInfo = info;
  1487. const rowSize = (info.width + 7) >> 3;
  1488. const buffer = new Uint8ClampedArray(rowSize * info.height);
  1489. // The contents of ArrayBuffers are initialized to 0.
  1490. // Fill the buffer with 0xFF only if info.defaultPixelValue is set
  1491. if (info.defaultPixelValue) {
  1492. buffer.fill(0xff);
  1493. }
  1494. this.buffer = buffer;
  1495. }
  1496. drawBitmap(regionInfo, bitmap) {
  1497. const pageInfo = this.currentPageInfo;
  1498. const width = regionInfo.width,
  1499. height = regionInfo.height;
  1500. const rowSize = (pageInfo.width + 7) >> 3;
  1501. const combinationOperator = pageInfo.combinationOperatorOverride
  1502. ? regionInfo.combinationOperator
  1503. : pageInfo.combinationOperator;
  1504. const buffer = this.buffer;
  1505. const mask0 = 128 >> (regionInfo.x & 7);
  1506. let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
  1507. let i, j, mask, offset;
  1508. switch (combinationOperator) {
  1509. case 0: // OR
  1510. for (i = 0; i < height; i++) {
  1511. mask = mask0;
  1512. offset = offset0;
  1513. for (j = 0; j < width; j++) {
  1514. if (bitmap[i][j]) {
  1515. buffer[offset] |= mask;
  1516. }
  1517. mask >>= 1;
  1518. if (!mask) {
  1519. mask = 128;
  1520. offset++;
  1521. }
  1522. }
  1523. offset0 += rowSize;
  1524. }
  1525. break;
  1526. case 2: // XOR
  1527. for (i = 0; i < height; i++) {
  1528. mask = mask0;
  1529. offset = offset0;
  1530. for (j = 0; j < width; j++) {
  1531. if (bitmap[i][j]) {
  1532. buffer[offset] ^= mask;
  1533. }
  1534. mask >>= 1;
  1535. if (!mask) {
  1536. mask = 128;
  1537. offset++;
  1538. }
  1539. }
  1540. offset0 += rowSize;
  1541. }
  1542. break;
  1543. default:
  1544. throw new Jbig2Error(
  1545. `operator ${combinationOperator} is not supported`
  1546. );
  1547. }
  1548. }
  1549. onImmediateGenericRegion(region, data, start, end) {
  1550. const regionInfo = region.info;
  1551. const decodingContext = new DecodingContext(data, start, end);
  1552. const bitmap = decodeBitmap(
  1553. region.mmr,
  1554. regionInfo.width,
  1555. regionInfo.height,
  1556. region.template,
  1557. region.prediction,
  1558. null,
  1559. region.at,
  1560. decodingContext
  1561. );
  1562. this.drawBitmap(regionInfo, bitmap);
  1563. }
  1564. onImmediateLosslessGenericRegion() {
  1565. this.onImmediateGenericRegion(...arguments);
  1566. }
  1567. onSymbolDictionary(
  1568. dictionary,
  1569. currentSegment,
  1570. referredSegments,
  1571. data,
  1572. start,
  1573. end
  1574. ) {
  1575. let huffmanTables, huffmanInput;
  1576. if (dictionary.huffman) {
  1577. huffmanTables = getSymbolDictionaryHuffmanTables(
  1578. dictionary,
  1579. referredSegments,
  1580. this.customTables
  1581. );
  1582. huffmanInput = new Reader(data, start, end);
  1583. }
  1584. // Combines exported symbols from all referred segments
  1585. let symbols = this.symbols;
  1586. if (!symbols) {
  1587. this.symbols = symbols = {};
  1588. }
  1589. const inputSymbols = [];
  1590. for (const referredSegment of referredSegments) {
  1591. const referredSymbols = symbols[referredSegment];
  1592. // referredSymbols is undefined when we have a reference to a Tables
  1593. // segment instead of a SymbolDictionary.
  1594. if (referredSymbols) {
  1595. inputSymbols.push(...referredSymbols);
  1596. }
  1597. }
  1598. const decodingContext = new DecodingContext(data, start, end);
  1599. symbols[currentSegment] = decodeSymbolDictionary(
  1600. dictionary.huffman,
  1601. dictionary.refinement,
  1602. inputSymbols,
  1603. dictionary.numberOfNewSymbols,
  1604. dictionary.numberOfExportedSymbols,
  1605. huffmanTables,
  1606. dictionary.template,
  1607. dictionary.at,
  1608. dictionary.refinementTemplate,
  1609. dictionary.refinementAt,
  1610. decodingContext,
  1611. huffmanInput
  1612. );
  1613. }
  1614. onImmediateTextRegion(region, referredSegments, data, start, end) {
  1615. const regionInfo = region.info;
  1616. let huffmanTables, huffmanInput;
  1617. // Combines exported symbols from all referred segments
  1618. const symbols = this.symbols;
  1619. const inputSymbols = [];
  1620. for (const referredSegment of referredSegments) {
  1621. const referredSymbols = symbols[referredSegment];
  1622. // referredSymbols is undefined when we have a reference to a Tables
  1623. // segment instead of a SymbolDictionary.
  1624. if (referredSymbols) {
  1625. inputSymbols.push(...referredSymbols);
  1626. }
  1627. }
  1628. const symbolCodeLength = log2(inputSymbols.length);
  1629. if (region.huffman) {
  1630. huffmanInput = new Reader(data, start, end);
  1631. huffmanTables = getTextRegionHuffmanTables(
  1632. region,
  1633. referredSegments,
  1634. this.customTables,
  1635. inputSymbols.length,
  1636. huffmanInput
  1637. );
  1638. }
  1639. const decodingContext = new DecodingContext(data, start, end);
  1640. const bitmap = decodeTextRegion(
  1641. region.huffman,
  1642. region.refinement,
  1643. regionInfo.width,
  1644. regionInfo.height,
  1645. region.defaultPixelValue,
  1646. region.numberOfSymbolInstances,
  1647. region.stripSize,
  1648. inputSymbols,
  1649. symbolCodeLength,
  1650. region.transposed,
  1651. region.dsOffset,
  1652. region.referenceCorner,
  1653. region.combinationOperator,
  1654. huffmanTables,
  1655. region.refinementTemplate,
  1656. region.refinementAt,
  1657. decodingContext,
  1658. region.logStripSize,
  1659. huffmanInput
  1660. );
  1661. this.drawBitmap(regionInfo, bitmap);
  1662. }
  1663. onImmediateLosslessTextRegion() {
  1664. this.onImmediateTextRegion(...arguments);
  1665. }
  1666. onPatternDictionary(dictionary, currentSegment, data, start, end) {
  1667. let patterns = this.patterns;
  1668. if (!patterns) {
  1669. this.patterns = patterns = {};
  1670. }
  1671. const decodingContext = new DecodingContext(data, start, end);
  1672. patterns[currentSegment] = decodePatternDictionary(
  1673. dictionary.mmr,
  1674. dictionary.patternWidth,
  1675. dictionary.patternHeight,
  1676. dictionary.maxPatternIndex,
  1677. dictionary.template,
  1678. decodingContext
  1679. );
  1680. }
  1681. onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
  1682. // HalftoneRegion refers to exactly one PatternDictionary.
  1683. const patterns = this.patterns[referredSegments[0]];
  1684. const regionInfo = region.info;
  1685. const decodingContext = new DecodingContext(data, start, end);
  1686. const bitmap = decodeHalftoneRegion(
  1687. region.mmr,
  1688. patterns,
  1689. region.template,
  1690. regionInfo.width,
  1691. regionInfo.height,
  1692. region.defaultPixelValue,
  1693. region.enableSkip,
  1694. region.combinationOperator,
  1695. region.gridWidth,
  1696. region.gridHeight,
  1697. region.gridOffsetX,
  1698. region.gridOffsetY,
  1699. region.gridVectorX,
  1700. region.gridVectorY,
  1701. decodingContext
  1702. );
  1703. this.drawBitmap(regionInfo, bitmap);
  1704. }
  1705. onImmediateLosslessHalftoneRegion() {
  1706. this.onImmediateHalftoneRegion(...arguments);
  1707. }
  1708. onTables(currentSegment, data, start, end) {
  1709. let customTables = this.customTables;
  1710. if (!customTables) {
  1711. this.customTables = customTables = {};
  1712. }
  1713. customTables[currentSegment] = decodeTablesSegment(data, start, end);
  1714. }
  1715. }
  1716. class HuffmanLine {
  1717. constructor(lineData) {
  1718. if (lineData.length === 2) {
  1719. // OOB line.
  1720. this.isOOB = true;
  1721. this.rangeLow = 0;
  1722. this.prefixLength = lineData[0];
  1723. this.rangeLength = 0;
  1724. this.prefixCode = lineData[1];
  1725. this.isLowerRange = false;
  1726. } else {
  1727. // Normal, upper range or lower range line.
  1728. // Upper range lines are processed like normal lines.
  1729. this.isOOB = false;
  1730. this.rangeLow = lineData[0];
  1731. this.prefixLength = lineData[1];
  1732. this.rangeLength = lineData[2];
  1733. this.prefixCode = lineData[3];
  1734. this.isLowerRange = lineData[4] === "lower";
  1735. }
  1736. }
  1737. }
  1738. class HuffmanTreeNode {
  1739. constructor(line) {
  1740. this.children = [];
  1741. if (line) {
  1742. // Leaf node
  1743. this.isLeaf = true;
  1744. this.rangeLength = line.rangeLength;
  1745. this.rangeLow = line.rangeLow;
  1746. this.isLowerRange = line.isLowerRange;
  1747. this.isOOB = line.isOOB;
  1748. } else {
  1749. // Intermediate or root node
  1750. this.isLeaf = false;
  1751. }
  1752. }
  1753. buildTree(line, shift) {
  1754. const bit = (line.prefixCode >> shift) & 1;
  1755. if (shift <= 0) {
  1756. // Create a leaf node.
  1757. this.children[bit] = new HuffmanTreeNode(line);
  1758. } else {
  1759. // Create an intermediate node and continue recursively.
  1760. let node = this.children[bit];
  1761. if (!node) {
  1762. this.children[bit] = node = new HuffmanTreeNode(null);
  1763. }
  1764. node.buildTree(line, shift - 1);
  1765. }
  1766. }
  1767. decodeNode(reader) {
  1768. if (this.isLeaf) {
  1769. if (this.isOOB) {
  1770. return null;
  1771. }
  1772. const htOffset = reader.readBits(this.rangeLength);
  1773. return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
  1774. }
  1775. const node = this.children[reader.readBit()];
  1776. if (!node) {
  1777. throw new Jbig2Error("invalid Huffman data");
  1778. }
  1779. return node.decodeNode(reader);
  1780. }
  1781. }
  1782. class HuffmanTable {
  1783. constructor(lines, prefixCodesDone) {
  1784. if (!prefixCodesDone) {
  1785. this.assignPrefixCodes(lines);
  1786. }
  1787. // Create Huffman tree.
  1788. this.rootNode = new HuffmanTreeNode(null);
  1789. for (let i = 0, ii = lines.length; i < ii; i++) {
  1790. const line = lines[i];
  1791. if (line.prefixLength > 0) {
  1792. this.rootNode.buildTree(line, line.prefixLength - 1);
  1793. }
  1794. }
  1795. }
  1796. decode(reader) {
  1797. return this.rootNode.decodeNode(reader);
  1798. }
  1799. assignPrefixCodes(lines) {
  1800. // Annex B.3 Assigning the prefix codes.
  1801. const linesLength = lines.length;
  1802. let prefixLengthMax = 0;
  1803. for (let i = 0; i < linesLength; i++) {
  1804. prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
  1805. }
  1806. const histogram = new Uint32Array(prefixLengthMax + 1);
  1807. for (let i = 0; i < linesLength; i++) {
  1808. histogram[lines[i].prefixLength]++;
  1809. }
  1810. let currentLength = 1,
  1811. firstCode = 0,
  1812. currentCode,
  1813. currentTemp,
  1814. line;
  1815. histogram[0] = 0;
  1816. while (currentLength <= prefixLengthMax) {
  1817. firstCode = (firstCode + histogram[currentLength - 1]) << 1;
  1818. currentCode = firstCode;
  1819. currentTemp = 0;
  1820. while (currentTemp < linesLength) {
  1821. line = lines[currentTemp];
  1822. if (line.prefixLength === currentLength) {
  1823. line.prefixCode = currentCode;
  1824. currentCode++;
  1825. }
  1826. currentTemp++;
  1827. }
  1828. currentLength++;
  1829. }
  1830. }
  1831. }
  1832. function decodeTablesSegment(data, start, end) {
  1833. // Decodes a Tables segment, i.e., a custom Huffman table.
  1834. // Annex B.2 Code table structure.
  1835. const flags = data[start];
  1836. const lowestValue = readUint32(data, start + 1) & 0xffffffff;
  1837. const highestValue = readUint32(data, start + 5) & 0xffffffff;
  1838. const reader = new Reader(data, start + 9, end);
  1839. const prefixSizeBits = ((flags >> 1) & 7) + 1;
  1840. const rangeSizeBits = ((flags >> 4) & 7) + 1;
  1841. const lines = [];
  1842. let prefixLength,
  1843. rangeLength,
  1844. currentRangeLow = lowestValue;
  1845. // Normal table lines
  1846. do {
  1847. prefixLength = reader.readBits(prefixSizeBits);
  1848. rangeLength = reader.readBits(rangeSizeBits);
  1849. lines.push(
  1850. new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0])
  1851. );
  1852. currentRangeLow += 1 << rangeLength;
  1853. } while (currentRangeLow < highestValue);
  1854. // Lower range table line
  1855. prefixLength = reader.readBits(prefixSizeBits);
  1856. lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"]));
  1857. // Upper range table line
  1858. prefixLength = reader.readBits(prefixSizeBits);
  1859. lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
  1860. if (flags & 1) {
  1861. // Out-of-band table line
  1862. prefixLength = reader.readBits(prefixSizeBits);
  1863. lines.push(new HuffmanLine([prefixLength, 0]));
  1864. }
  1865. return new HuffmanTable(lines, false);
  1866. }
  1867. const standardTablesCache = {};
  1868. function getStandardTable(number) {
  1869. // Annex B.5 Standard Huffman tables.
  1870. let table = standardTablesCache[number];
  1871. if (table) {
  1872. return table;
  1873. }
  1874. let lines;
  1875. switch (number) {
  1876. case 1:
  1877. lines = [
  1878. [0, 1, 4, 0x0],
  1879. [16, 2, 8, 0x2],
  1880. [272, 3, 16, 0x6],
  1881. [65808, 3, 32, 0x7], // upper
  1882. ];
  1883. break;
  1884. case 2:
  1885. lines = [
  1886. [0, 1, 0, 0x0],
  1887. [1, 2, 0, 0x2],
  1888. [2, 3, 0, 0x6],
  1889. [3, 4, 3, 0xe],
  1890. [11, 5, 6, 0x1e],
  1891. [75, 6, 32, 0x3e], // upper
  1892. [6, 0x3f], // OOB
  1893. ];
  1894. break;
  1895. case 3:
  1896. lines = [
  1897. [-256, 8, 8, 0xfe],
  1898. [0, 1, 0, 0x0],
  1899. [1, 2, 0, 0x2],
  1900. [2, 3, 0, 0x6],
  1901. [3, 4, 3, 0xe],
  1902. [11, 5, 6, 0x1e],
  1903. [-257, 8, 32, 0xff, "lower"],
  1904. [75, 7, 32, 0x7e], // upper
  1905. [6, 0x3e], // OOB
  1906. ];
  1907. break;
  1908. case 4:
  1909. lines = [
  1910. [1, 1, 0, 0x0],
  1911. [2, 2, 0, 0x2],
  1912. [3, 3, 0, 0x6],
  1913. [4, 4, 3, 0xe],
  1914. [12, 5, 6, 0x1e],
  1915. [76, 5, 32, 0x1f], // upper
  1916. ];
  1917. break;
  1918. case 5:
  1919. lines = [
  1920. [-255, 7, 8, 0x7e],
  1921. [1, 1, 0, 0x0],
  1922. [2, 2, 0, 0x2],
  1923. [3, 3, 0, 0x6],
  1924. [4, 4, 3, 0xe],
  1925. [12, 5, 6, 0x1e],
  1926. [-256, 7, 32, 0x7f, "lower"],
  1927. [76, 6, 32, 0x3e], // upper
  1928. ];
  1929. break;
  1930. case 6:
  1931. lines = [
  1932. [-2048, 5, 10, 0x1c],
  1933. [-1024, 4, 9, 0x8],
  1934. [-512, 4, 8, 0x9],
  1935. [-256, 4, 7, 0xa],
  1936. [-128, 5, 6, 0x1d],
  1937. [-64, 5, 5, 0x1e],
  1938. [-32, 4, 5, 0xb],
  1939. [0, 2, 7, 0x0],
  1940. [128, 3, 7, 0x2],
  1941. [256, 3, 8, 0x3],
  1942. [512, 4, 9, 0xc],
  1943. [1024, 4, 10, 0xd],
  1944. [-2049, 6, 32, 0x3e, "lower"],
  1945. [2048, 6, 32, 0x3f], // upper
  1946. ];
  1947. break;
  1948. case 7:
  1949. lines = [
  1950. [-1024, 4, 9, 0x8],
  1951. [-512, 3, 8, 0x0],
  1952. [-256, 4, 7, 0x9],
  1953. [-128, 5, 6, 0x1a],
  1954. [-64, 5, 5, 0x1b],
  1955. [-32, 4, 5, 0xa],
  1956. [0, 4, 5, 0xb],
  1957. [32, 5, 5, 0x1c],
  1958. [64, 5, 6, 0x1d],
  1959. [128, 4, 7, 0xc],
  1960. [256, 3, 8, 0x1],
  1961. [512, 3, 9, 0x2],
  1962. [1024, 3, 10, 0x3],
  1963. [-1025, 5, 32, 0x1e, "lower"],
  1964. [2048, 5, 32, 0x1f], // upper
  1965. ];
  1966. break;
  1967. case 8:
  1968. lines = [
  1969. [-15, 8, 3, 0xfc],
  1970. [-7, 9, 1, 0x1fc],
  1971. [-5, 8, 1, 0xfd],
  1972. [-3, 9, 0, 0x1fd],
  1973. [-2, 7, 0, 0x7c],
  1974. [-1, 4, 0, 0xa],
  1975. [0, 2, 1, 0x0],
  1976. [2, 5, 0, 0x1a],
  1977. [3, 6, 0, 0x3a],
  1978. [4, 3, 4, 0x4],
  1979. [20, 6, 1, 0x3b],
  1980. [22, 4, 4, 0xb],
  1981. [38, 4, 5, 0xc],
  1982. [70, 5, 6, 0x1b],
  1983. [134, 5, 7, 0x1c],
  1984. [262, 6, 7, 0x3c],
  1985. [390, 7, 8, 0x7d],
  1986. [646, 6, 10, 0x3d],
  1987. [-16, 9, 32, 0x1fe, "lower"],
  1988. [1670, 9, 32, 0x1ff], // upper
  1989. [2, 0x1], // OOB
  1990. ];
  1991. break;
  1992. case 9:
  1993. lines = [
  1994. [-31, 8, 4, 0xfc],
  1995. [-15, 9, 2, 0x1fc],
  1996. [-11, 8, 2, 0xfd],
  1997. [-7, 9, 1, 0x1fd],
  1998. [-5, 7, 1, 0x7c],
  1999. [-3, 4, 1, 0xa],
  2000. [-1, 3, 1, 0x2],
  2001. [1, 3, 1, 0x3],
  2002. [3, 5, 1, 0x1a],
  2003. [5, 6, 1, 0x3a],
  2004. [7, 3, 5, 0x4],
  2005. [39, 6, 2, 0x3b],
  2006. [43, 4, 5, 0xb],
  2007. [75, 4, 6, 0xc],
  2008. [139, 5, 7, 0x1b],
  2009. [267, 5, 8, 0x1c],
  2010. [523, 6, 8, 0x3c],
  2011. [779, 7, 9, 0x7d],
  2012. [1291, 6, 11, 0x3d],
  2013. [-32, 9, 32, 0x1fe, "lower"],
  2014. [3339, 9, 32, 0x1ff], // upper
  2015. [2, 0x0], // OOB
  2016. ];
  2017. break;
  2018. case 10:
  2019. lines = [
  2020. [-21, 7, 4, 0x7a],
  2021. [-5, 8, 0, 0xfc],
  2022. [-4, 7, 0, 0x7b],
  2023. [-3, 5, 0, 0x18],
  2024. [-2, 2, 2, 0x0],
  2025. [2, 5, 0, 0x19],
  2026. [3, 6, 0, 0x36],
  2027. [4, 7, 0, 0x7c],
  2028. [5, 8, 0, 0xfd],
  2029. [6, 2, 6, 0x1],
  2030. [70, 5, 5, 0x1a],
  2031. [102, 6, 5, 0x37],
  2032. [134, 6, 6, 0x38],
  2033. [198, 6, 7, 0x39],
  2034. [326, 6, 8, 0x3a],
  2035. [582, 6, 9, 0x3b],
  2036. [1094, 6, 10, 0x3c],
  2037. [2118, 7, 11, 0x7d],
  2038. [-22, 8, 32, 0xfe, "lower"],
  2039. [4166, 8, 32, 0xff], // upper
  2040. [2, 0x2], // OOB
  2041. ];
  2042. break;
  2043. case 11:
  2044. lines = [
  2045. [1, 1, 0, 0x0],
  2046. [2, 2, 1, 0x2],
  2047. [4, 4, 0, 0xc],
  2048. [5, 4, 1, 0xd],
  2049. [7, 5, 1, 0x1c],
  2050. [9, 5, 2, 0x1d],
  2051. [13, 6, 2, 0x3c],
  2052. [17, 7, 2, 0x7a],
  2053. [21, 7, 3, 0x7b],
  2054. [29, 7, 4, 0x7c],
  2055. [45, 7, 5, 0x7d],
  2056. [77, 7, 6, 0x7e],
  2057. [141, 7, 32, 0x7f], // upper
  2058. ];
  2059. break;
  2060. case 12:
  2061. lines = [
  2062. [1, 1, 0, 0x0],
  2063. [2, 2, 0, 0x2],
  2064. [3, 3, 1, 0x6],
  2065. [5, 5, 0, 0x1c],
  2066. [6, 5, 1, 0x1d],
  2067. [8, 6, 1, 0x3c],
  2068. [10, 7, 0, 0x7a],
  2069. [11, 7, 1, 0x7b],
  2070. [13, 7, 2, 0x7c],
  2071. [17, 7, 3, 0x7d],
  2072. [25, 7, 4, 0x7e],
  2073. [41, 8, 5, 0xfe],
  2074. [73, 8, 32, 0xff], // upper
  2075. ];
  2076. break;
  2077. case 13:
  2078. lines = [
  2079. [1, 1, 0, 0x0],
  2080. [2, 3, 0, 0x4],
  2081. [3, 4, 0, 0xc],
  2082. [4, 5, 0, 0x1c],
  2083. [5, 4, 1, 0xd],
  2084. [7, 3, 3, 0x5],
  2085. [15, 6, 1, 0x3a],
  2086. [17, 6, 2, 0x3b],
  2087. [21, 6, 3, 0x3c],
  2088. [29, 6, 4, 0x3d],
  2089. [45, 6, 5, 0x3e],
  2090. [77, 7, 6, 0x7e],
  2091. [141, 7, 32, 0x7f], // upper
  2092. ];
  2093. break;
  2094. case 14:
  2095. lines = [
  2096. [-2, 3, 0, 0x4],
  2097. [-1, 3, 0, 0x5],
  2098. [0, 1, 0, 0x0],
  2099. [1, 3, 0, 0x6],
  2100. [2, 3, 0, 0x7],
  2101. ];
  2102. break;
  2103. case 15:
  2104. lines = [
  2105. [-24, 7, 4, 0x7c],
  2106. [-8, 6, 2, 0x3c],
  2107. [-4, 5, 1, 0x1c],
  2108. [-2, 4, 0, 0xc],
  2109. [-1, 3, 0, 0x4],
  2110. [0, 1, 0, 0x0],
  2111. [1, 3, 0, 0x5],
  2112. [2, 4, 0, 0xd],
  2113. [3, 5, 1, 0x1d],
  2114. [5, 6, 2, 0x3d],
  2115. [9, 7, 4, 0x7d],
  2116. [-25, 7, 32, 0x7e, "lower"],
  2117. [25, 7, 32, 0x7f], // upper
  2118. ];
  2119. break;
  2120. default:
  2121. throw new Jbig2Error(`standard table B.${number} does not exist`);
  2122. }
  2123. for (let i = 0, ii = lines.length; i < ii; i++) {
  2124. lines[i] = new HuffmanLine(lines[i]);
  2125. }
  2126. table = new HuffmanTable(lines, true);
  2127. standardTablesCache[number] = table;
  2128. return table;
  2129. }
  2130. class Reader {
  2131. constructor(data, start, end) {
  2132. this.data = data;
  2133. this.start = start;
  2134. this.end = end;
  2135. this.position = start;
  2136. this.shift = -1;
  2137. this.currentByte = 0;
  2138. }
  2139. readBit() {
  2140. if (this.shift < 0) {
  2141. if (this.position >= this.end) {
  2142. throw new Jbig2Error("end of data while reading bit");
  2143. }
  2144. this.currentByte = this.data[this.position++];
  2145. this.shift = 7;
  2146. }
  2147. const bit = (this.currentByte >> this.shift) & 1;
  2148. this.shift--;
  2149. return bit;
  2150. }
  2151. readBits(numBits) {
  2152. let result = 0,
  2153. i;
  2154. for (i = numBits - 1; i >= 0; i--) {
  2155. result |= this.readBit() << i;
  2156. }
  2157. return result;
  2158. }
  2159. byteAlign() {
  2160. this.shift = -1;
  2161. }
  2162. next() {
  2163. if (this.position >= this.end) {
  2164. return -1;
  2165. }
  2166. return this.data[this.position++];
  2167. }
  2168. }
  2169. function getCustomHuffmanTable(index, referredTo, customTables) {
  2170. // Returns a Tables segment that has been earlier decoded.
  2171. // See 7.4.2.1.6 (symbol dictionary) or 7.4.3.1.6 (text region).
  2172. let currentIndex = 0;
  2173. for (let i = 0, ii = referredTo.length; i < ii; i++) {
  2174. const table = customTables[referredTo[i]];
  2175. if (table) {
  2176. if (index === currentIndex) {
  2177. return table;
  2178. }
  2179. currentIndex++;
  2180. }
  2181. }
  2182. throw new Jbig2Error("can't find custom Huffman table");
  2183. }
  2184. function getTextRegionHuffmanTables(
  2185. textRegion,
  2186. referredTo,
  2187. customTables,
  2188. numberOfSymbols,
  2189. reader
  2190. ) {
  2191. // 7.4.3.1.7 Symbol ID Huffman table decoding
  2192. // Read code lengths for RUNCODEs 0...34.
  2193. const codes = [];
  2194. for (let i = 0; i <= 34; i++) {
  2195. const codeLength = reader.readBits(4);
  2196. codes.push(new HuffmanLine([i, codeLength, 0, 0]));
  2197. }
  2198. // Assign Huffman codes for RUNCODEs.
  2199. const runCodesTable = new HuffmanTable(codes, false);
  2200. // Read a Huffman code using the assignment above.
  2201. // Interpret the RUNCODE codes and the additional bits (if any).
  2202. codes.length = 0;
  2203. for (let i = 0; i < numberOfSymbols; ) {
  2204. const codeLength = runCodesTable.decode(reader);
  2205. if (codeLength >= 32) {
  2206. let repeatedLength, numberOfRepeats, j;
  2207. switch (codeLength) {
  2208. case 32:
  2209. if (i === 0) {
  2210. throw new Jbig2Error("no previous value in symbol ID table");
  2211. }
  2212. numberOfRepeats = reader.readBits(2) + 3;
  2213. repeatedLength = codes[i - 1].prefixLength;
  2214. break;
  2215. case 33:
  2216. numberOfRepeats = reader.readBits(3) + 3;
  2217. repeatedLength = 0;
  2218. break;
  2219. case 34:
  2220. numberOfRepeats = reader.readBits(7) + 11;
  2221. repeatedLength = 0;
  2222. break;
  2223. default:
  2224. throw new Jbig2Error("invalid code length in symbol ID table");
  2225. }
  2226. for (j = 0; j < numberOfRepeats; j++) {
  2227. codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
  2228. i++;
  2229. }
  2230. } else {
  2231. codes.push(new HuffmanLine([i, codeLength, 0, 0]));
  2232. i++;
  2233. }
  2234. }
  2235. reader.byteAlign();
  2236. const symbolIDTable = new HuffmanTable(codes, false);
  2237. // 7.4.3.1.6 Text region segment Huffman table selection
  2238. let customIndex = 0,
  2239. tableFirstS,
  2240. tableDeltaS,
  2241. tableDeltaT;
  2242. switch (textRegion.huffmanFS) {
  2243. case 0:
  2244. case 1:
  2245. tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
  2246. break;
  2247. case 3:
  2248. tableFirstS = getCustomHuffmanTable(
  2249. customIndex,
  2250. referredTo,
  2251. customTables
  2252. );
  2253. customIndex++;
  2254. break;
  2255. default:
  2256. throw new Jbig2Error("invalid Huffman FS selector");
  2257. }
  2258. switch (textRegion.huffmanDS) {
  2259. case 0:
  2260. case 1:
  2261. case 2:
  2262. tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
  2263. break;
  2264. case 3:
  2265. tableDeltaS = getCustomHuffmanTable(
  2266. customIndex,
  2267. referredTo,
  2268. customTables
  2269. );
  2270. customIndex++;
  2271. break;
  2272. default:
  2273. throw new Jbig2Error("invalid Huffman DS selector");
  2274. }
  2275. switch (textRegion.huffmanDT) {
  2276. case 0:
  2277. case 1:
  2278. case 2:
  2279. tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
  2280. break;
  2281. case 3:
  2282. tableDeltaT = getCustomHuffmanTable(
  2283. customIndex,
  2284. referredTo,
  2285. customTables
  2286. );
  2287. customIndex++;
  2288. break;
  2289. default:
  2290. throw new Jbig2Error("invalid Huffman DT selector");
  2291. }
  2292. if (textRegion.refinement) {
  2293. // Load tables RDW, RDH, RDX and RDY.
  2294. throw new Jbig2Error("refinement with Huffman is not supported");
  2295. }
  2296. return {
  2297. symbolIDTable,
  2298. tableFirstS,
  2299. tableDeltaS,
  2300. tableDeltaT,
  2301. };
  2302. }
  2303. function getSymbolDictionaryHuffmanTables(
  2304. dictionary,
  2305. referredTo,
  2306. customTables
  2307. ) {
  2308. // 7.4.2.1.6 Symbol dictionary segment Huffman table selection
  2309. let customIndex = 0,
  2310. tableDeltaHeight,
  2311. tableDeltaWidth;
  2312. switch (dictionary.huffmanDHSelector) {
  2313. case 0:
  2314. case 1:
  2315. tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
  2316. break;
  2317. case 3:
  2318. tableDeltaHeight = getCustomHuffmanTable(
  2319. customIndex,
  2320. referredTo,
  2321. customTables
  2322. );
  2323. customIndex++;
  2324. break;
  2325. default:
  2326. throw new Jbig2Error("invalid Huffman DH selector");
  2327. }
  2328. switch (dictionary.huffmanDWSelector) {
  2329. case 0:
  2330. case 1:
  2331. tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
  2332. break;
  2333. case 3:
  2334. tableDeltaWidth = getCustomHuffmanTable(
  2335. customIndex,
  2336. referredTo,
  2337. customTables
  2338. );
  2339. customIndex++;
  2340. break;
  2341. default:
  2342. throw new Jbig2Error("invalid Huffman DW selector");
  2343. }
  2344. let tableBitmapSize, tableAggregateInstances;
  2345. if (dictionary.bitmapSizeSelector) {
  2346. tableBitmapSize = getCustomHuffmanTable(
  2347. customIndex,
  2348. referredTo,
  2349. customTables
  2350. );
  2351. customIndex++;
  2352. } else {
  2353. tableBitmapSize = getStandardTable(1);
  2354. }
  2355. if (dictionary.aggregationInstancesSelector) {
  2356. tableAggregateInstances = getCustomHuffmanTable(
  2357. customIndex,
  2358. referredTo,
  2359. customTables
  2360. );
  2361. } else {
  2362. tableAggregateInstances = getStandardTable(1);
  2363. }
  2364. return {
  2365. tableDeltaHeight,
  2366. tableDeltaWidth,
  2367. tableBitmapSize,
  2368. tableAggregateInstances,
  2369. };
  2370. }
  2371. function readUncompressedBitmap(reader, width, height) {
  2372. const bitmap = [];
  2373. for (let y = 0; y < height; y++) {
  2374. const row = new Uint8Array(width);
  2375. bitmap.push(row);
  2376. for (let x = 0; x < width; x++) {
  2377. row[x] = reader.readBit();
  2378. }
  2379. reader.byteAlign();
  2380. }
  2381. return bitmap;
  2382. }
  2383. function decodeMMRBitmap(input, width, height, endOfBlock) {
  2384. // MMR is the same compression algorithm as the PDF filter
  2385. // CCITTFaxDecode with /K -1.
  2386. const params = {
  2387. K: -1,
  2388. Columns: width,
  2389. Rows: height,
  2390. BlackIs1: true,
  2391. EndOfBlock: endOfBlock,
  2392. };
  2393. const decoder = new CCITTFaxDecoder(input, params);
  2394. const bitmap = [];
  2395. let currentByte,
  2396. eof = false;
  2397. for (let y = 0; y < height; y++) {
  2398. const row = new Uint8Array(width);
  2399. bitmap.push(row);
  2400. let shift = -1;
  2401. for (let x = 0; x < width; x++) {
  2402. if (shift < 0) {
  2403. currentByte = decoder.readNextChar();
  2404. if (currentByte === -1) {
  2405. // Set the rest of the bits to zero.
  2406. currentByte = 0;
  2407. eof = true;
  2408. }
  2409. shift = 7;
  2410. }
  2411. row[x] = (currentByte >> shift) & 1;
  2412. shift--;
  2413. }
  2414. }
  2415. if (endOfBlock && !eof) {
  2416. // Read until EOFB has been consumed.
  2417. const lookForEOFLimit = 5;
  2418. for (let i = 0; i < lookForEOFLimit; i++) {
  2419. if (decoder.readNextChar() === -1) {
  2420. break;
  2421. }
  2422. }
  2423. }
  2424. return bitmap;
  2425. }
  2426. class Jbig2Image {
  2427. parseChunks(chunks) {
  2428. return parseJbig2Chunks(chunks);
  2429. }
  2430. parse(data) {
  2431. if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("IMAGE_DECODERS")) {
  2432. throw new Error("Not implemented: Jbig2Image.parse");
  2433. }
  2434. const { imgData, width, height } = parseJbig2(data);
  2435. this.width = width;
  2436. this.height = height;
  2437. return imgData;
  2438. }
  2439. }
  2440. export { Jbig2Image };