From 6488c534f7c18896cf313a032ccc7245c46c802c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Am=C3=A9rico?= Date: Fri, 21 Dec 2018 19:40:44 -0300 Subject: [PATCH 1/3] Use sync version of zlib deflate method to compress png images --- lib/image/png.js | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/lib/image/png.js b/lib/image/png.js index 394767db9..0e9acfb68 100644 --- a/lib/image/png.js +++ b/lib/image/png.js @@ -114,7 +114,7 @@ class PNGImage { const imgData = new Buffer(pixelCount * colorByteSize); const alphaChannel = new Buffer(pixelCount); - let i = (p = (a = 0)); + let i = p = a = 0; const len = pixels.length; while (i < len) { imgData[p++] = pixels[i++]; @@ -123,22 +123,13 @@ class PNGImage { alphaChannel[a++] = pixels[i++]; } - let done = 0; - zlib.deflate(imgData, (err, imgData1) => { - this.imgData = imgData1; - if (err) { throw err; } - if (++done === 2) { return this.finalize(); } - }); - - return zlib.deflate(alphaChannel, (err, alphaChannel1) => { - this.alphaChannel = alphaChannel1; - if (err) { throw err; } - if (++done === 2) { return this.finalize(); } - }); + this.imgData = zlib.deflateSync(imgData); + this.alphaChannel = zlib.deflateSync(alphaChannel); + return this.finalize(); }); } - loadIndexedAlphaChannel(fn) { + loadIndexedAlphaChannel() { const transparency = this.image.transparency.indexed; return this.image.decodePixels(pixels => { const alphaChannel = new Buffer(this.width * this.height); @@ -148,11 +139,8 @@ class PNGImage { alphaChannel[i++] = transparency[pixels[j]]; } - return zlib.deflate(alphaChannel, (err, alphaChannel1) => { - this.alphaChannel = alphaChannel1; - if (err) { throw err; } - return this.finalize(); - }); + this.alphaChannel = zlib.deflateSync(alphaChannel); + return this.finalize(); }); } } From fe8632befc5c34b21fcc3473bb21db85101cf40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Am=C3=A9rico?= Date: Fri, 21 Dec 2018 20:22:30 -0300 Subject: [PATCH 2/3] Add png-benchmark demo --- demo/png-benchmark.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 demo/png-benchmark.js diff --git a/demo/png-benchmark.js b/demo/png-benchmark.js new file mode 100644 index 000000000..1f621fe7b --- /dev/null +++ b/demo/png-benchmark.js @@ -0,0 +1,33 @@ +const PDFDocument = require('../'); +const fs = require('fs'); + +const doc = new PDFDocument(); + +// files with alpha channel -> uses zlib.deflate +const files = [ + 'test.png', + 'test3.png' +]; + +const filesData = files.map(fileName => { + return fs.readFileSync(`images/${fileName}`); +}); + +const iterationCount = 100; + +console.time('png-bench') + +for (let i = 0; i < iterationCount; i++) { + filesData.forEach(data => { + doc.image(data) + doc.addPage() + }) +} + +doc.on('data', () => {}) + +doc.on('end', () => { + console.timeEnd('png-bench'); +}); + +doc.end(); \ No newline at end of file From f2208a7c20efb391ae7fff7ac3852012eee5a63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Am=C3=A9rico?= Date: Fri, 21 Dec 2018 23:40:50 -0300 Subject: [PATCH 3/3] Add png unit tests --- tests/images/fish.png | Bin 0 -> 10000 bytes tests/unit/png.spec.js | 170 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 tests/images/fish.png create mode 100644 tests/unit/png.spec.js diff --git a/tests/images/fish.png b/tests/images/fish.png new file mode 100644 index 0000000000000000000000000000000000000000..fca79c0b06215d1c416b5cd9efa868f5cb9fe365 GIT binary patch literal 10000 zcmV+rC-2yaP)!bwCyRCwCW-Fdj)Wtk`V&u@9Rv*hGtAsY}A_K*OwLm-Iaf(o{x zqFwfMX;tfVTTV?))hs>T(>+(sb@kNDR9{_H-HwH&)^bgiqJox)3y6v&5d}m*5&;v| zgzU-5+1};1%pdRb{>~eh61Qp(S8|x;|@>%avljth7 zjkSAsv_Jf%tsiLr+8B69v@Uvo{GM_$5-GwSl_*8wPpS;xXUZ2WvPn%($8HU$8&Q*J z+vaM8{dOL`@nek-7Eh1=*EaBA>~eotdsQToNsv`Ll~-?GNP@v_Uvt=IO+AG|GBg=X=ih=i0l) z$Ns#0EZk;S3bj9X%koun2NJSc9uVeFe zo3zAAnNs0tnRBH&Za3|=? zBy*?O_2Ep`WD2F8n!3~?4WpuvBKpg+!=$dIa;a3?b2i}nZu5FKSmE=|Uj4dl$N#(O zm%K6QOZ&0C4Iiq#I|;@O5<(%Wl0X#x8=#j`F3j{g-0xq$d$pZ;t(&%#UTe4 z3SYOuG986TA~vtC(3UDS#2Us;St?eBNE+#xkSGE?m^13*E_Al8(yd-?b@&b5U7R*| z!^rVpii^Iud~9oSbsv6}a=D~R2Yr;8s1e+(A96ZAVyRWKuuG9fh_JC-qM;?h(eOU? z@cOfyqNgiYc-9J^bb$>bh1*?jUHA>Lh%M39_VQnXf%{h^TWgyVNeKH5t*S04WJ5;w z&F|^j?IV_1E7p|A)r?s}2s}+qb);50q^2g31~`6_dhn9mQM;^jj!0pv|ab~nn4TZ#E z&v-%N3=`U(vDT^TA+>Zv6wT32qtP|cY4yUren+e)JCUMMu6FTPAHH_#PbI7Ep?2tLlMiWX$9PmnY zB~pb_D=;=C0j*wS%AGbk&tCUh?`bt@@S}wcT!zof!QZQWxO4N5p2Q!sgCDu+x=+_C zKCF~UL{%yt&=LJ8R_M9SoJDpy)uf(=L{kliJfLQUGfXPfb@lA>3JpoM{(V1a$O8h( z0&H*lj)NMu827aM{I+H&&61%KI}W>74C3@nwcCHHfp;z5w)^VIbEFE1Tn{y|H0)o0 z#WJ~6F7hScve8EOINNd^a~c{RwbQ88)>lxh`j?LTy(CRgfJfUxv} z!!A^aeND&PHLGQbh90}9O74iG<@(04pOWa8{?Ub#51H3dgqIbeYKSWY5eFj+U$e_u zHX66WLDSk&+x?a2T;>wzinJAS$Ibe(8zcdi71hf3&B_Ce7@*k_r?@zTpsN(_4&Pm< zX9mDuWpXqb|ItrDG7oHw-?!GOzE&l7@(@&1_+?=D_dIT;t1Q-Zt$mK!?i)@q=4z`g zmW!3@IwIS>K~r5U4^?9~fVV!an8=iJUA=H1N`+jhrQuu;nQ|h3SOnf@xG7M+uf6FX zFz{PZ^1%#i9rlANg_q$`1{tpihVOBkQ(dSo7J1H2JG{YL%-CW=Q(dX0t1EU~5>xkSImQQG3$!KA)x_9`3|RdBzQi?)*uMkpFW!X}p z5de5SFy)2R3NsEVWpX|3DjW%B=kh^m{U6)$k2NsA{M1WU__E{LYEE(3aamZuydsiv zxzgV{(`l(Z$i_KgPh%OaE}xN}JrPClk5AM|I2v(xC{cmcnN()AMIy zueQljndh7)R(Qzjiu;@iubpzpxfKJG455!c9}`#MYrx5+p#-amG^BE|x@$ceVtT3! zfvOCzk3#qh75^Xhe$>EtUH+;mg%KNlQ>^WC&TyOgu%`Xmp-}pk7u;iqw^^?tQhLlL ziLTTk%asZsW+x=!1)zc#H1sXa60lm4?2n_L?3L$36+^EA~(vJmJ8 zk2hi5KBouPrX~q-uo&uM#DO3#LwBmbgZ*$)4}{jd!y=0u2}`14W6KKstC9xg`+vy5 z&o&pm=WD)Z&WMK9zH5u76!Jn_IZVy^)zJYD#bD_HL{#e&QSzQ{^8~QH ze)IatGrZ_wg-v=+wch8PE_1F6e8Fu_HEY_n=AA0ll#2DVwH#O143t7@-lV!htf3+D zqU)+y*FROcIo~yIwG~xdjiiWWm7C=O@lexowamRr$HXCk`5`=Os0kE_CT(`lkb%AT zrIuUaJkz$h-@g@^GH%9Fb0%$+nzT~G=e$;;tz(gSb%}k}gf;J&vO2`W)QHlk{Z5vJ z0N&>Xy6*BCjjASCppSELg-N5T`t10Qx;baM+jw=>ii(RJf@;G?zHi9DZ@01=`YzGX zkoYGeQ;r5UdWW;jI9aOH6{{gdSKsoUcfBE3KwF4Hk8SLkRdELTe9fijGB?Qo87 zNQ`JW-Gmyt(xECZ50SH!JMK=eH>U6jr<$n}Lln;cps#h}9#Y=WYt`n%8T|4EPd8`9 z3T-o8~%2R|3vVs4L4x_+Hk+M;Ej z$E}s=qNOJFyz{ZtQB9dlSER5;M^9aD&Ou4F?lqAqWk~QfrMjL>77}>uVJBM=+GUAY zuF$T4T{mFeJ|a#6^v(kuJ4ZI;jDuFduyG5d7+&9r`Yt+=ZfF`YVWo4mtW=Xq)y#`^ zOvc$+tn1q8vfx@#=mYmnS)c)P0})YF zHN`WT(y1XY8Uol(ND_u3YIIICK}@=#sVO!mb372_sRXn}%wtWq$=1BSQgTWumI(dsTG}HrGA@)F6}bML#H9K+CBnuofFGKt2-5i*ro~%32K^B zHEBrq1I{N2Saad5B{~xIAIf+OySA{G3v{q^I#K#yuHI4fJtl3Rv@@; zqi3uYg>HM@Qn9XO4m%P+Lce%jWJW4Aq9Y5%Z2wW})kD>)LMINguOifg@zCxRy20TR zg}SVI__Q)K3XoudD~%U|(7Lh_-#mUvxH0fDwJzcZ9E^~hf`puB7`m}95xMS!E>6$a6trx^7b+zDt1O7GBlWORO_&Q}- zr8|u(44YS-uQC+b*@Ek)#^XiHl0d*GYR0TIWke&a;1d5_B$J`(VmtL5)0G=@spoa{ zB-*C*Lb_k+1#KNuVeRuFxq{H#WZIl=sPCpi{!9YwD%1jn(UeNm&5FgQEUl=+K1%Hu z=5a+*^<8;-nEPH9cbCV=Boc`c=X+kN2vvDoJ*-Kl?s_jct|l@f64~S#HHFhX5!S8{ zIaOCD#L`k02#9{g&_5${YDNq~TVgu2&ib8)TJV~OY`5K4Osj{~zqk_pMHPWrR@_>j z*qo^v0g+O9Qd(P9R5)>$r>t?imDVZIL{CpGVD_fpRLa#ukiN#BdYL0unX2mX*j4^N zSBOPsl)4%^(yFIXnsvxS=C!S|1-Xv#&>ol#WmDJP&bJ(0pYcvH4mjn6h$#fXg*`3A zAvFyu{c>5_o9vVH&)Ve@H=B2{I~{O|B&_SaNUWzLmx(pdlcM3RKIvk|O@{|d^fa8T z9gxYgsslAx`^;m$?Kg}_JnPdgwMwiL`W%H)15X&$wZ{r$ZtxYaL&uV#1TipZp?>K5 zNn@xBT`CvH>1fxKFN)mcbcr!7H+j)_)PjGfmFja45OQfil571_5Bj!qMH*obYhGoC zn$%INtHfIdQt(Azag7)3(RG@eJ??7`vY^;?*-Mhv@|iRU6Dt1EB#Bq<1DFIT@(`f zTix%V9oDL;1zMt1%6wH~n>%gy1DS@`+Zv)?qxx;%wA06x_V|P^DvSn9npR9`vCvUE zp-}4crV9uss>cu8=O!z}l0fnn5|MZNnAxgP)=<|_6X`0^37(&-sad2IPFcUiYM6AL z+#4!ToriVr_>^rv?5}*p-l3K+@>eC){~)*F9Y3sNLy@19lN~fm{@E=XGrZapsdQk(G`_>C)D`e_}bZ8 zh>3Z?6N5_n0^`14=_z{JA?wtF*?C}`>r!=%&}5E-IknLCE<-ugU+aC2X{#F(8+WH? zl~#HIaY*xhuQG9_1pcC|Dz&=qJRg5{F8;xvjFCjfGv6=S!hW2ce|?=)Vq0KXp4?XNG^$;7 zAN$d9#H2AtOgV0e(!3>N;|^L^)f|T%@q+#4tTiGRn=|W}wU$Y(FsUX|98DdHs=~6* zq)b+w_(d-8hz$WL#DU5ygNgm_Pfmu%v@x zx1Z1tnRZZNox(9ooE#+U&nnIOzCB8%B^KKt4n$%mh+T#9B>4l!fQY$2Cj(ET}Z#ys`EYSQ?GSLK1AD7C~!Wm40YDg3}% zbVVZ1I-+ikap#z@-x25ew5K#pxWFqsWuNbwGwrw$i==2d$qGxQT2eJ#HKk=<=eWN+ zoR-s37NwCy7S?azp#36gi@P0ivN)Wjq~g5FKr?*P+vU0%__$?G4!}SqQRjP3u~e*O zt!a~{j7qg_QhLVK5=ZS;I?Jf<`jV5K?Hs3t+?bmddB%MXd%K33#p({}=s9M}vtH1Y z%cLePwaQXGbz|APrc<5X?)c1p((Z$wB;>7ru4%d1=lwHdm0+?~wJ>v$N2F%Viyihk zb8ZL?%RY0Hh5F!Z4>_c(=O%S+k&hddxLRS}3iD#;d)VJw>SC`JE2Xl~uwzVYwF~`~ zj^`A{bggi@Wg(&-uuEn_P2!;a<|NLxZuev-U042Kr!z~`I0BRyi&%@ zX$1LlipQ8Il$#t^RMLYy1fl-xE>s3`B2uWk#(!|5ao@8^O|0oQr}@p`*m0ma z22i@6W+uGSVQ=@Mue;b%yFBb9n>37Bt?hC9O<1XB)~Ev>+4;YfG4a+uT1-O#Nh+eJ z2!!2h+~Y`ylFcCG>0^$EjH^4(9&23f)X*~;C^81zXL3UB?6+Xn_%~w5eAC9zEPIXf zWT9HGRVt4G^VUz{XW6UaRPV4`;#xO4$-Q3ClNfcWEfTvWYC0C%xRsdZ_I{x41xh>$ zXeAHr$HeK{z7ynB0^61AdCXz+PL?~*600=j;dOmvlZQ4;|26fhQPz*wYn<#p*K33% zGK#`{;J~Ab*o~@|8HG`))R^mi-INgo%e&ldD*Uo~;85=OjFZ$g#k!ugs&c9*6h?8#frA~)%*$mudU|?JcacSb+8>a; zY4Cv}d@eY7Jv`6x;2CvS`ns+}-Bnt4tAz$m>S`0Fj9a{um~txGnN!(26cX zyGDhAg?gjoIV%DviM>qE^Pv#CNZnIf8i6`F!ubI5bBQeAW=^&%w96A0>ew4by$Xpd?ES*!<)DRq+dz4pn-4m*eu>oA!lz=3Tx*+s zX58*6zhRNxUNE62HRe%gJ7}2^&8nnH!#MI_2q@JsQX!>M>}mVLS8+wsH?%70NMG_7 zN%drod$JM^^&`a@o*pX5x7aOK*9x$I!|hf3EPhx!ZWdJ?yijgLRa1ivQeQIb)mG}* z?{lsR4}I7gqqez5J%p-ez_&%vv-C|Y)ikvgN_&0Pm^bJJmll>J4t#;Yc1Hmcc0J=x z9|(148AzzEDA4@5$kn#m5{7M)_Bjt%2CkalcSrfQepsmKh2x!v^Eenge$gFT-XSq> z)@NL#F44qyyvuPj#;d(4hqU+utwYDRJmZj_Qp>0!B zD~*M4wnwY1or{bq#Jpr6xBOO14}t{$F7|*a%kA{M_nHhfd>Jao0gfufK|va0#$&eo z*TyR8$RG&qa8X74C!xJ|*j7gzJDP3#A;s^$Klb|z&EdS_KECbiu62r7N9GAToo~Xd z*iuc;c+}g}-Rj05AIU4KD%TBai#)VM3y=7Uy*grt#V&ER4JObFrl!ge!)tnaI==7A z)_A)ywIN+wzlQyY_lBNIJcM~lrRYD7{J{?y_~JUd^H2{amE`o}CS4)XG3%gvoZ@Uf zb5i3*bo{;lM$=u+woWZ{3i~~vJcJpcUEL2E$Ngvf)XdrGG^d)AX*$^%R$HW{Yew5a z&qy70%&7IQwJZ=CNr(&mg#Lugrm9q4X!1b0zV-AEsqTAEmtTpls}E5JxsSQRDPi>V zE>qs9Et4D3&@|_>-l1iymDYv^cTKO-KXk*COA+8&H=LMBPfJb6buCuYbIASLmN?g_ zOhe&3BbKWh)etKK5-P*sPa)OzfPYp+_;?7C;~r1{7*YDuSESpMYD6`1mzs@oxrgm^ zxur_6Bj$`5G373Ax7c>EEf`fQ^+L~}4AO!6Q0KkB@*j1#Bc`xgO>CLequX%k<3Y7**G{*tA1N9kR(1Ej|03 z;~_`f{ex!llT`QjmG=on(q0pG`MMjez?@k<4RvjWJG?{P6K->b z5k){3^+5U7gSeos7Ff7c7B1&VtZ|Z6GD~&M>6&rWUgukF+;RI{uN7XMDneCX23PB2 ztS5ZeZw$F!G}PCPMc;7WPZXuEEu;4r0Y{!}dkz%dC%Cqq}RWPu84`uDDKSX1GERP2~bWtyJ%S|d`aMp&$3NJ|(6oz!i9bEpVb zQDmV7^Zr)(56n%hd#t>r@5vq0UMtr%Z&us52`#0qMqO%;?cQpQ8;$szAd!o!95tvP z1|;wRe)q>?SGvf*_PdT+;|xuEZT2#Y9B`4fK`hy;kZCQPyZ-d&Lq6;Gs{V8N!!lUK zha2DfDZ^Ru|Kjc0Wa87VQ&j5RmQ11PIZyaKdwj`jOh~1!bf(*EvN_1&G@L*ni}@HK9t4%W$LK~s6CJ_e8wTarykU83w7e4vtJ%9{^y@M z!~3#h(Qk9WQOiu5F{P~=rmJ`PvVS3UhpVkq4_I-j-*(WSo32)}792FMc$j`uCD)TG zbR<%ny{KuC4>)ebZWj$zi-WQ^4`1gV^&gz(w*qpF!T>^cLNg}+?U7?IVMsauOz%_A z8#Aw~9T0whHvS9NJIxLkI$tZWr%Gzc>;BNCFT$CtRl@P2a;c7Gj!8w%@)vq9XEODuOlp>EvkBvPF19#?m>2_KNV z&6_Qfm@-zer-RPsM+8ERws!Z;9OH0+&h@ z8tQVfBrsros&K>=a-YB{RdE_Ato9}6gqm&C-L9$zePR#!8~=m4n!;CH7?e!=eM#F} zTxdxE+G&6g!!pW2!5sZ=)MU~Ph zuf{&U>`||Bc^JgW6rS{$8zoAK|I@#6QgGf!{e^#LxkBb!Mx1YtN6Z;@t;M0599$() z&Fcx8JnGW-+H`bH%fzfpP6BWj^c-uL;09u9P|PP$e<&!Mqyb zij+^;+&cIR-RZPN@HcZ*_Xec7=`)y2Lf1eu#(W z7KQFpTHVD!Df-LuUygTvsrRZqA0;2?{b^qc zRIlp1LC;7~BreEFqEM#B71Ak#jHi^F4HDW_8db;`&=Yy3jT*$vVyLVw#mfKQpN+o6 z>l}Z^i{m<<%2x~O?7?tjI&=?gJ9KMn!BvN+JIesv7DkH)GuDGqxg>D0dB80Xnzzg< zqau+`UoN;edh5tHe`U8*KD*e5y{#4)=z)MPu5O*lf+l8gr9g7R&AtPGTvTNJK;k@T zco&t1Bk~vCVR2y129esQqW6v+`xV}8xb|3bb8=I0bm8(G6;#VZCD^~uAPadgKVg7l z;WFHK2o4X%4)UScJ8z9i9M%gMv^W~SHM#j`GwvUmOHZ6iPPMXEpd1*!)(`7gGV zfj$_h1*1yfsEVl3kmA0mx=6$GM@0o51`)V$tG9?fe`H=k}oVMv<1?k2&!KdPd2!}a&Svx5_-9V-5x{X1uGx)it-gduX(?Kfh;eV zf1|vtxUzRo?}VAJ=!D^oqPj|@7~0*1YXp1MZ6s;Mwg?r=!Fx{HTwb>5-fMq>3&wv5 z*HG_cUG)CwJ+;Z`1jv?G=rpcM)2PCc193rA?cd;GGKJ#kw?4M{gR@Vc{0l$bFYO}n zgUw`f^uG88&2s4azOo{IqiXnc&|b|ey=f9s4zY4R`h0dvv~BX&=OXdpkE5;V<=zs% z-Z=|WqG*Vm9bAk%NFD { + let document; + + const createImage = fileName => { + const img = new PNGImage(fs.readFileSync(fileName), "I1"); + // noop data manipulation methods + img.loadIndexedAlphaChannel = () => { + if (img.image.hasAlphaChannel) { + img.alphaChannel = {}; + } + }; + img.splitAlphaChannel = () => { + if (img.image.hasAlphaChannel) { + img.alphaChannel = {}; + } + }; + img.embed(document); + img.finalize(); + return img; + }; + + beforeEach(() => { + document = new PDFDocument(); + }); + + test("RGB", () => { + // ImageWidth = 400 + // ImageHeight = 533 + // BitDepth = 8 + // ColorType = 2 (RGB) + // Compression = 0 + // Filter = 0 + // Interlace = 0 + + const img = createImage("./demo/images/test2.png"); + + expect(img.obj.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: "DeviceRGB", + Filter: "FlateDecode", + Height: 533, + Length: 397011, + Subtype: "Image", + Type: "XObject", + Width: 400, + DecodeParms: expect.any(PDFReference) + }); + + expect(img.obj.data.DecodeParms.data).toMatchObject({ + BitsPerComponent: 8, + Colors: 3, + Columns: 400, + Predictor: 15 + }); + }); + + test("RGB with Alpha", () => { + // ImageWidth = 409 + // ImageHeight = 400 + // BitDepth = 8 + // ColorType = 6 (RGB with Alpha) + // Compression = 0 + // Filter = 0 + // Interlace = 0 + + const img = createImage("./tests/images/bee.png"); + + expect(img.obj.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: "DeviceRGB", + Filter: "FlateDecode", + Height: 400, + Length: 47715, + Subtype: "Image", + Type: "XObject", + Width: 409, + SMask: expect.any(PDFReference) + }); + + expect(img.obj.data.SMask.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: "DeviceGray", + Decode: [ + 0, + 1 + ], + Filter: "FlateDecode", + Height: 400, + Length: 16, + Subtype: "Image", + Type: "XObject", + Width: 409, + }); + }); + + test("Pallete", () => { + // ImageWidth = 980 + // ImageHeight = 540 + // BitDepth = 8 + // ColorType = 3 (Pallete) + // Compression = 0 + // Filter = 0 + // Interlace = 0 + + const img = createImage("./demo/images/test3.png"); + + expect(img.obj.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: ["Indexed", "DeviceRGB", 255, expect.any(PDFReference)], + Filter: "FlateDecode", + Height: 540, + Length: 56682, + Subtype: "Image", + Type: "XObject", + Width: 980, + DecodeParms: expect.any(PDFReference) + }); + + expect(img.obj.data.DecodeParms.data).toMatchObject({ + BitsPerComponent: 8, + Colors: 1, + Columns: 980, + Predictor: 15 + }); + }); + + test("Grayscale with Alpha", () => { + // ImageWidth = 112 + // ImageHeight = 112 + // BitDepth = 8 + // ColorType = 4 (Grayscale with Alpha) + // Compression = 0 + // Filter = 0 + // Interlace = 0 + + const img = createImage("./tests/images/fish.png"); + + expect(img.obj.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: "DeviceGray", + Filter: "FlateDecode", + Height: 112, + Length: 9922, + Subtype: "Image", + Type: "XObject", + Width: 112, + SMask: expect.any(PDFReference) + }); + + expect(img.obj.data.SMask.data).toMatchObject({ + BitsPerComponent: 8, + ColorSpace: "DeviceGray", + Decode: [ + 0, + 1 + ], + Filter: "FlateDecode", + Height: 112, + Length: 16, + Subtype: "Image", + Type: "XObject", + Width: 112, + }); + }); +});