From 187a25a71f9c4732bc6a7eb5f2c19ddd97ea7e9b Mon Sep 17 00:00:00 2001 From: Oz Ramos <0xozram@gmail.com> Date: Tue, 30 May 2023 20:34:16 -0700 Subject: [PATCH] #1 loadImage can now display static GIFs - Replaces the callback example with static gif - Adds new basic animated gif example - Minor whitespace fixes --- .../arnott-wallace-wink-single-frame.gif | Bin 0 -> 2760 bytes src/image/loading_displaying.js | 197 +++++++++--------- 2 files changed, 103 insertions(+), 94 deletions(-) create mode 100644 docs/yuidoc-p5-theme/assets/arnott-wallace-wink-single-frame.gif diff --git a/docs/yuidoc-p5-theme/assets/arnott-wallace-wink-single-frame.gif b/docs/yuidoc-p5-theme/assets/arnott-wallace-wink-single-frame.gif new file mode 100644 index 0000000000000000000000000000000000000000..db886487ee2898cc01215a4dd0d05c8af9be1ec3 GIT binary patch literal 2760 zcma)6XIN9&7QG=PL5hNqr}RreAVM0=B!UJ~2o5l`K|oYO5+O>8Nq~TihCYJM06Hp7 z5d*07C!+%>U8RYrsAEUK0#BM)u#p!Wo%!Z{Z{GLLpL@z$d#|<6zQ@yxK_sy_00(#t z0DP2lg2P(5>-sbg_uN2cF~|3mG^i+A){q+7n!Dviv;So4rpv{V1LfSC_1o`V5RLr0 z{YC4J(N4}(2YaeBX8Mxg<<*F{_o7BFiJxAHo#__MU5R}$B%8k#`{_aat4F((&)Ldx zo^nF`VJvB3;`=jMIbDj9xuN~a7jorXs`7ohQkkWkKKSNgh4SU;_Y*BWwH=>cU0--V zu2d?4|6^DvwPbt|$YDuYs;_drOvGaE;7Y+rZWK@8hMI0}MS(ny8)~Do58g*a$5W&9X{ge-GIu{gp=E?G6_bEPaC3jBm;${j`^u|%oF zE(V}+C2TQIB;^SOpm-aZ6)B9Bx}i{@@{0k!=#QuZ3HGxYEL+IO$yg#B0gGQW^t)5O z$j9e@L;3vAXjLgB(g5zCYX56oNl=1_iwodNgt1~aR|U6R%p@XH#axzDC=L<|W4@Nq zFIp%SN}`1#kV;)F840xA$P;jc@e=eR#m9&2C6Gv20yfu+=7v)3V0kxQn&@Ju!_d z=EZS246%?8el|_!{k;_0-$+4yp>qCC34{KpkiWV>;Z#y^|8dV>w*nZ8v)?;b)tjot zA3e_%C{>*B%xwF4CocU*cU2RQuRpseZ zCo9U!6emiLmmE7@ z__$c9M7&cZ6!2qqZ0AKsZR2v-k*tWVTQ-Mp3JVR{82nvOV1U2hx4u5!-)!(=dNSxV zs)sve{W>?-wPX@;jf=CBqXPkt!(#01R-u{ZH-_Jc;FjBiuiTOP<3j3$xdcV?a zdi&N_Hbyo!7=pu2j>O)|Vjs%N3XQfj)zd>BHqh7Ft(8p3+)9YwXJuPnQJ!mc@X+BJ zq`qcxT1jZB;$-8=TuYXQX zUSptXg!#>zfC3**HQORvM~&)@Z;vyuVDI#TEt)xRgz$DxU-2%hB>HVFOOdROyBR3Q z9@pmRII7X=S!V5Go0mNi3jY(1nr2H@YlOyZZp|}^Pn?RXFHOGkKi0cbvbuy zmX@^)p$o_AmO<4c4&GCA}o;TEy5f%lS<_gcP03@j-B^hB|qKpv2q$Tct2KIF; zkUt$+eoP3NXMmZ_Cn-QY20koDG~5i`;v)G(SV0HJ7#!TRUqcEWb<)4j>1Q=c4J*-k)pB<=$6LfPjinp(S0UNs z9u|lLJl3ExEzYS} zHP{9)MsS+$Ee9|G{iOg@*N*~$ z7iF{!`5XIDa+r3L#y8+I;gcFho;3Ht09vzmy=|BG^tG^alW%rDK#B;6@Gz~M$n|eE zF~_f%6rF`?4<$L@VzQ&>^L*CoydHq9IsX_Nje(z5Y$1=;Ia=+TfglVchTlPtM&-QJ zC~K=M>uB~z1$`?*!t!4|7$ z9~7l;q{%}F=(z{?v5l31b@cBYWuv=C48r)W*%R5^>rV~(vX|*DNv@vy7qT;O`s1tz zY+3czp)<-4M0wHG6aFKGkFLV?PuZO>VRvdWKlGjhl%ejsx(a*eP*(}XO z1_Lf>F1M|F7`eK8#eJ)sq?B=WM7?gyhO&}fPXgOC`%)>;SneLO5!H9z#Uy`NcV%k3 z*~)q9DYKNx%-WUSX(KagAL|*``ijeH)-xBXh_kp&9zC<`EIT6`bP1VRrB3S{As;TX z%;`y{c8rFV*kC;a_T%G>vqO4TE$2F{g;jKIrih+dM9+pcczR@ksTJMz3Fvu>>9|d{ z+R^|GY+LvGqV}o{G1trzk`yi?f7dA6>v={&6hre|f%)ScOXI@tm@6H{a@AuFJfVKYy DvA=a5 literal 0 HcmV?d00001 diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js index 7c09f614d2..b84b6bca07 100644 --- a/src/image/loading_displaying.js +++ b/src/image/loading_displaying.js @@ -55,12 +55,23 @@ import '../core/friendly_errors/fes_core'; * * function setup() { * // here we use a callback to display the image after loading - * loadImage('assets/laDefense.jpg', img => { + * loadImage('assets/arnott-wallace-wink-single-frame.gif', img => { * image(img, 0, 0); * }); * } * * + *
+ * + * let img; + * function setup() { + * img = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); + * } + * function draw() { + * image(img, 0, 0); + * } + * + *
* * @alt * image of the underside of a white umbrella and grided ceililng above @@ -598,106 +609,104 @@ function _createGif( const frames = []; const numFrames = gifReader.numFrames(); let framePixels = new Uint8ClampedArray(pImg.width * pImg.height * 4); - if (numFrames > 1) { - const loadGIFFrameIntoImage = (frameNum, gifReader) => { - try { - gifReader.decodeAndBlitFrameRGBA(frameNum, framePixels); - } catch (e) { - p5._friendlyFileLoadError(8, pImg.src); - if (typeof failureCallback === 'function') { - failureCallback(e); - } else { - console.error(e); - } + const loadGIFFrameIntoImage = (frameNum, gifReader) => { + try { + gifReader.decodeAndBlitFrameRGBA(frameNum, framePixels); + } catch (e) { + p5._friendlyFileLoadError(8, pImg.src); + if (typeof failureCallback === 'function') { + failureCallback(e); + } else { + console.error(e); } - }; - for (let j = 0; j < numFrames; j++) { - const frameInfo = gifReader.frameInfo(j); - const prevFrameData = pImg.drawingContext.getImageData( + } + }; + for (let j = 0; j < numFrames; j++) { + const frameInfo = gifReader.frameInfo(j); + const prevFrameData = pImg.drawingContext.getImageData( + 0, + 0, + pImg.width, + pImg.height + ); + framePixels = prevFrameData.data.slice(); + loadGIFFrameIntoImage(j, gifReader); + const imageData = new ImageData(framePixels, pImg.width, pImg.height); + pImg.drawingContext.putImageData(imageData, 0, 0); + let frameDelay = frameInfo.delay; + // To maintain the default of 10FPS when frameInfo.delay equals to 0 + if (frameDelay === 0) { + frameDelay = 10; + } + frames.push({ + image: pImg.drawingContext.getImageData(0, 0, pImg.width, pImg.height), + delay: frameDelay * 10 //GIF stores delay in one-hundredth of a second, shift to ms + }); + + // Some GIFs are encoded so that they expect the previous frame + // to be under the current frame. This can occur at a sub-frame level + // + // Values : 0 - No disposal specified. The decoder is + // not required to take any action. + // 1 - Do not dispose. The graphic is to be left + // in place. + // 2 - Restore to background color. The area used by the + // graphic must be restored to the background color. + // 3 - Restore to previous. The decoder is required to + // restore the area overwritten by the graphic with + // what was there prior to rendering the graphic. + // 4-7 - To be defined. + if (frameInfo.disposal === 2) { + // Restore background color + pImg.drawingContext.clearRect( + frameInfo.x, + frameInfo.y, + frameInfo.width, + frameInfo.height + ); + } else if (frameInfo.disposal === 3) { + // Restore previous + pImg.drawingContext.putImageData( + prevFrameData, 0, 0, - pImg.width, - pImg.height + frameInfo.x, + frameInfo.y, + frameInfo.width, + frameInfo.height ); - framePixels = prevFrameData.data.slice(); - loadGIFFrameIntoImage(j, gifReader); - const imageData = new ImageData(framePixels, pImg.width, pImg.height); - pImg.drawingContext.putImageData(imageData, 0, 0); - let frameDelay = frameInfo.delay; - // To maintain the default of 10FPS when frameInfo.delay equals to 0 - if (frameDelay === 0) { - frameDelay = 10; - } - frames.push({ - image: pImg.drawingContext.getImageData(0, 0, pImg.width, pImg.height), - delay: frameDelay * 10 //GIF stores delay in one-hundredth of a second, shift to ms - }); - - // Some GIFs are encoded so that they expect the previous frame - // to be under the current frame. This can occur at a sub-frame level - // - // Values : 0 - No disposal specified. The decoder is - // not required to take any action. - // 1 - Do not dispose. The graphic is to be left - // in place. - // 2 - Restore to background color. The area used by the - // graphic must be restored to the background color. - // 3 - Restore to previous. The decoder is required to - // restore the area overwritten by the graphic with - // what was there prior to rendering the graphic. - // 4-7 - To be defined. - if (frameInfo.disposal === 2) { - // Restore background color - pImg.drawingContext.clearRect( - frameInfo.x, - frameInfo.y, - frameInfo.width, - frameInfo.height - ); - } else if (frameInfo.disposal === 3) { - // Restore previous - pImg.drawingContext.putImageData( - prevFrameData, - 0, - 0, - frameInfo.x, - frameInfo.y, - frameInfo.width, - frameInfo.height - ); - } - } - - //Uses Netscape block encoding - //to repeat forever, this will be 0 - //to repeat just once, this will be null - //to repeat N times (1