diff --git a/CHANGELOG.md b/CHANGELOG.md index f7f074fed..8344bf2d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * **Update encoders to leverage dataclasses** All encoders now follow a class approach which get annotated with the dataclass decorator. Similar to the connectors, it uses a nested dataclass for the configs required to configure a client as well as a field/property approach to cache the client. This makes sure any variable associated with the class exists as a dataclass field. ### Features + +* **Store base64 encoded image data in metadata fields.** Rather than saving to file, stores base64 encoded data of the image bytes and the mimetype for the image in metadata fields: `image_base64` and `image_mime_type` (if that is what the user specifies by some other param like `pdf_extract_to_payload`). This would allow the API to have parity with the library. ### Fixes diff --git a/example-docs/embedded-images-tables.jpg b/example-docs/embedded-images-tables.jpg new file mode 100644 index 000000000..0445e7358 Binary files /dev/null and b/example-docs/embedded-images-tables.jpg differ diff --git a/example-docs/embedded-images-tables.pdf b/example-docs/embedded-images-tables.pdf new file mode 100644 index 000000000..fcf1c483d --- /dev/null +++ b/example-docs/embedded-images-tables.pdf @@ -0,0 +1,944 @@ +%PDF-1.7 +% +1 0 obj +<< /MarkInfo << /Marked true >> /Metadata 3 0 R /Names 4 0 R /OpenAction [ 5 0 R /FitH 804 ] /Outlines 6 0 R /PageLabels << /Nums [ 0 << /S /D /St 4 >> ] >> /PageLayout /SinglePage /PageMode /UseOutlines /Pages 7 0 R /StructTreeRoot 9 0 R /Threads 12 0 R /Type /Catalog >> +endobj +2 0 obj +<< /Author (Omotayo Sanni) /CreationDate (D:20181229014113+05'30') /Creator (Elsevier) /CrossMarkDomains#5b1#5d (elsevier.com) /CrossMarkDomains#5b2#5d (sciencedirect.com) /CrossmarkDomainExclusive (true) /CrossmarkMajorVersionDate (2010-04-23) /ElsevierWebPDFSpecifications (6.5) /Keywords (Corrosion; Stainless steel; Inhibitor; Sulphuric acid) /ModDate (D:20181229014113+05'30') /Subject (Data in Brief, 22 \(2018\) 451-457. doi:10.1016/j.dib.2018.11.134) /Title (Data on environmental sustainable corrosion inhibitor for stainless steel in aggressive environment) /doi (10.1016/j.dib.2018.11.134) /robots (noindex) >> +endobj +3 0 obj +<< /Subtype /XML /Type /Metadata /Length 7222 >> +stream + + + + + application/pdf + doi:10.1016/j.dib.2018.11.134 + + + Data on environmental sustainable corrosion inhibitor for stainless steel in aggressive environment + + + + + Omotayo Sanni + Abimbola Patricia I. Popoola + + + + + Corrosion + Stainless steel + Inhibitor + Sulphuric acid + + + + + Elsevier Inc. + + + + + Data in Brief, 22 (2018) 451-457. doi:10.1016/j.dib.2018.11.134 + + + + + journal + Data in Brief + © 2018 Published by Elsevier Inc. + 2352-3409 + 22 + 451-457 + 451 + 457 + 10.1016/j.dib.2018.11.134 + https://doi.org/10.1016/j.dib.2018.11.134 + + + 2010-04-23 + true + 10.1016/j.dib.2018.11.134 + + + elsevier.com + sciencedirect.com + + + + + 6.5 + 10.1016/j.dib.2018.11.134 + 2010-04-23 + true + noindex + + + elsevier.com + sciencedirect.com + + + + + VoR + + + Elsevier + 2018-12-29T01:41:13+05:30 + 2018-12-29T01:41:13+05:30 + 2018-12-29T01:41:13+05:30 + + + True + + + Corrosion; Stainless steel; Inhibitor; Sulphuric acid + + + uuid:18e6e669-c7d1-4a60-a50c-831986980914 + uuid:efa1ddba-863c-4c08-90fd-8204df8d3708 + + + + + + http://creativecommons.org/licenses/BY-NC-ND/4.0/ + + + + + + + + + + + + + + + + + + + + + + + + + + + +endstream +endobj +4 0 obj +<< /Dests 13 0 R /EmbeddedFiles 14 0 R /JavaScript 15 0 R >> +endobj +5 0 obj +null +endobj +6 0 obj +<< /Count 9 /First 16 0 R /Last 16 0 R >> +endobj +7 0 obj +<< /Count 1 /Kids [ 17 0 R ] /Type /Pages >> +endobj +8 0 obj +<< /Type /ObjStm /Length 152 /Filter /FlateDecode /N 3 /First 17 >> +stream +x=A +0E/u!I6B)TZ ijR흤n͟!$ JpeR j3e qzѭ3Aޅwֳnڌؓ9>Bl>d=ʫ YT \(qG__MO\Wm4endstream +endobj +12 0 obj +[ 18 0 R ] +endobj +13 0 obj +<< /Kids [ 19 0 R ] >> +endobj +14 0 obj +<< >> +endobj +15 0 obj +<< >> +endobj +16 0 obj +<< /Count 8 /Dest /First 20 0 R /Last 21 0 R /Parent 6 0 R /Title >> +endobj +17 0 obj +<< /Annots [ 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R ] /B [ 28 0 R ] /Contents 29 0 R /CropBox [ 0 0 467.716 680.315 ] /MediaBox [ 0 0 467.716 680.315 ] /Parent 7 0 R /Resources 30 0 R /Rotate 0 /Type /Page >> +endobj +18 0 obj +<< /F 31 0 R /I << /Title >> >> +endobj +19 0 obj +<< /Limits [ ] /Names [ 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R 64 0 R 65 0 R 66 0 R ] >> +endobj +20 0 obj +<< /Dest /Next 67 0 R /Parent 16 0 R /Title >> +endobj +21 0 obj +<< /Dest /Parent 16 0 R /Prev 68 0 R /Title >> +endobj +22 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 168.831 282.671 189.638 290.608 ] /Subtype /Link /Type /Annot >> +endobj +23 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 312.321 271.275 336.472 279.269 ] /Subtype /Link /Type /Annot >> +endobj +24 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 341.178 271.275 345.94 279.269 ] /Subtype /Link /Type /Annot >> +endobj +25 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 217.644 259.937 241.568 267.931 ] /Subtype /Link /Type /Annot >> +endobj +26 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 261.014 259.937 265.776 267.931 ] /Subtype /Link /Type /Annot >> +endobj +27 0 obj +<< /Border [ 0 0 0 ] /Dest /Rect [ 272.013 214.526 292.479 222.463 ] /Subtype /Link /Type /Annot >> +endobj +28 0 obj +<< /N 69 0 R /P 17 0 R /R [ 37 212 425 309 ] /T 18 0 R /V 70 0 R >> +endobj +29 0 obj +<< /Filter /FlateDecode /Length 3157 >> +stream +hYےTx\&8ˣ%QYnŮIA6{szfpRkT%/8陾>=X}yͳqfz3ݼ[R82l-QVd{i 7k.wT,5y/Enͩ0Du{XׇSW@$V !J4shMj>8 K혇Ö/mI0}?4[ +iSïuu.Y\Z^ʼjG' 9VIm>.6Ƕ|+sOUsGB 5xOh<WFĚRp޺\،+k(2sQ|!©w,h4hMVm`iLvkH ao:{ChBͱ=ݾ(n$(e\s1'ṴqI:s6h ̰).cJWVW/ +<@"n"#>4qonMa<RgHS”uB3Ikž6]Ѿ/x5j}iS|6T@zZ2DЬ=ф{w]ܯLcW}(D@lRPI%C)R_|V."=Hش`y@LJkSA܎w*,+RitjpP!ARi9(eNTCKv&1Q(R3ړEja cn1Q(:ag(cF\uY% +=3B$O/bq-W_ p%yQ(pa;M}S{pR>YvK¼6sU,e»+ rx/xj |-/by35aBS.Zb`c+ PM߯>PEBU]ҐKFh/aŒ3f+dp1UTA?N^N2x*h3=B^R 9HDYPV{Fd@F+t# C%sU9aQ%32Q-]Z2bT UMU~m&G .h4@W2L'Q3aL42S)r'<%)99KOB'@ԏUW %TI[9bpY_-lɂDᏄ=),cAQڸ6SPzP +$%G(Ld\"&Y0%TZkm!D</'ߣf N̡!#z<2,MBުGS2t>lNiyAS(rGkjo!Ee؀o6RH31U!Vn둡ȺB_@O.}>t߶nc4JZܛʦE n@^0-{l&NVVL328|e/z7/=s={|!i,޻>Z -Ex  >?^_1&5猬oS.(Z6W`I.*ÐLCjRi( }5ogĈbq8bxm,L|Q,JKXG#'plJwgT9sRy:=}{࠰잛\}Fe*eEydGÝ ,dIe|"{9Rҗ4e܉uò @W4۔,^L&K(܃IMwqV E=HKai~r\?C%tf\!T#}D$W]RRCAFQ(+_YM'^/'tV8j`,9vz<[M?H'{/~ﯕs~O>OBo ͱ%|cc*zc o˞^WCyDcB n_O6޵h+bWEh wMSKMRŢb, +taE?d&p*>WUD*y NOendstream +endobj +30 0 obj +<< /ColorSpace << /Cs8 71 0 R >> /ExtGState << /GS1 72 0 R /GS2 73 0 R >> /Font << /F1 74 0 R /F10 75 0 R /F11 76 0 R /F12 77 0 R /F13 78 0 R /F3 79 0 R /F5 80 0 R /F7 81 0 R >> /ProcSet [ /PDF /Text /ImageC ] /Properties << /MC10 82 0 R /MC9 83 0 R >> /XObject << /Im4 84 0 R >> >> +endobj +31 0 obj +<< /N 85 0 R /R [ 43 605 431 620 ] /T 18 0 R /V 86 0 R >> +endobj +32 0 obj +<< /D [ 87 0 R /FitR 46 555 428 555 ] >> +endobj +33 0 obj +<< /D [ 5 0 R /FitR 0 433 468 433 ] >> +endobj +34 0 obj +<< /D [ 87 0 R /FitR 0 406 468 406 ] >> +endobj +35 0 obj +<< /D [ 87 0 R /FitR 0 390 468 390 ] >> +endobj +36 0 obj +<< /D [ 87 0 R /FitR 0 374 468 374 ] >> +endobj +37 0 obj +<< /D [ 87 0 R /FitR 0 358 468 358 ] >> +endobj +38 0 obj +<< /D [ 87 0 R /FitR 0 334 468 334 ] >> +endobj +39 0 obj +<< /D [ 5 0 R /FitR 40 104 434 95 ] >> +endobj +40 0 obj +<< /D [ 88 0 R /FitR 0 303 468 303 ] >> +endobj +41 0 obj +<< /D [ 88 0 R /FitR 0 241 468 241 ] >> +endobj +42 0 obj +<< /D [ 88 0 R /FitR 0 200 468 200 ] >> +endobj +43 0 obj +<< /D [ 89 0 R /FitR 34 216 440 34 ] >> +endobj +44 0 obj +<< /D [ 90 0 R /FitR 34 630 440 448 ] >> +endobj +45 0 obj +<< /D [ 90 0 R /FitR 34 462 440 251 ] >> +endobj +46 0 obj +<< /D [ 17 0 R /FitR 34 630 440 428 ] >> +endobj +47 0 obj +<< /D [ 17 0 R /FitR 34 215 440 41 ] >> +endobj +48 0 obj +<< /D [ 91 0 R /FitR 34 630 440 428 ] >> +endobj +49 0 obj +<< /D [ 91 0 R /FitR 34 431 440 240 ] >> +endobj +50 0 obj +<< /D [ 91 0 R /FitR 34 243 440 52 ] >> +endobj +51 0 obj +<< /D [ 88 0 R /FitR 34 536 440 397 ] >> +endobj +52 0 obj +<< /D [ 87 0 R /FitR 46 430 428 430 ] >> +endobj +53 0 obj +<< /D [ 89 0 R /FitR 0 288 468 288 ] >> +endobj +54 0 obj +<< /D [ 88 0 R /FitR 0 618 468 618 ] >> +endobj +55 0 obj +<< /D [ 88 0 R /FitR 0 597 468 597 ] >> +endobj +56 0 obj +<< /D [ 88 0 R /FitR 0 398 468 398 ] >> +endobj +57 0 obj +<< /D [ 88 0 R /FitR 0 148 468 148 ] >> +endobj +58 0 obj +<< /D [ 87 0 R /FitR 0 493 468 493 ] >> +endobj +59 0 obj +<< /D [ 87 0 R /FitR 46 493 428 493 ] >> +endobj +60 0 obj +<< /D [ 88 0 R /FitR 40 148 423 148 ] >> +endobj +61 0 obj +<< /D [ 88 0 R /FitR 40 398 423 398 ] >> +endobj +62 0 obj +<< /D [ 88 0 R /FitR 40 597 423 597 ] >> +endobj +63 0 obj +<< /D [ 88 0 R /FitR 40 618 423 618 ] >> +endobj +64 0 obj +<< /D [ 89 0 R /FitR 40 288 423 288 ] >> +endobj +65 0 obj +<< /D [ 17 0 R /FitR 34 440 440 305 ] >> +endobj +66 0 obj +<< /D [ 5 0 R /FitR 46 528 428 528 ] >> +endobj +67 0 obj +<< /Count 3 /Dest /First 92 0 R /Last 93 0 R /Next 94 0 R /Parent 16 0 R /Prev 20 0 R /Title >> +endobj +68 0 obj +<< /Dest /Next 21 0 R /Parent 16 0 R /Prev 94 0 R /Title >> +endobj +69 0 obj +<< /N 95 0 R /R [ 37 538 425 620 ] /T 18 0 R /V 28 0 R >> +endobj +70 0 obj +<< /N 28 0 R /R [ 43 50 431 254 ] /T 18 0 R /V 96 0 R >> +endobj +71 0 obj +[ /Separation /mac_blue /DeviceCMYK 97 0 R ] +endobj +72 0 obj +<< /OP false /OPM 1 /SA false /SM 0.02 /Type /ExtGState /op false >> +endobj +73 0 obj +<< /OP false /OPM 1 /SA true /SM 0.02 /Type /ExtGState /op false >> +endobj +74 0 obj +<< /BaseFont /IHEODF+AdvOT863180fb /Encoding /WinAnsiEncoding /FirstChar 37 /FontDescriptor 98 0 R /LastChar 122 /Subtype /Type1 /Type /Font /Widths [ 614 687 0 364 364 0 0 229 406 229 343 572 572 572 572 572 572 572 572 572 572 343 343 0 0 0 0 781 656 593 593 708 562 500 697 739 302 0 645 489 927 729 708 562 0 614 520 552 708 656 1041 666 614 0 354 0 354 0 500 0 510 572 468 593 520 322 541 604 291 302 552 291 916 604 562 593 583 406 437 364 593 541 854 552 541 489 ] >> +endobj +75 0 obj +<< /BaseFont /IHEOLK+AdvMacMthSyN /Encoding 99 0 R /FirstChar 1 /FontDescriptor 100 0 R /LastChar 254 /Subtype /Type1 /ToUnicode 101 0 R /Type /Font /Widths [ 500 0 781 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 781 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 333 0 0 0 0 0 0 0 0 0 0 0 0 0 781 ] >> +endobj +76 0 obj +<< /BaseFont /IHEONL+ArialMT /Encoding /WinAnsiEncoding /FirstChar 32 /FontDescriptor 102 0 R /LastChar 121 /Subtype /Type1 /Type /Font /Widths [ 278 0 0 0 0 889 0 0 333 333 0 0 0 0 278 278 556 556 556 556 556 556 556 556 556 556 0 0 0 0 0 0 0 0 0 722 0 667 0 0 722 278 0 0 0 0 0 0 0 0 0 0 611 0 0 944 0 0 0 0 0 0 0 0 0 556 556 500 0 556 278 556 556 222 0 0 222 833 556 556 556 0 333 500 278 556 0 0 500 500 ] >> +endobj +77 0 obj +<< /BaseFont /IHEONM+AdvOTb92eb7df.I+20 /Encoding /WinAnsiEncoding /FirstChar 150 /FontDescriptor 103 0 R /LastChar 150 /Subtype /Type1 /Type /Font /Widths [ 572 ] >> +endobj +78 0 obj +<< /BaseFont /IHEPFJ+AdvOT8b40f9c2.B+03 /Encoding 104 0 R /FirstChar 1 /FontDescriptor 105 0 R /LastChar 1 /Subtype /Type1 /ToUnicode 106 0 R /Type /Font /Widths [ 760 ] >> +endobj +79 0 obj +<< /BaseFont /IHEOEG+AdvOTb92eb7df.I /Encoding /WinAnsiEncoding /FirstChar 40 /FontDescriptor 107 0 R /LastChar 122 /Subtype /Type1 /Type /Font /Widths [ 364 375 0 0 218 406 218 312 552 552 552 552 552 552 0 552 0 552 312 0 0 0 0 0 0 604 572 572 687 531 0 0 0 291 0 614 0 885 0 677 531 0 583 489 510 677 0 979 0 0 0 0 0 0 0 0 0 531 0 447 552 479 291 510 562 281 0 0 270 854 572 531 552 0 395 406 343 572 510 802 489 520 447 ] >> +endobj +80 0 obj +<< /BaseFont /IHEOEI+AdvOT863180fb+20 /Encoding /WinAnsiEncoding /FirstChar 147 /FontDescriptor 108 0 R /LastChar 150 /Subtype /Type1 /Type /Font /Widths [ 427 427 0 572 ] >> +endobj +81 0 obj +<< /BaseFont /IHEOFK+AdvOTb83ee1dd.B /Encoding /WinAnsiEncoding /FirstChar 40 /FontDescriptor 109 0 R /LastChar 122 /Subtype /Type1 /Type /Font /Widths [ 364 364 0 0 250 0 250 281 0 572 572 572 572 572 572 572 572 572 0 0 0 0 0 0 0 666 0 593 718 593 541 0 0 343 0 0 0 0 0 0 625 0 656 520 562 0 666 0 0 0 0 0 0 0 0 0 0 541 604 489 614 531 375 562 645 322 0 625 322 968 645 604 614 0 447 447 395 635 0 854 552 541 500 ] >> +endobj +82 0 obj +<< /Metadata 110 0 R >> +endobj +83 0 obj +<< /Author (Nisha Ray) /Creator (Adobe Illustrator\(R\) 14.0) /Metadata 111 0 R /Title (gr5.eps) >> +endobj +84 0 obj +<< /BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter /DCTDecode /Height 673 /Subtype /Image /Type /XObject /Width 1001 /Length 41478 >> +stream +Adobed    +  $$''$$53335;;;;;;;;;;  %% ## ((%%((22022;;;;;;;;;;"? +  +  3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?TI%)$IJI$R?e˾就~^~^EWY-y $CHM_aq:Οz\3=9]BUW8^J?a+pz{Q?j}WͯfgN~` 9rFоtfqІ+ɝf0qmz]OF$mTWfצ ƎcRI(Ŭs⒙$:ScѺx톷1\⒝I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJXZ~tul&~k}g:s$Sg!6:#tMG}AW[tdkLkk3@"EzpbSܜ|6s5kvݚ3H9@@Y/K?Ms:O?)y mJ#YXGOm{]p E}S윬6ssp?t>Byx[zF?,z I1xN_y[O[⒝ĒI%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%1w_XU))I$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IHrr*7dkuW-ݫ\ 'Ay~F@==;[St:X  xC^ƿb1Dz}I$;V/orw?>5?JwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$SA~:-:2}Js%ϫ+,Rުp Qġk9K"?ĿYv=s֘$@> +I"uwuf%/ s1/siw[[⒝ĒI%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$_/;  A=Յu~XłVˈ`.r+2LB&G`_VEb\".{Mη0GzKL$%!RI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$;V/orw_$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$.hl cRy߂`$t˙$te滗fJI$TI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JbXU+iA~3RSI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$??]R`r,:P\s?P\ P$ + ϓ$ +02͋LO N Ij #\O[K:n?O.ʌ8p+K̎k뻧ۅN&\u@ KC^$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI%cvIM.g:h+zm2:V?)$`5d㾦5E+WZټR=/%+\/%]2yCI$c*I$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IK8I khϒGΛߪ[/`ՁbOR@ͮj0N#p2}|¯KbƩ[WZcVf i_Wex``0F:?r (ڝe/3TttNx]7OulȤשyV}Z/^l81I^udװXvNx{}ŬsHyzPi{F N/./ľ }-}+Y%;$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$([>SME iq%#3ɖ#]E>wcb4>uc7}`hm4gNUo%Z3~oE IL_Kes/eI$U$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$:}C-iq$)ӺHeǧW_ӝ3Ô +Iv=W\WsovFV7\\ JpzugL`*I  eu:$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJP&tSLb "̯f~:(:r'iug]L@T,sCO88$\z>ѫ$r8jDcCBII$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%1w_XU))I$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)a}`VjnG-?Ig*fR2cDq01/kX t`Ю}LoquA<39Yϩͱn1[&;W9oah|jI$*I$RI$I%)$IJI%ngGM +1 ЁF蔄EIy8]gȥY?*odb<_OIy8]gȥY?)}'^aY?)|_t௼C|]?\d^D!.[$A$zzzJ~N]kku?.wGռ>MwUdIcUYxMoC}s ey@U~}lWÔKyS$16Ɔ5F4YTuY`+!׆9KIS2u+&z=, (7X <O\t|1y%"<m}Lu.g뮁M3%RI$aRI$I$$I)I$JR uf``A:%0ˢI?[C?r_7$~UC?r_7$~UC?raמIdQ!" +Y}{bٕsj.<-E~tcl.gH, =5n7>v4f`e>䷨JvZx[};]}]鹕c2mf[$Gե׾tS*a; ̀"|28eXN^OWqS5!t'guZ>1#*;1`ˡM +ۂmw>  ླ[O+mV7 GɮLB"^vbd%* 7dWԮ)9lyΚ΃v ̾tm?lƻ[lYَ$L4~cOؤI1rI$I%9Yrr&]0-~ԫȿc{HlX{MMnõ%׾SYh?Du?g@|-xQ#KGwhNQp-p:.‹ȩR%A VP1zIa4f~<|s| +p@݊@vO|tI1rI$+<4IRAkk[- }ɳ$FDt1:gEzGW'"wmǮH>D&O׀KzvH$OUwmc?c2sO/yl݉OC<zrr:FbU2$L*Fr8Np<1  +j;蟁XU(v>=6/ s1/si>%%;$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$K7zmYEB ȚN77ѴY} \Λ[rGȝRܱh}QϺUa'l~ ţ(`c|O?6xrsuw,oϾuSn7[t+/MTc׿OE##!̭ ȝB(*lu˝u4qc 5G ε~Ұn}O̵,ƙs6#:M" vP Z R +)kNnb*Ku:I&RI$I$wۺvcuw!Y.kr=k|䮝$4#U/VoI$JbXU+iA~3RSI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$}QYx_k)x!G,1 n kpᲸ{xafLlJGE<AsYy-Ѻ-=68{@i"(\O;lmU}O/:}\u\^C~J.pd=l_}'&;\1]<0Y=?5$Jf$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$.{Z%碏OFruU])a%;l!y6^}fI6*y 7c_z7 +`$jiGfwVGq}05&uT8Ina&)$jTI$$I)I$JRI$;V/orw_$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$g9:, ;l]:sZ%XKF+\Nb4\w\A6@J7N Xy.Ueg~x٩s4pO's}VNxx 7{y-qetUkG~k4y%rr^hDӐKh<ONSW]/l9"!R\sS?]t +.[y3s?dRI$aRI$I$$I)I$JRb@Lvu5=œ3BRlq^ԯޗ_xI)^[}ԯޗ_xIO\U>WKԯ޼Rz?$Kk+?s?.GZ9g٠s矚1d +YV%6mm' +|Nc׎}K@wLR$@o/u-1@ rk_NUMf(' A=WfkM \7FS*􆕀BkMYVCwJ2>7ET56K5q= +k>6U-[D/SO 8FjI$RI%)$IJI$R1~&Ugvk vy9X~q^q:~u,kt.x|"Sغ4#9|0y3>AqsL@}\Ͽt\\rh; +݇[^[=K +:|1VA?]TI1rI$I%)$IJI$S| +_q[O[⒝ĒI%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI1 jRR +` +WwǀM +M1 &r~0!dcysXp{ + sx/%A/4;%deo¬_ȅUr;]u?%Oi(#Hv Ϭ=G6Xol:er_+!;j=`Ǖ> 3 C\F4CDzK̈́~\TΜ6%>\Q%rz+\kv>0`uX >D]nfu˞wOXq1g?C.ZMuOWP]] /bFsuk[BayiȊ}t,\g&;XSA1o[r<ԒI)TI$$I)I$JRI$E ? } ?%I=bg/bg$\GCL_,4%L_,4#$+(~ɋ6SMͱM$g+?EϴߣD I +P5]/QqT;swA9U~[Ҭ`Ϧc㴅3:oYhf_Wp &O<8TcZ[*$42tQ:b\u.?2}Z=G]538v*i#f^YAI$b$I)I$JRI$?W-W]3\XybV83^se▗mxgꇮ7*UN,w 0؟\ p|oR#Ku)^кs_Js͎/-73у[8?V2z%d%L8tfqǽ餒ݑ]MFHN֗81)γjWѫO/wH?ma'ǠtGX7kJ"2&fcMw3Q@S$y}jCC&I-̖bے-|[I@KyT%\P&:~VYc~_ F}̊c{w5v] du<dc;5:g=ŷYulq&4u^ۗ6v}r k4OU{_XO@I%p@"㯢Ba}ܦ^~;O?r_+~xi/4C_%?K<xO?r_+_xi/7oמ~So.{82X~iy= .[:3U w>@zIpV<\G X:?h |T21^I@u87P_԰+w|מ[_A?5VY~)~\DG>WѰ?U~׻pΥ;pN +^+xo}&T:I-$' :MOg^_Gts# zQm'xU5Ճsի3UNXN?']e;\1cW\,a9- ´Wnw0U$ߐΪ{?%<#>^mpoiVOu-ţi?ܸXP&,1s윷2#xqod}mO|˯9SZw:Z c~/F-Da)x\> OCd!Q]En=,WFO-K59|s eCIXk1@:c9!/;oSbk>?;V+͉gS-85:C#d(LxVCj Qѫg֮5ހ:o]ѵJh_W:p;M@RC_4~aUq+S>!7ݻOp}txAXyWmzbã<G;frquy,R c?R?Te mdwZ*/PpbBYFĩ$R)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%0[[nc8xuS:oSgXN14Hs`W|i#bџh <0()=\f Pu+⡏kmJ3LF^zO]|6+~хGFū[{}V+[Y& ab9]iuxDra1mT +et2h②FvIVR9kn?T܇=奡"şM7W3&eMisvSfv7k1cCZĈҘ=jkQ($I,~b}Vk,ÕXU))I$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$R^GPv=ZxV:" ˆL >/o9pz~YC}Kb316kXܕgYe7Dev$ه`?!أO{u\_>*H#{1atSB+4_s>]c;(C)MԏCol'wST ca.>BTɳO=BOպ .9$z/[<# x^IwQ97\WA:+cev0|9sM@Ǟe1?v }Lp~_R~|X>Z8zxJ,-ug_~Cqq2ʜ@9(|Ch3-@jWNqMQzc@-y-JG9k e-I߫zh_ 9Sqd2^l,\NjO~8yr[zߩu#/nyb(Lv$t'*k0ku_1Oe}UϭP陇30=XPN');j;z_oޫy?Ώ9:]cXE?g/KO~5%6/}` Cb9I\u*\%m§l{\BÔ lC|T aÔo FlGi[3%IoPm9,a.]}OV֬rswtpK5&݇r/ p4NU@ VH Ɛ t#u$HI$JRI$I$$I)I$JRI$I$$I)I$JRI&s. 蒗I 宒ܟm z [sD zHVMrc n#~,)4|IYtA*I$RI$I%)$IJI$S1U=61$UuL I݄S:#;;W18R r',oP´z겺w[0?hGWH#H<~D ?$IRI$I$$I)KϿOEm.։1㦫˯ ܫ,yfg?;IK Y >{y2 Hs +ﭝePp{D߳:V6 ɥ7{gF[m Wsoعy[Xs%L? +@4,݉;kԺI$b$I)I$JRI$I$/[⶟+9%;$JRI$I$$I)I.֎&1KsWRƫKrw}`J_˸W }nBR_/+%yw +/X{NF-e/=X?һb6 r{ZkW|}}!qx~Ti3X C5$'̓c b Ǥ{՟{6oWW߾ }F~̓g Xwz{zmDGga~лw烈g;}wwLdV }/~߽^;+em;Ԭo~ciz1fplLwuˏqG,g?r_I}d}K~_c~q1V`nsfL`;r\# ~{],J|ՏOw] LxHr2|J[IщfG}͕{.[ asጧ>KhZHQnۚ~aR,<6q85yy=6;5X'&A£/aҖv!#Goa}_ܭaiC X.pf+x9?o\lm"d:xkIR_*t C +11 4#ZR#PLa}P䱘e-hqEjkx_OjQ8m?\=2ϧm`$\2>hetI$I$RI4/7 +~U.w +t_NEM-pWs)*&@qV浽7Fςw◡c?|4oQwԿzV?ѻKߊ>__7;~i~گs}ՏnR>wUSQ[ jUN:0·G~C?Dps'[pp?u6]Ί`G!8Wu:L5#BLA͐g/JEDIX![s%^78p_%\ϙ[8c9$Gp;<ʴ +ο8arʲO9k}-Ç#GDSSvZcs8Hm{&1$ I\ƆΩYnTt8|;ƪ!i b1tٕCėBGgaJH>Gӛ(v.{L\-Z}=L`D(8Dmdzl +Q8:Qb8ntoxLGb<php"p%1idgn2];PꮬYK8SSB0܉줒I$)$IJI$RI$I%)$IJI$RI$I%)r?]?tv1?Ɏ?3Lw@3%RI$aRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JY 0+g9773SWeYo.\Yanָr%y_.y72 QIn%z/xN5_ag$ZJ:n> NCgw?-TMdo V'bn"{`wƻwRI$^I% ̦۱v8C^;tYrtDJ>q -cvqAY"@090CNV R\sw4{)}V_wUvN0(GP5)zxG.p> ?'Qx.cI$TN\ f%? s1/c+9%;$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$`7X?ZԆ\*#*NdF"$*7Kx>_Lq^|p: 器9O[ghT6)m/R<܏`lD}E`w?m_[z>!2W_ޜ}BއSoW:L9ϟwߦ?DfQ"#+>P9*,zu◭ywK qb;j𥳐W;> ++5[Yr/r_h_<|W ˔v.sr[#k2[7?5_ML'>)%u2XPmw°(SC'|?eq +[#&-Y2ydT5i$%Ջ)cX|GR9OMqw%)ds^,w&>m :eѺ}.v{ҧeCŦX) [&I»uzo$+WqZ|UWtۂ;L^A&A8/VIGrv{?ܼL,8Ouz\^x+I[I$JRI$I$$I)I$JRI$]r~;WVl?}[S?]t &;O忙g$S0$IJI$RI$I%)$IJI$RI$I%)$IJI%~t[l4i?tYtγS Z$HZ)@I$I%)$IJI$RI$^:NWV{1%yK>VQfHvodBdD@2?lh+t|0deVu=g)ߊIIxL{:$IRI$I$$I)I$JbXU+iA~3RSI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)g5!CЧ"HPR?B zDI*Ч^?Je#)ODH +p(]X%$v +A_a/%H>Ë%_a$c)qфË# { /0qфt`bF,V4 +\1CZdK~k;+[K%u'rŊ|)o|7TnL;kz"Atk4J$Dk\r1| F5k8#Ժ>NC,qh‡.JZ{w,#`ӷ$;U{Kێw2no7}ɛm_f~}]]UلK5h$n? RWA4 a`A?/7{<܃iKy_Ҹ/?~⪏wWA4<܃i\z_{X{UG? U:R[9B?}MպoP99s]`F (K0 r~`uszE{a|tϭ?Z[>E=F=rh8}1Z=qwK_K\zcu!:3rZX(~NM취$N εְ~ݓ纽mA)HHG[ֿ. #K3s]Wʽ-/ Ao"K=If_K }Į:T\>P5'7*I$RI%)$IJI$RI$I%)$IJI$RI$I%)$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%) +\{T ũzON" Ϫ3%m$iP SV TevVX-:r{7Ru"u y>}uݭuS Ϫ;8FhoQhwwbv#)TiLkڀSy~`z 8M#! *\W1:'T,ӺN~;_Zqʿ;p }XwHz3Lj<.݀s:fr[7o3zD`QtW5:/S\2^|&f>.3QRG^gXqmvZGL-׫;ms<xV>}gxUU k+՞}zIw9k5]+@=#UJ>>KLHvRL"FQK!.C@܅[b_F#&;}sS?]t 0[?I$I$JRI$I$$I)I$JRI$I$$I)I$JR侰z o}WD h.$(X=FG}Ctg u|1~2RϬ׻?#Oa@#.Ľۮ;#fQQ(UH~kSud?%PS[kS D@ZF#RI$I$JRI$I$$I)I$JRI$n5+_:wH+a˲mpo Y DznEƇML[r^%4䌽7ŧDGUT/=Z^﹍1v= 7.w=7Ljm p7tRI$A~3VbVg/8q$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)3 BOX ;#,reᏝØW}[%heʩ1>-Ǩuqr>xp4!duY?F.o3t̃Ov}'cgpeHKdO 52 +_WzM{y'œE_ch}'GnO4uXTnHs`_!YN"7ۿm:N:Kդä躗>.[ϰe>K}Mj' zJf/C;qVCw=Pϓ~+2lcvh[XHDOoy1#~f''-1}cabeWWN k?H? _,~ܚ r$(Ԛrk00F&$tx]{13Iגd~Uu]m9^[30qϪ_[źǗcI߽>xćEI\Oj.kù\Oj,w?6nG{g뮁sS?]t 0Y=?5$Jf$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRC2\dEaWˬYSiBW^vit߬ 9h~P߮U^^5[/s&g.kvˀ.W־^L\#<7޸b<_(5{>'Q@X ?ZņTA}\'.Ǽ=9RG :_bH>s~uķ_븽sv{N]3#mmm--vOe1z~MYq%O| +LFS7=I=Z8 H +I&"@<ى}Io?~5RSI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)YmLi%eΡv0Ku[ātV=Yt>Σ?`'7䘖8pJzYoT rBZL~*GQeu;49fRVT +O;U?@$ѶC¥wF80`)(k}x'g];xzOϧ?4kƣ6=''"Z(stnnP 0d~ŏݛ8yǘm-Nǯ&hWuwN6Tmt|W:+2hps\5Y[:S:Jm{+YJ8rp44Z_QzZt|: ;miיּgӏCV8p̍~mLH&;\1]o-<椒IL¤I%)$IJI$RI$I%)$IJI$RI$I%)$5tJ)hγJ2~۳:W~fk*=$c?OX]^0<A[bL<%!`A1} Xޡ1 u] |HKp))t4hH +^H(@$o]C7+75 &5]Juz8J⥼^ԒI $I)I$J[FGY7:}VX5+a$]Uz?Kh<~k1[2'hJyu$epG]fӺf`eLmu5֎ +I%fU$I)bVg/8| +_qINI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I) q֙qR>KP~pp]<ausD1sJÂC,{B{dus6v0@ӕcDmI$rԚr\W9t^u5[ncǔva(.^hyGɧ3CO~_wLR'$[}`n"T'!/l}rw?Mo2tX&l9_i컦}fKlXA.DtpEۚHUy/du +']:1]Ɏ\0[=?5$Jf$I)I$JRI$I$,nַn] eeu؝_ia:[drmu'V뛽-߮%@$o|Pg~cuLza$E`ߊpqG NT7Rrifd.73X-.f1&>unFMΪƂyCfMV?J꽀!30sO^j&cƆ@uխ G7_N_ID'Z]ˀ~~qk j}J/0Wyq<=@QzP37__^?R .?\ wsvI1zI$I%)$IJI$RI$I%1w_XU))I$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)V4㺫D額AVR@A6P8Eo׶z&.MyT2̵B>X8[PgV|<,GciRI%uzI$'Ecu^oz ?o Usu =wb>_}yg&3ޡlAVq\q.wHoiDx!cY3 LCMUy!rzLɎ;!-~]&8 + j,Q<@ +I%#I$I%)$IJI$RI$I%)$IJI$RI$;ɬ}m^"I)ѺV5|Jjp1"abf03*^k?t:/NßcF}6܋z=_[o$,{>V[C2e8~($Me?gmMm#OLSc[C֎IM+7IȰ~6Xy{Oꪪu1@h#঒])^,+5.I)I$JRI$I$$I)I$JRJ[=5f~]XtHQ2l$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$S}kUg{ ʿIҩs?H-.1 LBĆN# 1ֱ16E5Zdxt ꃺmkCNl̤D ~GI$I$S~ޯg2vk 7ޛfW:t^m? ɸjOͭ'g뮙s?P]tə'/.t~_OW̩ilfG}eia\6 ;vΙM*KZZ>;t跨 NOl{;30Ode!1 +)w'2cLHh$%:g49 +Ji?{ΡP|]q->J͟WzK<өu*65F2ӤY,nR;/z~?Yq:gRg_]#xDB1טҐ(=]46F -lBH>I)$IJI$RI$I%)$IJI$RI$:I):Z:[c6=j}Zz>srsc|⺴*^I뺒I$A~3VbVg/8q$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IH2ˬsCơS] aq#iLuU)$NRI$}}Ƶލisx0;齻n`B\2.?rVIƺ}f[> Qc[CZ8$%."Ot<1I I$JRI$I$$I)KԳq+ڗ B][lBSeOVL3&%(W+%g%~/};T?_I/=W+._Nӿ;>毿a3<힫ҿ?eϹ/};K9j?_In}W&=;_N)Š56{B~.S,&$rXXg Dbv)}zu>Fiḧggc7k19\ӎ T:}eb`6>''YbUÓM#ixIhYK_P?N&wR[/K\7?y5gقЮBS¾^[+A̚i)$L\I%)$IJI$RI$I%)$IJI$RI$I%)$IL_+9m?;V/orJwI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$uyɳLjp`|f^s^cuʹE.$ԒI $I)I$JRI$I$$I)I$JRI$I$$I)I$JbXU+iA~3RSI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$}G#?'V7BRR&z1HQ稜{vcDh-ϫZXuY}2&šY)9V@KL$25'P πoo#2T{-:|uZ[!7&}ut:[_FGDoݍ;}fO#p_Zn4'v4_:Nͧj.!kz'Qm=FdJUkөSK}a=1.NN+V8qю@`qA#mv$q@MJ+9߬9.h$Nܳ:'YƮ׈.%J{4?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu([..{9qIOFY9gOڴܥ8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isu%8WYrJz?8WYr_u$Isiˡ˰,k.36ƇZA׏%=K}C+/?S$?}C+%=K}C+/?S$?}C+%=K}C+/?S$?}C+%=K}C+/?S$?}C+%=K}C+/?S$?}C+%=K}C+/?S$?-ӗK `X\gSѤ}fͱ;Pu/?S$?}C+%=K}C+/?S$?}C+%=K}C+/?S$?>~?ܒ%OݙI]A\IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$Xļ48y32~S֬k5Ӈ O@}RH1#rV:[t1_`~w":Y̳' Ueރ~8ⷒFZZ\x~v|#{gHkw~辥}[B.l`D:*^I$D +>\;uWTɁi$JRI$I$$I)I$JRI$I$$I)I$JRI$I$,׏ʵ_[,ic:@ǟmf4@$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$׏ʭ?쭖4iBv4@R$JRI$I$$I)I$JRI$I$$I)I$JRI$I$,Ϭs"<Zj/49xIM~?"kZhNI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$JU-k0VMOc_TȢlk'uW < =O))I$I$$I)I$JRI$I$$I)I$n^5.mc %=ƪI)I Y[YkZ؝Q4<IJZ5iS$mL =ySIJI$RI$I%)$IJI$RI$I%)$IJI$R@9a J0 I( jsx峪JfI$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$: ^{հΗuϧ]^\Gri(,!b81T#ɡwDW^ûoüƱzKni]P56,c8mo~WO߲ǻ҈!#d88ʯ*1@Nx!]ۮ;"qpQ_43奔Y.}2+t3wjU7λN%c}F? 8x/WG1p˄~ Cѝׯf}"q0P*<7NûgvWut͇~ +{~Ԙ]k +\enJs 6ph'xNJ_܎c1 .5,-N3Tr,Ty-~K]F-/㽏[pV0h2 ~'lu}d=ke̜\6eX:6P陎/~.9h?c8jWnnVgPne[;}^L8&+·rKYc}D&R˽95#eY:6/Py/v.9h/c㹮nnVwP~8ڷ0oɎCzrUcg޻ GJ;u<ٓCX}9+; +΅KٞI p~Z.nu>K\ #Xc3 pzVqae9Z:o\ceKuж׾z6 .ĤI`s_^(za;N=!(_~I$)$IJI$RI$;蟂EOu[~}hwHӁ՝KjGCW\~%/m_߮ռysMM <N?qkk])w|%/߷F{oqp9(pH2?HF^U:~S~7d7WXx'Ύ﮿X2fEiH?s쳭Q_—x.#H8㗇?E ~}gf5WYwLox'wHw_9lȲ,/EG]/c>#=זh:eߤlKO#T\Gr J DPqq}A'!mcoO矂~{2rpc<9_r^ǿG ;kiz䜵'F]EG$} _Ywft,ﳽ@YYo\ceKuж׾j_O5*׶ +Q2r/\;F#>0*13דJIԖ ~H JA`Y+1 +I$W)$IJI$RI$I%)$IHrn65;@ƒ}T\W&ꏨk6q!Nc%]RN8|806)q,~no.u]]=?d7dhWӫO&䜥>|G1<D@1IW,:].vxs*ՎzMqu$I%wլW5iq]Be1U=|a??d !=?\+q$v=#Y0:]sk#ehD÷3丽8$ k3xk_}y?[rO\ #Xc3 sX$ee>}fqS/\k~+Ѱv%DZ%s?^p`H?鰁Т}H(~AI'I$I%)$IJI$RI$I%)$IJI$R>wM趿Evo.7eޛKΌj=xbvM$\<,8_?i;3#W@#n]&f$8Zv߫\  ?^-1}9 t_^TFfI')I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$$I)I$JRI$I$.;7ޭ.n7P:X#Pv#MGI +!:޲ާ!WQa|`f_=u{K OOܶN.MwnBMuuGu ~D>Rҭ}Wm=Ek^u!HӠ1&^']u>՜ّ' `[n?BήK+y疮,n-`2O0$$@QPV}LgWONy%@<]],fIDC I;:Z׊ޟ;gu:z{,Hyj>XoCx.ߛ&AwH2?5MWKOߪ^zYyΫcEtTw< wֲU4p] +IC{?Qӷ䤒I%)$IJI$RI$I%<֏Yx:[}MVuFu/ ʶ.$|77Rok[댾:`h?rSz}MGCqlN@yП)w !UWzS{ +>}PzsN| *woYoT=KCqn~ѼOt:"Ӳ vx?T:?PwW Ӡ^T=OCqoFH+I# i(peҽxvx-ffyv4@Qg, YӞIeo"@<$E +׋^N x/o]d.> S\Wn^RHHx*'?H=O義tx﫭3 *}t)$II$ RI$I$$I)I$JRI$1Zy}K՜cb^w92wJoM].>}T6׋L"| +N]b1$V~-]uKΟ3L'en"@?,^ҭÿ.2f6#f2gBx0ȉL֊W\1gל1Eakσ\^e0>[(ʱAϼz%#+)p"MDȯr1gqK | Qe<,kp+~>_e-ʭՂ@U'Ruۓ^S~)C~rRǢ`2\~Y~jewÎ.!85v'~2\~[3 WS_s+Kw:]:H$\R2I?Ed NPq>z Ӻ~+2,H3'{mwQg_m@:*GnG>ʺe}RYPsIcχcpksQbNO)'Bs偏]B"O.*rKĕCNcJ.Y[Ksue}UYl6&+@% \RdL}C|8xww4 #Dz]s4cYԺnӲ3m˶} Vgߪh~ϳQ.I vN~SR˩ @g#o!8v 8xV/?[2_c. 9cYgfu8X}?) m 'i_%8nJ'!Nj}5yo=R<`(^ FWϢukl@|0;qqTO!COz$Ys绹tO񟝛NŮg]La}\;m 7IŸ́n=ф,#xሏOR~0qt924:GOa<')KI6k3^>S O:_V3\-:[JP GOQ35),}n:&3s-/`sV.Moki/==s1GOe1T|gwNsqC]3EFc#ǃጥk;#]kp  lhonwHYGQb?"zٝk('Iѳkh$ ?'c旵ȸι+2,^.<87=Kg@ɽT;\<|Wmރrmkkk\LɤA+Xħc]@W}Y_U{줃sYL0t!l[5p~)cIbwN-bua]u|{ՀwX ֿªW}:ˋvvz;pݭ ~E7S{H@=7yu{tڹM]̣0Z*Ȉ5<9W !+=;7O0@-NN]8Y]5]ݕUkvZƽPXccAcD@GCKLDili_T~tY5u"U啗-s }4AyoB#8g$EKYL1oN0m+tKYUV7ek*Xh#Ng 2Aֆ> >W2~'֬ T*;h +'_o֌CDZC-64LׅSUElwZ9zt Gɫ3:n0˦,] ]VR]ǹc+Р.ƨ,o'qK!鐉؍4[C݀|wGS2}.mv92 oNl\͇uzz~Lp'n݁rd 3@h22]DH>oG.99$]Y>atLq~uُF[fϙ^Q^}3 Gܚ\jI4c@C+r/ֈ?ojoo~_YkNQԟgEHk'pek.TlƵTǸp4FqK|DL^ٌDl#Ym#@2t0? YKΤzLr~Ρ%=8Yf}W_Ĵ;"9'a4DeC Ij?^U:Ľ6WCwwiGxsbV#*e]BX@㉯1yd`Ճњ f9V:tƺK :D^kǧ k>VAV?n'r>cey302ؾw+*E,(?ʫz^'W2VưC@ 2k$iw$%<|C ~3|>aR0:VX;7֏g}fzu&6ZǗ$݃Kq<Ɵ_f"^M,1~qUt-ml5;Æ?/Jn=!V4-ho\7H?2xLr$laf0tW'I$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$RI$I%)$IJI$R_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*endstream +endobj +85 0 obj +<< /N 112 0 R /R [ 43 564 431 635 ] /T 18 0 R /V 31 0 R >> +endobj +86 0 obj +<< /N 31 0 R /R [ 43 304 431 432 ] /T 18 0 R /V 113 0 R >> +endobj +87 0 obj +null +endobj +88 0 obj +null +endobj +89 0 obj +null +endobj +90 0 obj +null +endobj +91 0 obj +null +endobj +92 0 obj +<< /Dest /Next 114 0 R /Parent 67 0 R /Title >> +endobj +93 0 obj +<< /Dest /Parent 67 0 R /Prev 114 0 R /Title >> +endobj +94 0 obj +<< /Dest /Next 68 0 R /Parent 16 0 R /Prev 67 0 R /Title >> +endobj +95 0 obj +<< /N 115 0 R /R [ 37 48 425 401 ] /T 18 0 R /V 69 0 R >> +endobj +96 0 obj +<< /N 70 0 R /R [ 37 209 425 290 ] /T 18 0 R /V 116 0 R >> +endobj +97 0 obj +<< /BitsPerSample 8 /Decode [ 0 1 0 1 0 1 0 1 ] /Domain [ 0 1 ] /Encode [ 0 254 ] /Filter /FlateDecode /FunctionType 0 /Range [ 0 1 0 1 0 1 0 1 ] /Size [ 255 ] /Length 659 >> +stream +h,e_Sq}1lccX) +b"*"`wwwwwwwwww8{>B0" PK$bAbax5$A+ L# #$iTfH֪%ʪ68!%ADpzH4CHc24"AaFDq +Z'Q&(ZeR6i=@ECGSG!O)W7@@F( TCI4$DC6V&[h42M42Lm0F˲i q4&D$ko0%BSs4 w Yf¬\h90El0N`1,ɷ|/-p2X+8x%*t5EN^ 늝87ƮM%)[`k7o]wp.{`/+_p{pT(±J/R$8 gRlU\쫸//?2߀}| nWNܯxXgcx2D sxQJVuA~S OyD׆kw0a#ҟWtendstream +endobj +98 0 obj +<< /Ascent 789 /CapHeight 735 /CharSet (/D/a/t/A/r/i/c/l/e/o/n/v/m/s/u/b/h/f/g/O/y/S/comma/P/I/period/p/R/d/three/one/two/zero/eight/seven/N/C/T/six/hyphen/w/parenleft/parenright/z/five/M/H/four/q/nine/percent/x/E/B/Y/colon/slash/j/at/semicolon/k/U/F/W/L/X/bracketleft/bracketright/G/V/K/ampersand/underscore) /Descent -211 /Flags 34 /FontBBox [ -72 -250 1041 979 ] /FontFile3 117 0 R /FontName /IHEODF+AdvOT863180fb /ItalicAngle 0 /StemV 0 /Type /FontDescriptor /XHeight 542 >> +endobj +99 0 obj +<< /Differences [ 1 /C15 3 /C0 188 /onequarter 222 /Thorn 240 /eth 254 /thorn ] /Type /Encoding >> +endobj +100 0 obj +<< /Ascent 0 /CapHeight 0 /CharSet (/C15/C0/eth/Thorn/onequarter/thorn) /Descent 0 /Flags 4 /FontBBox [ 0 -947 1239 708 ] /FontFile3 118 0 R /FontName /IHEOLK+AdvMacMthSyN /ItalicAngle 0 /StemV 0 /Type /FontDescriptor >> +endobj +101 0 obj +<< /Filter /FlateDecode /Length 234 >> +stream +hTP=o 9uD ] PsNH B`gM;GL`F0d4gV#eö${g> +endobj +103 0 obj +<< /Ascent 0 /CapHeight 0 /CharSet (/endash) /Descent 0 /Flags 32 /FontBBox [ -41 -208 885 781 ] /FontFile3 120 0 R /FontName /IHEONM+AdvOTb92eb7df.I+20 /ItalicAngle 0 /StemV 0 /Type /FontDescriptor >> +endobj +104 0 obj +<< /Differences [ 1 /uni03A9 ] /Type /Encoding >> +endobj +105 0 obj +<< /Ascent 0 /CapHeight 0 /CharSet (/uni03A9) /Descent 0 /Flags 4 /FontBBox [ -500 -416 916 937 ] /FontFile3 121 0 R /FontName /IHEPFJ+AdvOT8b40f9c2.B+03 /ItalicAngle 0 /StemV 0 /Type /FontDescriptor >> +endobj +106 0 obj +<< /Filter /FlateDecode /Length 215 >> +stream +hTPj0 +tlq{*Э4dE6s@Oz'cҒ MzGq3@:׮u2E[=Ե4"/yUj -6WnG4 X> +endobj +108 0 obj +<< /Ascent 0 /CapHeight 0 /CharSet (/quotedblleft/quotedblright/endash) /Descent 0 /Flags 32 /FontBBox [ 9 -208 947 781 ] /FontFile3 123 0 R /FontName /IHEOEI+AdvOT863180fb+20 /ItalicAngle 0 /StemV 0 /Type /FontDescriptor >> +endobj +109 0 obj +<< /Ascent 789 /CapHeight 735 /CharSet (/S/p/e/c/i/a/t/o/n/b/l/V/u/f/h/d/one/period/D/F/g/two/three/T/I/r/parenleft/parenright/slash/E/A/m/P/z/s/C/y/four/five/six/seven/eight/x/comma/nine/k/w/R) /Descent -211 /Flags 34 /FontBBox [ -93 -250 1041 989 ] /FontFile3 124 0 R /FontName /IHEOFK+AdvOTb83ee1dd.B /ItalicAngle 0 /StemV 0 /Type /FontDescriptor /XHeight 554 >> +endobj +110 0 obj +<< /Subtype /XML /Type /Metadata /Length 14366 >> +stream + + + + + + + untitled + + + application/postscript + + + 2018-11-29T18:01:25+05:30 + Adobe Illustrator CS4 + 2018-11-29T18:01:25+05:30 + 2018-11-29T18:01:25+05:30 + + + + 256 + 144 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAkAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4qpXN3a2qK9zMkCO6x o0jBAXc0VQWIqzHYDFVDSta0fWLU3ek39vqNqGMZuLSVJ4+a9V5xllqK7jFUZirsVdirsVdirsVd irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqC1P6tW1+s8PR9Y19SnH+6kp9rbFVGQ6EEJ jWyZ+ysY1H3gN+rFWHfmB5m1/RLW0k8teWrHXpppGW4iSeNfTUAFW3VOpxVlqPpZYB4tPVO5WRCf uMY/XirzSXXNeNjeraSXUuqmKd7iOXTbZLaznhjlljis5Wii+srK0axg/veteakgFVlflm6sbnyp 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 + + + + + + Acrobat Distiller 9.0.0 (Windows) + + + + + + saved + xmp.iid:F860A0FDA1F3E811A1EAA43DBDCD17B3 + 2018-11-29T17:20:39+05:30 + Adobe Illustrator CS4 + / + + + converted + from application/postscript to application/vnd.adobe.illustrator + + + saved + xmp.iid:B6A5572BD1F3E811A1EAA43DBDCD17B3 + 2018-11-29T18:01:25+05:30 + Adobe Illustrator CS4 + / + + + + + xmp.iid:F860A0FDA1F3E811A1EAA43DBDCD17B3 + xmp.did:F860A0FDA1F3E811A1EAA43DBDCD17B3 + uuid:9ace12f7-7589-417e-bcc6-e60521b765af + + uuid:9ace12f7-7589-417e-bcc6-e60521b765af + xmp.iid:B6A5572BD1F3E811A1EAA43DBDCD17B3 + xmp.did:B6A5572BD1F3E811A1EAA43DBDCD17B3 + + + False + False + 1 + + 20.008423 + 11.056071 + Picas + + + + + ArialMT + Arial + Regular + Open Type + Version 5.21 + False + arial.ttf + + + + + + Black + + + + + + Default Swatch Group + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + endstream +endobj +111 0 obj +<< /Filter /FlateDecode /Length 455 >> +stream +hn0sIb&h=lTm"WqvLl j= +5AIsTxaf,9l*w‚e A%|IBl-n7wQ/YЦ +ah +Y$ej-{o.xn˯`sx0L"\x~H t枱V Z[QFu`?"LciYyҹ뼲*Afk 3zPNײd ) +QZ}A8Z0t:a}ڐyz-+g=~)Wim6Rˠc*YI`eFϑ[I5F>Y 7OC7JC\awEE_;dڏ){3Dbg蛉^7? 2A& dWY<ܤEϵ'`endstream +endobj +112 0 obj +<< /N 125 0 R /R [ 68 595 408 610 ] /T 18 0 R /V 85 0 R >> +endobj +113 0 obj +<< /N 86 0 R /R [ 43 446 431 495 ] /T 18 0 R /V 126 0 R >> +endobj +114 0 obj +<< /Dest /Next 93 0 R /Parent 67 0 R /Prev 92 0 R /Title >> +endobj +115 0 obj +<< /N 126 0 R /R [ 43 571 431 620 ] /T 18 0 R /V 95 0 R >> +endobj +116 0 obj +<< /N 96 0 R /R [ 37 303 425 426 ] /T 18 0 R /V 127 0 R >> +endobj +117 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 5857 >> +stream +hޜXyXSWmz57tsVRn( +N$ $Ț a IDܪZjVvjN~s.=wvJg>|Osw\O^߆uY#x Ϗro4I?5Ɵzg>}υ5 .^#18x.o%oE1i^T/P$f"y1@" yXN$-2I'H"%ZD'E^?A O"#|?IJ1syBIa LƋf&$R ZKQ)?-l}ZR@D~r8mhWxH)/92q/f$ d>/!(`ܑVmuv[zxz<=yz<7c8+<7_UNV/w q}w8C8{l1J.YTq{ %koz& ;o5h Ec6YB T ^{[gԃs󝳐űn]eEedC7T0W;ڞBj_"؁]{N]rm |!:M, [J \6mxqgp.?AN58|:5h:Fv@Nڲv_nvSiMHYHIċӒCϋoMwB oBlq^}\i5iOB4Fw 6CX E N= Y! ^ᷱS0H6&QUz9,,˝ؑnq;)mUFsqYF |!kOMD[iKow]rUP,܈CM%0k`" S2_Mk=_9r+Hk$47n41"Sn%skSd L60Pxg\-gꇎj͇#fg&)ks8%^L5 9&kB?`r?lSTɸtt:ӒNwK;$LKucch9v䷇EݿA8(-2pMP pp `>}49g.|_1rYA@M[XWE D~#KW'.u@ܾ( lkp8u+2[J + piHX}rE>l*?yV!=UrL0YE¶;XlG8s\NXj  ~YMVeCq #!"Gai\j;*ArM +<" unEJxN:WKJh(x{[I|DVLSh74%H +c5*e*w)@J$Sfzj17U;޽up<: lCŵ'ڵzU^7,")HLM:e#u03 bv0e lE8 x) 'ORvTQ &`ВoAxP6Is+ߠc`*0N +w''`SGߴ||:`3/E4FTC(‹ (څ 8دI&oF.pv9s5K! prI5 RJIF$i9=KZ +UTάP +4ҵiһQ6609>ŏ4;?UqmtVʪ3kF/uІ_1>N)A +ֺjʮV5H{8u`2K[l *BH0S`d[+/RDϕX$p[Ug9J\{aǺ/OK(@@{7UI! *bQv068&5HTUzBNXX]𒝕HD\tj8*ϾG/Oզ@ZQlC1bD=M63/c23bAUĂK BPu4WWvCen#Kp`S[ehwq u s.(vq]W\b6Y59WÈ[[f4]grOh.yiݟŀzp7{>KN XI蕍$p$7="}@> I-ҫդ1>pO?!pjVH6X#;$+(Tr4GKAMSItG1nʡMs:3xּ0agޮa8p-KYK^u -^koB[q=Ѓ š6$XWc9XP8'[i)U?MHzo @E}ǧSIeyFņrq*+:\M[.o-\ɘo%:mv/10.5xlA묧ᙿ8b|E'1 +@  9VXP'x ``|C!b-nĺpM8g8R^HϘi0g>p>gǎS:}35zp*-mzcS$2=^'X,X!k_R`'U5DUNeꄈĄdb1s(˯5Tk籬Cf +L@>E +)b$1#~UoM W(G)r[&<- _y=``){+(b6+4ؚC錆JXSe#zN",JK<i?a`kN! +zm=YtPl}_*FQ+ْ*!ٽ)&g L1KA|tpFPKkOY7^oLҢe8CuOe7ucdqYgE97U ˘΀t9'r?`ڼݱ/KAedJ*R!yYr|K?^hh4q̰e9u5rJ@ 7k+*1B5(dp:ݟW.|;7  lo=1Ϯ$RWzLMe4Ͽ9Z E8rXZ-Ńb7UDY%} z ZR0!IV2S o9͘R+%S뺔GSu]T- bb{ ]p$I9Z7 e.磪8-fSZ>ۧ8Ņj4X6wZco +e-t-CX^cZ^5F0 9z2zS93ɹ"DWߒoXẕ4BY]W5M*1ۘU (/6 L-%ܒsMyfѾF7 0M-JSU&©`=:frVsՌenbJu>)88=|Y`: s-A(<~_?endstream +endobj +118 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 382 >> +stream +hބ1Haǿ/[ :l(L"PNRA|܁D!A"t}@t_>,qv|)Kw2kendstream +endobj +119 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 3839 >> +stream +hތWipgI`Lvg5e)d$!GȲ-Yua٘Keݷ%YdlcLCaȐ! fjkkS;m%wt}_>>=]EZTUUao:ӯKm]+K,kV?z=iUUU5G5b֓{PR($cU H"~M"<;Hא!]Mj"m&6TWYԪ}VW<Қem*>O=Dm +C~ة䵻u^w|뷮쩟ѫ7WomXAZھLY&VT_?i%NQCn.-{)?53(:^cȘG, [J8Fx9GXͫvOM6^ j(5ΠmcE# "AOUE+Jr/y' 8G_9Db@$n)8 +?&>-fV2ͅ--tWm2ۑ~z[s]Dx~}"hjH[!!0f|+r2I>T݈~&ju c.ɻ(8sEMWh͓HoO2f#SEy|w\@g㚔:%}WdAE9" Si{^q8yr4J2)PȪI4WL);@78)Bœϱ0 R];hG(. c Pڗ eCP8RІ|nfӋ3.&҉t(J@I{2_Tw|G}pStyCϛEwn$Y4ʘdq4.r`-DD_b.5ȷO*SB% +QZEUp,Z^ϙ4"OB7!|05 +gimѤQ8hBY| ᇺZǴ'@hҕ٤YA#Jwp-dzPdG,SYxMHܼaP1vܲPgXPulǿ\b_䗰k*hJt4q h~.x:|Ky1L3EtwXQv|er{;A@BOG|L&#|![WTJemlhsMڽfƷ$p;3wI|L#C` +N-V@ڛ"׭]:LE_7I%7LܨQC=ztvQ1p;~Jd=SD+GDnfhl gᕣr&lLBdYO>$8˫iƶטwewB(w\7Ǿ}5e^inCڦw…itld2xN"=1k3TnZc\DkFAw7Zw$䁼QY0"0(e6\Seg7WsRnSZFQ5)!G&^vZ3%]č=fS 05+D!D`dЫE5>k0{xAGל17цMiyepB :32fHc, rCnGZ;QY¸O-2Ɍ?ݴkhehQj+UϹd_hJ /MPw̸Gg!F"Hŭ0x%ݵEyR͢dJ!_۬ȉ%pqޟDõ=z\IoiZlu}KP(Co7Z琹֣`۲:JoQW<Xg9or*Q\:\kԈZ?}EIEXZn (\3~_'_Sar v_ +XA* [h$=_ +Y +Ȉ/ KRK MaēK*ѴYMqC4-NGNzMWuv"Oj-k=hˋJwico +Lfu{Zmw!]")_ƖުR뎑_s_;uhn@w #qT5Tz/*C,rFnrM +[jݦ@OJT~z_ܯEbXք#fȔHSW+55Y??P`~j֨+7Z>P(.?Gȕu`2pа'Äu]K: +h`Fs8e$B38i=e;ջı*z6jlf] +jt%-<էOSJ~A`lYendstream +endobj +120 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 348 >> +stream +hlPJA#(>PQXJ( &@|DN]Fo7‰:=f9qZ獫ˋOz^B1J͊N}ϹBW\~z뜼TS%MRLqD>CJO^K0. :f=8꤅KJG.{r`"X>Ex 4 kR G (7a!>ka(RSSiU`f0b)<"_hC*wu.j6:yN6?#syɯ-eayRf +K? `bendstream +endobj +121 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 448 >> +stream +hބOkAw*-R0:x14lE1DBqăLL,I + ڋ=!x +~/S҈m^yX P +ەf?ym{>jU\/Wײ[ ]\=?<<+=ײٯkeL(qb㔓P2:P10`%XT!bT! @755GQyp!eZj098a*Xv"S".3܎NU3ժ0}1ܼvS0g%613Kb4^̦[&˳!c+féI@kLow +l}W%u*Kg]+zrg{?y|MS[]=U7u|}WuW?C=ХR7^Q[o8/_pu~ 07ڪendstream +endobj +122 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 4943 >> +stream +hޜX TSʹQWɽZ֡*j*""*̄@@@!!!BB$Euz}uؓo^_ʺ7g}{?BaM|R%oYDy~/̜Y;٬'X|[}]'d\I$#"]|`nDMF n2_ΗE\Q*7/NxtL9,w]&s-X4i|)W*J$HRg!?)%S<)1oL ٲ4[(S$>; \$!9%#A P7#!•RYdepٌdG]΍ڸ~mܨmQѡ^kI c=-5 +f^zZbXYYKYV.z"?6NNh҉{nbs)ݓ +&&WM6ck}|GONjzuZ´_'x3gnl.|Q'<1dIS;5h.VC_9WIgobp +o;y?  # SqqȾh&ev)T‹ᡯ)5ḵ7#d(YiTSV 0*ń &'b |:1goG;:xrlj&k zpgVG?h]} ˭Ǩo!#P,ot%#Z6'[IdhƑ]p}Ý#$׈]ȢuNSL,"%2ĪA,8-ci4ezzW +9iz9r]| WoUy8da #32IpPRafj@E[$jNS#e +n= .k7p8 =S}wv?WqE6j%%&)Kqnb'VD4$LpN|:( MP43!"m'qS^b_HO[SWu@_ens(swYGw&GAY?QfWl2IiiTӅش|3`w` ^ןpڻLy +_vR&<''3>#(`_Fna@>>=!g_lCQ59ej̫ZZML5Z3 @QS-! +JEJKz&I +^Ҡ9yQ #et{_rw<1;E`ixl0H^h;Om:u2s6 +Nh~lB (*ҼR֫TJ$JNdf`j7xf4Fsw7GxQPh4zL.7Ii=<_nNmϞ(vN:z犬y(s. yZ˱sn-IyaZ!_hSw2T {0OmWowodG|)ts $1N]! lX+4>z2ScsXgȣBM#ul,4Ha>_cvA2@ +W d"],[Օ@3I]/106?ڇW6?g'}N*#j*\LC{ۣi:8lg,3ߑ4]#<0Tj11Gv*5ZP͖PH?3>Uv_ LM~$5lQPmqT#p<-!;p9ԭjWI*Sn8wSs a"|g? 7pK}%2'u-=_hηKgݤ{ϒp鵌t4#j5+"`W4Wp71hsb/b; 4` 3l,(?\ဠ"4EQybCȃ˘Y5~Ł1.]d$|¿Y5>f.'T6?U`EO']#068vʡbUIӉ0Yt +5Hˣy~W4SLb_ z۩7c=(bQ +O) 䏜\&9u]=nȺԊ118MszMUi*(ȍÏqffUf]90 jm[fM 8#*=1Vt*8Z<-+2=LLGY4zzY/LqR p{ns3T}bospu?ރT}@{oO(HX/ w{F:2|2culj)5lg/`UFg6Y`7cph1sy%!j whӭ;4NrY1)uI>K-f4O굃9J4TT:iџL2' wCǛe)AaU#`.f9n7sW$պ*.:@KSWo+ptZQ"Ro0(vchv /mIp6?Zx83wZp a.Gkzv]Бb~][WD+y X8}vMu@`V4 5 n-x ௟%l筇.]t>e'VCOv؟8*,x>|YܿMϳԕ!Yb2GDoCaYHm94vyщrJBB0wښ3i]^@QԿt%JUӷGXSC0Qj\xsW`pKqc3Ǖ"3bߣ<t{Ty9w\{[hT9sWS'Tzw苭ecbh eyz)}|]h8g|M'7>6=Iv8 ąL<9t8,$ +ͯ粽uok4Z ȰиW7QjDTwoYt#/}ѿWG?ᜍ=eȆ`,e{fb/ؐy N ESf3(z:=$\v€KK$!a4Y02(53§^:D9ɠj[\FRC Eqy{Hdy>ϬBL I.y{ftt8]dՠVMSa,T*ni#owoI{p;zxR8応x::\=ĩ:KfmoK-/F7.g&7JN *2kj 3c^p*HIJ"iRyaQnPs6Ķ#HӲE$_QXgrqh3}ĄuvG|?w7*|^i. &v +|rk 5_I*jVtt|3}sBu_rw=nAXQl,*J-ԚURfXNagUڬqs\Eu6!gysfV9#0pA>?1Xa,Дܝ;?aͣl1KIt*uТQ HN|ɖ$ڠn+=GweMU'L]^\LMRw*``,o7@t]Ej<@+@Id~GI֪ˣsZ:l .=Ndꍆ +eި2!oTvԶt2QOתL`jtV)$6*zY[;:.#s;ֆsPIV2sDk{S[kFSe%}nv4+T+EjJim'>;wO+Gj/Ci+%̦}>ΆD1MO& hX-NT dOfKpjree(%z]E+0Ҍ9d8{a +y;o7V8hw(yPf`Z`JzIDt6=DWVz *ŤJa+k)'",ԕ4sb'?endstream +endobj +123 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 517 >> +stream +hdkAwC 6",BÒRғ`lfffg`5II(=X`{R/7R+Qtz&Brh2Q2FA/C=3298':a5Ӳ)2#a.q.r"`xpՑj$0S2X "i +hLqhDbB:ఒh N@-!86ca]\a2N=GpZ5LjPApq- r0"^ Fw&PE8)SG.-}U 4a)8:Lrf OϦC4U ]2?E1zw섛ont+\*VX~xꭶ77z+ [YrU_f@Fmbtyvg~pA>j>u^R#mm{LJ$xJ~[7- F~ 0E>endstream +endobj +124 0 obj +<< /Filter /FlateDecode /Subtype /Type1C /Length 4139 >> +stream +hޜW{XgdmX2ӝI[Z/K"% !-!!!ȕpT +PZ/ںjm[nߡoݭkl3ϼ=w~9Ng8N@@C^4gm2*&ybpaj꼐%!g̜k~l1afLcV?ayfFޓqc_ X)X'Ţt@&'S"|`᫯2OE.MM + $EL8W$H+ŴX- ܤLH,Sҳ{z!-e s,X:O0uRL4E^\(`3)lZ:W-U+XIt\~BS\.N+cr33J|O@!OJf%%cOEHOR +B\( +,fe lT6=O6"BmCXxL`[ht]Ngbg*3-d 98qeNH 'Dč,dLs윳;fT8r6L0MH2r +x{^ e 'njI/L:59xrS)wN +x[xӦLSL>O6p@)؈eM_|Ijjm$fHCHS0 +!vs.!q ` J + ōQ!A5o%ol]oh442?,ޕ+23频ƃ70೘ˢ 9"NiZ%.ѦIH/b3ۻu GP< +vb0TW\Xhpɇ݈Yz gY Ag E^jnoF7R zf؉tJ/WU* õ[/]~ҫ5҃Fv " n\{Y_ IbF+1@N8JnǙ p $>sZ\6q$+3(inn+! >8"Y1g["%扦H6 @ws.tSXjbB>4'J5L8\wk]f ߄(ZGt + m:5Ǩ B |.41k:NI^H;5RXD|4q 1Q?| $LDA|{u4(wRdwB &ςOCH/@0xfpZnŎ* 6Z-?)tBTtn1nkzېfM!qiA-99FuY8.XZnyT@DG`8 W3S8(s7a0E]]EH7qF 9r8ԥ{ + +cƃ;kfz5]:&vfJ#nݑY=Y807gY _;|0Uم(erbC0wb\* `L :m9B{n@uեƠHE![Nh5G0|tLʆoK2ղ<5AAw>ցn&?5r«?E"`. +qmm!`9$ MP & ;^fq.d@Z0 &;3j8mQ#-jsfܯD#ˊjRfa֢`7Rpc #9*Ak}M^}au1=R86c Aw VZl=ֱNrKeje׸N#Ds&qGhV{X]C.D*3JEn04a`b;QfUoH ܗq mtz8 _1*ТC%Mh%.lm|$pnvzn3=X+cG8X^𖵒EtC`$C,\AkXrz +(0B*VЧ(3B񗇷}q 謹dUվ*MHz+U]=u--ck26VN^a Q+asD +}F%1 Bz"C}%H\U~k{c HްP[m.x&{s{D`sls/%Q$40U)QkGK${ )=fRfp Rz"g p+\woX͎(xc4>ɘMQ cGS"=dZJ~Z<&d}|?[p =RSk%&kWU۩Hbl :;(Τ`Q4%wk tħJjD.N3\"riar6|'{,f|u8EZtvr;ՖnKhqG}%-Wftyw sȯ؎  'Zo# }>:u AoV/m'K|O`<չ*ۑ/JȯC#|XnPkcKn/HQ*Nơ<2gW 3A:9m7=\-s*_nõ̻X܁z:ϜKvJ -߇@HKzwZ{ ШG f] 6s3I8A1~`?x`oN#ۑ2FCi:%cvQwP(7Ns3qcGWyc@T6IkB  +? +,1}>:m7ΙK68#6oEy'V}8`3gC_0:kp6ѱ`xwX䍀w`ACsG 0Sա@^nE@G#P]mVQ<a粺'ʶȏQL5.&FU- Ejm#c_!IS\K5Vuj!F|` +mZX1Y9Yu)@`-:O۔Q'$i/BCkDJN6$.)bEKs*r QIC=88f߂r*;3@#W%0ڒ!EykcG(އbm20μ>ee+D\vA=e" ʷfVKXzH3H}7|.! Ey +v)M .ՙDbf֞؁|QHpݎzfIn5b2te|1Gsx (2vޫl{rɸJJuerQW!&^7_>t(6%>Frd1o?ŜO yendstream +endobj +125 0 obj +<< /N 128 0 R /R [ 43 512 431 542 ] /T 18 0 R /V 112 0 R >> +endobj +126 0 obj +<< /N 113 0 R /R [ 43 508 431 558 ] /T 18 0 R /V 115 0 R >> +endobj +127 0 obj +<< /N 116 0 R /R [ 37 436 425 453 ] /T 18 0 R /V 129 0 R >> +endobj +128 0 obj +<< /N 130 0 R /R [ 43 411 362 516 ] /T 18 0 R /V 125 0 R >> +endobj +129 0 obj +<< /N 127 0 R /R [ 149 445 419 484 ] /T 18 0 R /V 131 0 R >> +endobj +130 0 obj +<< /N 132 0 R /R [ 43 393 431 420 ] /T 18 0 R /V 128 0 R >> +endobj +131 0 obj +<< /N 129 0 R /R [ 49 466 150 484 ] /T 18 0 R /V 133 0 R >> +endobj +132 0 obj +<< /N 134 0 R /R [ 43 269 181 397 ] /T 18 0 R /V 130 0 R >> +endobj +133 0 obj +<< /N 131 0 R /R [ 149 477 419 495 ] /T 18 0 R /V 135 0 R >> +endobj +134 0 obj +<< /N 136 0 R /R [ 198 224 431 397 ] /T 18 0 R /V 132 0 R >> +endobj +135 0 obj +<< /N 133 0 R /R [ 49 477 150 495 ] /T 18 0 R /V 137 0 R >> +endobj +136 0 obj +<< /N 138 0 R /R [ 43 222 431 240 ] /T 18 0 R /V 134 0 R >> +endobj +137 0 obj +<< /N 135 0 R /R [ 149 487 419 516 ] /T 18 0 R /V 139 0 R >> +endobj +138 0 obj +<< /N 140 0 R /R [ 43 183 431 201 ] /T 18 0 R /V 136 0 R >> +endobj +139 0 obj +<< /N 137 0 R /R [ 49 498 150 516 ] /T 18 0 R /V 141 0 R >> +endobj +140 0 obj +<< /N 142 0 R /R [ 43 171 156 176 ] /T 18 0 R /V 138 0 R >> +endobj +141 0 obj +<< /N 139 0 R /R [ 149 508 419 526 ] /T 18 0 R /V 143 0 R >> +endobj +142 0 obj +<< /N 144 0 R /R [ 155 171 431 176 ] /T 18 0 R /V 140 0 R >> +endobj +143 0 obj +<< /N 141 0 R /R [ 49 508 150 526 ] /T 18 0 R /V 145 0 R >> +endobj +144 0 obj +<< /N 146 0 R /R [ 55 158 156 176 ] /T 18 0 R /V 142 0 R >> +endobj +145 0 obj +<< /N 143 0 R /R [ 149 519 419 558 ] /T 18 0 R /V 147 0 R >> +endobj +146 0 obj +<< /N 148 0 R /R [ 155 158 425 176 ] /T 18 0 R /V 144 0 R >> +endobj +147 0 obj +<< /N 145 0 R /R [ 49 539 150 558 ] /T 18 0 R /V 149 0 R >> +endobj +148 0 obj +<< /N 150 0 R /R [ 55 148 156 166 ] /T 18 0 R /V 146 0 R >> +endobj +149 0 obj +<< /N 147 0 R /R [ 149 550 419 568 ] /T 18 0 R /V 151 0 R >> +endobj +150 0 obj +<< /N 152 0 R /R [ 155 148 425 166 ] /T 18 0 R /V 148 0 R >> +endobj +151 0 obj +<< /N 149 0 R /R [ 49 550 150 568 ] /T 18 0 R /V 153 0 R >> +endobj +152 0 obj +<< /N 154 0 R /R [ 55 137 156 155 ] /T 18 0 R /V 150 0 R >> +endobj +153 0 obj +<< /N 151 0 R /R [ 149 560 419 620 ] /T 18 0 R /V 155 0 R >> +endobj +154 0 obj +<< /N 155 0 R /R [ 155 137 425 155 ] /T 18 0 R /V 152 0 R >> +endobj +155 0 obj +<< /N 153 0 R /R [ 49 602 150 620 ] /T 18 0 R /V 154 0 R >> +endobj +156 0 obj +<< /Type /XRef /Length 301 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 2 0 R /Root 1 0 R /Size 157 /ID [<6d3f2f7f1a0bf42b5be93b7d055d410d><45440faf129c4d81c7c58c70d1169cf1>] >> +stream +xҽ+a뺕APEJ yL _e,Ŧ,Xf*b),/}> ~뾟 v)I>3[Lcsf*6(4?~JA쌆>ь-mS (8xH+e3(oUiݻiү +3p̙mj4޸]&o yldLT]jM7_g}B= +endstream +endobj +startxref +109222 +%%EOF diff --git a/test_unstructured/partition/pdf_image/test_image.py b/test_unstructured/partition/pdf_image/test_image.py index b8004c3ff..f8a29d706 100644 --- a/test_unstructured/partition/pdf_image/test_image.py +++ b/test_unstructured/partition/pdf_image/test_image.py @@ -1,5 +1,6 @@ import os import pathlib +import tempfile from unittest import mock import pytest @@ -7,6 +8,7 @@ from PIL import Image from pytesseract import TesseractError from unstructured_inference.inference import layout +from test_unstructured.partition.pdf_image.test_pdf import assert_element_extraction from test_unstructured.unit_utils import assert_round_trips_through_JSON, example_doc_path from unstructured.chunking.title import chunk_by_title from unstructured.documents.elements import ElementType @@ -632,3 +634,34 @@ def test_partition_image_has_filename(inference_results): assert element.metadata.filetype == "JPEG" # This should be kept from the filename we originally gave assert element.metadata.filename == filename + + +@pytest.mark.parametrize("file_mode", ["filename", "rb"]) +@pytest.mark.parametrize("extract_to_payload", [False, True]) +def test_partition_image_element_extraction( + file_mode, + extract_to_payload, + filename=example_doc_path("embedded-images-tables.jpg"), +): + extract_element_types = ["Image", "Table"] + + with tempfile.TemporaryDirectory() as tmpdir: + if file_mode == "filename": + elements = image.partition_image( + filename=filename, + strategy="hi_res", + extract_element_types=extract_element_types, + extract_to_payload=extract_to_payload, + image_output_dir_path=tmpdir, + ) + else: + with open(filename, "rb") as f: + elements = image.partition_image( + file=f, + strategy="hi_res", + extract_element_types=extract_element_types, + extract_to_payload=extract_to_payload, + image_output_dir_path=tmpdir, + ) + + assert_element_extraction(elements, extract_element_types, extract_to_payload, tmpdir) diff --git a/test_unstructured/partition/pdf_image/test_pdf.py b/test_unstructured/partition/pdf_image/test_pdf.py index fa14ee017..8dd45376d 100644 --- a/test_unstructured/partition/pdf_image/test_pdf.py +++ b/test_unstructured/partition/pdf_image/test_pdf.py @@ -1,6 +1,8 @@ +import base64 import logging import math import os +import tempfile from tempfile import SpooledTemporaryFile from unittest import mock @@ -15,6 +17,7 @@ from unstructured.documents.coordinates import PixelSpace from unstructured.documents.elements import ( CoordinatesMetadata, ElementMetadata, + ElementType, ListItem, NarrativeText, Text, @@ -1123,3 +1126,62 @@ def test_extractable_elements_repair_invalid_pdf_structure(filename, expected_lo caplog.set_level(logging.INFO) assert pdf.extractable_elements(filename=example_doc_path(filename)) assert expected_log in caplog.text + + +def assert_element_extraction(elements, extract_element_types, extract_to_payload, tmpdir): + extracted_elements = [] + for el_type in extract_element_types: + extracted_elements_by_type = [] + for el in elements: + if el.category == el_type: + extracted_elements_by_type.append(el) + extracted_elements.append(extracted_elements_by_type) + + for extracted_elements_by_type in extracted_elements: + for i, el in enumerate(extracted_elements_by_type): + if extract_to_payload: + assert el.metadata.image_base64 is not None + assert el.metadata.image_mime_type == "image/jpeg" + image_data = base64.b64decode(el.metadata.image_base64) + assert isinstance(image_data, bytes) + assert el.metadata.image_path is None + else: + basename = "table" if el.category == ElementType.TABLE else "figure" + expected_image_path = os.path.join( + str(tmpdir), f"{basename}-{el.metadata.page_number}-{i + 1}.jpg" + ) + assert el.metadata.image_path == expected_image_path + assert os.path.isfile(expected_image_path) + assert el.metadata.image_base64 is None + assert el.metadata.image_mime_type is None + + +@pytest.mark.parametrize("file_mode", ["filename", "rb"]) +@pytest.mark.parametrize("extract_to_payload", [False, True]) +def test_partition_pdf_element_extraction( + file_mode, + extract_to_payload, + filename=example_doc_path("embedded-images-tables.pdf"), +): + extract_element_types = ["Image", "Table"] + + with tempfile.TemporaryDirectory() as tmpdir: + if file_mode == "filename": + elements = pdf.partition_pdf( + filename=filename, + strategy="hi_res", + extract_element_types=extract_element_types, + extract_to_payload=extract_to_payload, + image_output_dir_path=tmpdir, + ) + else: + with open(filename, "rb") as f: + elements = pdf.partition_pdf( + file=f, + strategy="hi_res", + extract_element_types=extract_element_types, + extract_to_payload=extract_to_payload, + image_output_dir_path=tmpdir, + ) + + assert_element_extraction(elements, extract_element_types, extract_to_payload, tmpdir) diff --git a/test_unstructured/partition/pdf_image/test_pdf_image_utils.py b/test_unstructured/partition/pdf_image/test_pdf_image_utils.py index 2ae7ffa69..13bc2b50b 100644 --- a/test_unstructured/partition/pdf_image/test_pdf_image_utils.py +++ b/test_unstructured/partition/pdf_image/test_pdf_image_utils.py @@ -7,7 +7,7 @@ from PIL import Image as PILImg from test_unstructured.unit_utils import example_doc_path from unstructured.documents.coordinates import PixelSpace -from unstructured.documents.elements import ElementMetadata, ElementType, Image +from unstructured.documents.elements import ElementMetadata, ElementType, Image, Table from unstructured.partition.pdf_image import pdf_image_utils @@ -60,58 +60,66 @@ def test_convert_pdf_to_image( assert isinstance(images[0], PILImg.Image) -def test_save_elements(filename=example_doc_path("embedded-images.pdf")): +@pytest.mark.parametrize("element_category_to_save", [ElementType.IMAGE, ElementType.TABLE]) +@pytest.mark.parametrize("extract_to_payload", [False, True]) +def test_save_elements( + element_category_to_save, + extract_to_payload, + filename=example_doc_path("layout-parser-paper-fast.pdf"), +): with tempfile.TemporaryDirectory() as tmpdir: elements = [ Image( text="3", - coordinates=( - (78.7401411111111, 86.61545694444455), - (78.7401411111111, 519.9487805555556), - (512.0734647222223, 519.9487805555556), - (512.0734647222223, 86.61545694444455), - ), + coordinates=((78, 86), (78, 519), (512, 519), (512, 86)), coordinate_system=PixelSpace(width=1575, height=1166), metadata=ElementMetadata(page_number=1), ), Image( text="4", - coordinates=( - (570.8661397222222, 86.6154566666667), - (570.8661397222222, 519.6862825000001), - (1003.9369655555556, 519.6862825000001), - (1003.9369655555556, 86.6154566666667), - ), + coordinates=((570, 86), (570, 519), (1003, 519), (1003, 86)), coordinate_system=PixelSpace(width=1575, height=1166), metadata=ElementMetadata(page_number=1), ), Image( text="5", - coordinates=( - (1062.9921808333331, 86.61545694444455), - (1062.9921808333331, 519.9487805555556), - (1496.3255044444445, 519.9487805555556), - (1496.3255044444445, 86.61545694444455), - ), + coordinates=((1062, 86), (1062, 519), (1496, 519), (1496, 86)), coordinate_system=PixelSpace(width=1575, height=1166), metadata=ElementMetadata(page_number=1), ), + Table( + text="Sample Table", + coordinates=((1062, 86), (1062, 519), (1496, 519), (1496, 86)), + coordinate_system=PixelSpace(width=1575, height=1166), + metadata=ElementMetadata(page_number=2), + ), ] pdf_image_utils.save_elements( elements=elements, - element_category_to_save=ElementType.IMAGE, + element_category_to_save=element_category_to_save, pdf_image_dpi=200, filename=filename, output_dir_path=str(tmpdir), + extract_to_payload=extract_to_payload, ) - for i, el in enumerate(elements): + saved_elements = [el for el in elements if el.category == element_category_to_save] + for i, el in enumerate(saved_elements): + basename = "table" if el.category == ElementType.TABLE else "figure" expected_image_path = os.path.join( - str(tmpdir), f"figure-{el.metadata.page_number}-{i + 1}.jpg" + str(tmpdir), f"{basename}-{el.metadata.page_number}-{i + 1}.jpg" ) - assert os.path.isfile(el.metadata.image_path) - assert el.metadata.image_path == expected_image_path + if extract_to_payload: + assert isinstance(el.metadata.image_base64, str) + assert isinstance(el.metadata.image_mime_type, str) + assert not el.metadata.image_path + assert not os.path.isfile(expected_image_path) + else: + assert os.path.isfile(expected_image_path) + assert el.metadata.image_path == expected_image_path + assert not el.metadata.image_base64 + assert not el.metadata.image_mime_type def test_write_image_raises_error(): diff --git a/test_unstructured/partition/test_auto.py b/test_unstructured/partition/test_auto.py index aaf9f1ca7..4df28143d 100644 --- a/test_unstructured/partition/test_auto.py +++ b/test_unstructured/partition/test_auto.py @@ -3,7 +3,7 @@ import os import pathlib import warnings from importlib import import_module -from unittest.mock import ANY, Mock, patch +from unittest.mock import Mock, patch import docx import pytest @@ -347,15 +347,17 @@ def test_auto_partition_pdf_with_fast_strategy(monkeypatch): mock_partition.assert_called_once_with( filename=filename, - metadata_filename=None, file=None, url=None, - include_page_breaks=False, - infer_table_structure=False, - extract_images_in_pdf=ANY, - image_output_dir_path=ANY, strategy=PartitionStrategy.FAST, languages=None, + metadata_filename=None, + include_page_breaks=False, + infer_table_structure=False, + extract_images_in_pdf=False, + extract_element_types=None, + image_output_dir_path=None, + extract_to_payload=False, hi_res_model_name=None, ) diff --git a/unstructured/documents/elements.py b/unstructured/documents/elements.py index 0e152c8fa..0a87b56b0 100644 --- a/unstructured/documents/elements.py +++ b/unstructured/documents/elements.py @@ -173,9 +173,11 @@ class ElementMetadata: file_directory: Optional[str] filename: Optional[str] filetype: Optional[str] + image_path: Optional[str] + image_base64: Optional[str] + image_mime_type: Optional[str] # -- specific to DOCX which has distinct primary, first-page, and even-page header/footers -- header_footer_type: Optional[str] - image_path: Optional[str] # -- used in chunks only, when chunk must be split mid-text to fit window -- is_continuation: Optional[bool] languages: Optional[List[str]] @@ -457,6 +459,8 @@ class ConsolidationStrategy(enum.Enum): "filetype": cls.FIRST, "header_footer_type": cls.DROP, "image_path": cls.DROP, + "image_base64": cls.DROP, + "image_mime_type": cls.DROP, "is_continuation": cls.DROP, # -- not expected, added by chunking, not before -- "languages": cls.LIST_UNIQUE, "last_modified": cls.FIRST, diff --git a/unstructured/partition/auto.py b/unstructured/partition/auto.py index be6ebfe34..23d7d9ec3 100644 --- a/unstructured/partition/auto.py +++ b/unstructured/partition/auto.py @@ -137,7 +137,9 @@ def partition( detect_language_per_element: bool = False, pdf_infer_table_structure: bool = False, pdf_extract_images: bool = False, + pdf_extract_element_types: Optional[List[str]] = None, pdf_image_output_dir_path: Optional[str] = None, + pdf_extract_to_payload: bool = False, xml_keep_tags: bool = False, data_source_metadata: Optional[DataSourceMetadata] = None, metadata_filename: Optional[str] = None, @@ -193,11 +195,26 @@ def partition( transformation of the data into an HTML . The "text" field for a partitioned Table Element is always present, whether True or False. pdf_extract_images - If True and strategy=hi_res, any detected images will be saved in the path specified by - pdf_image_output_dir_path. + Only applicable if `strategy=hi_res`. + If True, any detected images will be saved in the path specified by 'image_output_dir_path' + or stored as base64 encoded data within metadata fields. + Deprecation Note: This parameter is marked for deprecation. Future versions will use + 'extract_element_types' for broader extraction capabilities. + pdf_extract_element_types + Only applicable if `strategy=hi_res`. + Images of the element type(s) specified in this list (e.g., ["Image", "Table"]) will be + saved in the path specified by 'image_output_dir_path' or stored as base64 encoded data + within metadata fields. + pdf_extract_to_payload + Only applicable if `strategy=hi_res`. + If True, images of the element type(s) defined in 'extract_element_types' will be encoded + as base64 data and stored in two metadata fields: 'image_base64' and 'image_mime_type'. + This parameter facilitates the inclusion of element data directly within the payload, + especially for web-based applications or APIs. pdf_image_output_dir_path - If pdf_extract_images=True and strategy=hi_res, any detected images will be saved in the - given path + Only applicable if `strategy=hi_res` and `pdf_extract_to_payload=False`. + The filesystem path for saving images of the element type(s) + specified in 'extract_element_types'. xml_keep_tags If True, will retain the XML tags in the output. Otherwise it will simply extract the text from within the tags. Only applies to partition_xml. @@ -397,7 +414,9 @@ def partition( strategy=strategy, languages=languages, extract_images_in_pdf=pdf_extract_images, + extract_element_types=pdf_extract_element_types, image_output_dir_path=pdf_image_output_dir_path, + extract_to_payload=pdf_extract_to_payload, hi_res_model_name=hi_res_model_name or model_name, **kwargs, ) diff --git a/unstructured/partition/image.py b/unstructured/partition/image.py index 4c1ba1fa6..9fb890d28 100644 --- a/unstructured/partition/image.py +++ b/unstructured/partition/image.py @@ -26,6 +26,10 @@ def partition_image( metadata_last_modified: Optional[str] = None, chunking_strategy: Optional[str] = None, hi_res_model_name: Optional[str] = None, + extract_images_in_pdf: bool = False, + extract_element_types: Optional[List[str]] = None, + image_output_dir_path: Optional[str] = None, + extract_to_payload: bool = False, **kwargs, ) -> List[Element]: """Parses an image into a list of interpreted elements. @@ -58,6 +62,27 @@ def partition_image( The last modified date for the document. hi_res_model_name The layout detection model used when partitioning strategy is set to `hi_res`. + extract_images_in_pdf + Only applicable if `strategy=hi_res`. + If True, any detected images will be saved in the path specified by 'image_output_dir_path' + or stored as base64 encoded data within metadata fields. + Deprecation Note: This parameter is marked for deprecation. Future versions will use + 'extract_element_types' for broader extraction capabilities. + extract_element_types + Only applicable if `strategy=hi_res`. + Images of the element type(s) specified in this list (e.g., ["Image", "Table"]) will be + saved in the path specified by 'image_output_dir_path' or stored as base64 encoded data + within metadata fields. + extract_to_payload + Only applicable if `strategy=hi_res`. + If True, images of the element type(s) defined in 'extract_element_types' will be encoded + as base64 data and stored in two metadata fields: 'image_base64' and 'image_mime_type'. + This parameter facilitates the inclusion of element data directly within the payload, + especially for web-based applications or APIs. + image_output_dir_path + Only applicable if `strategy=hi_res` and `extract_to_payload=False`. + The filesystem path for saving images of the element type(s) + specified in 'extract_element_types'. """ exactly_one(filename=filename, file=file) @@ -93,5 +118,9 @@ def partition_image( strategy=strategy, metadata_last_modified=metadata_last_modified, hi_res_model_name=hi_res_model_name, + extract_images_in_pdf=extract_images_in_pdf, + extract_element_types=extract_element_types, + image_output_dir_path=image_output_dir_path, + extract_to_payload=extract_to_payload, **kwargs, ) diff --git a/unstructured/partition/pdf.py b/unstructured/partition/pdf.py index 696f18be4..4df6eb5ef 100644 --- a/unstructured/partition/pdf.py +++ b/unstructured/partition/pdf.py @@ -106,7 +106,6 @@ from unstructured.utils import requires_dependencies if TYPE_CHECKING: pass - # NOTE(alan): Patching this to fix a bug in pdfminer.six. Submitted this PR into pdfminer.six to fix # the bug: https://github.com/pdfminer/pdfminer.six/pull/885 psparser.PSBaseParser._parse_keyword = parse_keyword # type: ignore @@ -140,10 +139,11 @@ def partition_pdf( metadata_last_modified: Optional[str] = None, chunking_strategy: Optional[str] = None, # used by decorator links: Sequence[Link] = [], + hi_res_model_name: Optional[str] = None, extract_images_in_pdf: bool = False, extract_element_types: Optional[List[str]] = None, image_output_dir_path: Optional[str] = None, - hi_res_model_name: Optional[str] = None, + extract_to_payload: bool = False, **kwargs, ) -> List[Element]: """Parses a pdf document into a list of interpreted elements. @@ -173,18 +173,29 @@ def partition_pdf( with Tesseract, you'll first need to install the appropriate Tesseract language pack. metadata_last_modified The last modified date for the document. - extract_images_in_pdf - Only applicable if `strategy=hi_res`. - If `True`, any detected images will be saved in the path specified by - image_output_dir_path. - extract_element_types - Only applicable if `strategy=hi_res`. - Images of the element type(s) defined in this list will be saved to `image_output_dir_path`. - image_output_dir_path - Only applicable if `strategy=hi_res`. - The path for saving images when using `extract_images_in_pdf` or `extract_element_types`. hi_res_model_name The layout detection model used when partitioning strategy is set to `hi_res`. + extract_images_in_pdf + Only applicable if `strategy=hi_res`. + If True, any detected images will be saved in the path specified by 'image_output_dir_path' + or stored as base64 encoded data within metadata fields. + Deprecation Note: This parameter is marked for deprecation. Future versions will use + 'extract_element_types' for broader extraction capabilities. + extract_element_types + Only applicable if `strategy=hi_res`. + Images of the element type(s) specified in this list (e.g., ["Image", "Table"]) will be + saved in the path specified by 'image_output_dir_path' or stored as base64 encoded data + within metadata fields. + extract_to_payload + Only applicable if `strategy=hi_res`. + If True, images of the element type(s) defined in 'extract_element_types' will be encoded + as base64 data and stored in two metadata fields: 'image_base64' and 'image_mime_type'. + This parameter facilitates the inclusion of element data directly within the payload, + especially for web-based applications or APIs. + image_output_dir_path + Only applicable if `strategy=hi_res` and `extract_to_payload=False`. + The filesystem path for saving images of the element type(s) + specified in 'extract_element_types'. """ exactly_one(filename=filename, file=file) @@ -199,10 +210,11 @@ def partition_pdf( infer_table_structure=infer_table_structure, languages=languages, metadata_last_modified=metadata_last_modified, + hi_res_model_name=hi_res_model_name, extract_images_in_pdf=extract_images_in_pdf, extract_element_types=extract_element_types, image_output_dir_path=image_output_dir_path, - hi_res_model_name=hi_res_model_name, + extract_to_payload=extract_to_payload, **kwargs, ) @@ -249,13 +261,14 @@ def _partition_pdf_or_image_local( languages: Optional[List[str]] = None, ocr_mode: str = OCRMode.FULL_PAGE.value, model_name: Optional[str] = None, # to be deprecated in favor of `hi_res_model_name` + hi_res_model_name: Optional[str] = None, + pdf_image_dpi: Optional[int] = None, metadata_last_modified: Optional[str] = None, pdf_text_extractable: bool = False, extract_images_in_pdf: bool = False, extract_element_types: Optional[List[str]] = None, image_output_dir_path: Optional[str] = None, - pdf_image_dpi: Optional[int] = None, - hi_res_model_name: Optional[str] = None, + extract_to_payload: bool = False, analysis: bool = False, analyzed_image_output_dir_path: Optional[str] = None, **kwargs, @@ -402,7 +415,9 @@ def _partition_pdf_or_image_local( element_category_to_save=ElementType.IMAGE, filename=filename, file=file, + is_image=is_image, pdf_image_dpi=pdf_image_dpi, + extract_to_payload=extract_to_payload, output_dir_path=image_output_dir_path, ) @@ -415,7 +430,9 @@ def _partition_pdf_or_image_local( element_category_to_save=el_type, filename=filename, file=file, + is_image=is_image, pdf_image_dpi=pdf_image_dpi, + extract_to_payload=extract_to_payload, output_dir_path=image_output_dir_path, ) @@ -425,10 +442,12 @@ def _partition_pdf_or_image_local( continue if isinstance(el, Image): - # NOTE(crag): small chunks of text from Image elements tend to be garbage - if not el.metadata.image_path and ( - el.text is None or len(el.text) < 24 or el.text.find(" ") == -1 + if ( + not extract_images_in_pdf + and ElementType.IMAGE not in extract_element_types + and (el.text is None or len(el.text) < 24 or el.text.find(" ") == -1) ): + # NOTE(crag): small chunks of text from Image elements tend to be garbage continue else: out_elements.append(cast(Element, el)) @@ -457,10 +476,11 @@ def partition_pdf_or_image( ocr_languages: Optional[str] = None, languages: Optional[List[str]] = None, metadata_last_modified: Optional[str] = None, + hi_res_model_name: Optional[str] = None, extract_images_in_pdf: bool = False, extract_element_types: Optional[List[str]] = None, image_output_dir_path: Optional[str] = None, - hi_res_model_name: Optional[str] = None, + extract_to_payload: bool = False, **kwargs, ) -> List[Element]: """Parses a pdf or image document into a list of interpreted elements.""" @@ -518,11 +538,12 @@ def partition_pdf_or_image( include_page_breaks=include_page_breaks, languages=languages, metadata_last_modified=metadata_last_modified or last_modification_date, + hi_res_model_name=hi_res_model_name, pdf_text_extractable=pdf_text_extractable, extract_images_in_pdf=extract_images_in_pdf, extract_element_types=extract_element_types, image_output_dir_path=image_output_dir_path, - hi_res_model_name=hi_res_model_name, + extract_to_payload=extract_to_payload, **kwargs, ) out_elements = _process_uncategorized_text_elements(elements) diff --git a/unstructured/partition/pdf_image/pdf_image_utils.py b/unstructured/partition/pdf_image/pdf_image_utils.py index ee9c9d29f..5ffd8d07f 100644 --- a/unstructured/partition/pdf_image/pdf_image_utils.py +++ b/unstructured/partition/pdf_image/pdf_image_utils.py @@ -1,5 +1,7 @@ +import base64 import os import tempfile +from io import BytesIO from pathlib import PurePath from typing import TYPE_CHECKING, BinaryIO, List, Optional, Union, cast @@ -79,11 +81,17 @@ def save_elements( pdf_image_dpi: int, filename: str = "", file: Optional[Union[bytes, BinaryIO]] = None, + is_image: bool = False, + extract_to_payload: bool = False, output_dir_path: Optional[str] = None, ): """ - Extract and save images from the page. This method iterates through the layout elements - of the page, identifies image regions, and extracts and saves them as separate image files. + Saves specific elements from a PDF as images either to a directory or embeds them in the + element's payload. + + This function processes a list of elements partitioned from a PDF file. For each element of + a specified category, it extracts and saves the image. The images can either be saved to + a specified directory or embedded into the element's payload as a base64-encoded string. """ if not output_dir_path: @@ -91,14 +99,25 @@ def save_elements( os.makedirs(output_dir_path, exist_ok=True) with tempfile.TemporaryDirectory() as temp_dir: - _image_paths = convert_pdf_to_image( - filename, - file, - pdf_image_dpi, - output_folder=temp_dir, - path_only=True, - ) - image_paths = cast(List[str], _image_paths) + if is_image: + if file is None: + image_paths = [filename] + else: + if hasattr(file, "seek"): + file.seek(0) + temp_file = tempfile.NamedTemporaryFile(delete=False, dir=temp_dir) + temp_file.write(file.read() if hasattr(file, "read") else file) + temp_file.flush() + image_paths = [temp_file.name] + else: + _image_paths = convert_pdf_to_image( + filename, + file, + pdf_image_dpi, + output_folder=temp_dir, + path_only=True, + ) + image_paths = cast(List[str], _image_paths) figure_number = 0 for el in elements: @@ -124,9 +143,17 @@ def save_elements( image_path = image_paths[page_number - 1] image = Image.open(image_path) cropped_image = image.crop((x1, y1, x2, y2)) - write_image(cropped_image, output_f_path) - # add image path to element metadata - el.metadata.image_path = output_f_path + if extract_to_payload: + buffered = BytesIO() + cropped_image.save(buffered, format="JPEG") + img_base64 = base64.b64encode(buffered.getvalue()) + img_base64_str = img_base64.decode() + el.metadata.image_base64 = img_base64_str + el.metadata.image_mime_type = "image/jpeg" + else: + write_image(cropped_image, output_f_path) + # add image path to element metadata + el.metadata.image_path = output_f_path except (ValueError, IOError): logger.warning("Image Extraction Error: Skipping the failed image", exc_info=True)