jbig2.js 74 KB

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