From c1075b829532371fe63dffb27a74611327bcf7a5 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 21 May 2019 14:56:07 +0300 Subject: [PATCH] Add "Save" button to capture window Allows saving images from both stills and streams by clicking a button. --- .../camera_web_server/main/app_httpd.c | 3 ++ .../main/www/index_ov2640.html | 33 ++++++++++++++++-- .../main/www/index_ov2640.html.gz | Bin 4316 -> 4593 bytes .../main/www/index_ov3660.html | 33 ++++++++++++++++-- .../main/www/index_ov3660.html.gz | Bin 4408 -> 4685 bytes 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/examples/single_chip/camera_web_server/main/app_httpd.c b/examples/single_chip/camera_web_server/main/app_httpd.c index c450642..2d6bba4 100644 --- a/examples/single_chip/camera_web_server/main/app_httpd.c +++ b/examples/single_chip/camera_web_server/main/app_httpd.c @@ -252,6 +252,7 @@ static esp_err_t capture_handler(httpd_req_t *req){ httpd_resp_set_type(req, "image/jpeg"); httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); #if CONFIG_ESP_FACE_DETECT_ENABLED size_t out_len, out_width, out_height; @@ -357,6 +358,8 @@ static esp_err_t stream_handler(httpd_req_t *req){ return res; } + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + while(true){ #if CONFIG_ESP_FACE_DETECT_ENABLED detected = false; diff --git a/examples/single_chip/camera_web_server/main/www/index_ov2640.html b/examples/single_chip/camera_web_server/main/www/index_ov2640.html index 09024d8..5a3c032 100644 --- a/examples/single_chip/camera_web_server/main/www/index_ov2640.html +++ b/examples/single_chip/camera_web_server/main/www/index_ov2640.html @@ -135,7 +135,7 @@ padding: 0 5px } - button { + button, .button { display: block; margin: 5px; padding: 0 12px; @@ -149,6 +149,17 @@ outline: 0 } + .save { + position: absolute; + right: 25px; + top: 0px; + height: 16px; + line-height: 16px; + padding: 0 4px; + text-decoration: none; + cursor: pointer + } + button:hover { background: #ff494d } @@ -543,8 +554,9 @@
@@ -657,6 +669,7 @@ document.addEventListener('DOMContentLoaded', function (event) { const streamButton = document.getElementById('toggle-stream') const enrollButton = document.getElementById('face_enroll') const closeButton = document.getElementById('close-stream') + const saveButton = document.getElementById('save-still') const stopStream = () => { window.stop(); @@ -694,6 +707,22 @@ document.addEventListener('DOMContentLoaded', function (event) { updateConfig(enrollButton) } + saveButton.onclick = () => { + var canvas = document.createElement("canvas"); + canvas.width = view.width; + canvas.height = view.height; + document.body.appendChild(canvas); + var context = canvas.getContext('2d'); + context.drawImage(view,0,0); + try { + var dataURL = canvas.toDataURL('image/jpeg'); + saveButton.href = dataURL; + } catch (e) { + console.error(e); + } + canvas.parentNode.removeChild(canvas); + } + // Attach default on change action document .querySelectorAll('.default-action') diff --git a/examples/single_chip/camera_web_server/main/www/index_ov2640.html.gz b/examples/single_chip/camera_web_server/main/www/index_ov2640.html.gz index f6e19a456a57ee655f704e3db8bafb8ac02b6148..4b90c82679b088d7b29d10ebe4cdbb3de3408657 100644 GIT binary patch literal 4593 zcmV7D70xxQ5KYR837mTWZ+?S@K9NI~gj!V}H>8v3-3=YRRp`HrOm{sz67-*Y7@B zQgeFK@=bCz$J&(4T;s+m|3`!0=@cW2AF|UKCP*`hp@sNL$H&_An#OyBhbxPShH{#m`xW)Gcz@KEa?&o49guWw{dr-LHu1^h`l ze27ir_+EF098ZDCa>BWbKnAvpOYz*AVJ~V|V53MnmJ{$%Ln?=8=2fCCqs#L>tPmib zXc?e69YFtG9Wrw~Zd60<@TfPxtWf3QG5xbTXpSt)@g_sFGA1uH;X+mVER~yDYRGjaUdJJL2JD0+z{H%EkzzZO zD8LFr61kNy3^!MAb(VPi*&!VvlQFja04qnvBV6D7+zAN^NF9X8COD|ZhpAOmV=JCk z3~)Tx@o;_eissFtdh(UW{M)>Z|@N+Zk6NXUo&hu zNNY;&e9{A(YH7%`w5A_8;0TC?8yBuX;+W%>g5?sQktL#b8~Upea_FzpffPJ4^kw>z zDJ;?%{msy2r&M?Gpjd~HX3ZuHT}-u(Mx$g)4I_}MRZf4hQLMqPn$$bV?0ODYE;;awWoTy`t6?6F! zp)yu#!UuL7a;3Z{JW+8ccEQrLkfm#APOCkd&{!Mhw3^HbM zFeoc3?#?gEg&-4axM+;sGLnTe6og$7tBPwkMp>G?j_&+*vQsuD@RrG)gA*1-!CrRQXAOIhew zhK9K1v+b&;(Y6nJhewr_lak9^7QUlHB z7{MqL7wMr^i=mG5wfgo-hfRvdwRj%dz8R^intG16if`L{~2>6$SfBUDWra?D|r_TakwgOnQAoR9MTpDxUfOba)Z+e{b!QD1K;5 zUt2EWzHOsdto4ql`hY?Yde8ux(Zb458nb~6Y{zvwuD`6VM9M9B#ZIeDep6~Ah+O{@ z)c)8GSLzy@C5jE~al46XnG&xA%iEr%L(J(0t!LU81=vNjg5PL`qOyIH!Rv6sMECuy zE_HeBP#mk(W?fP4XFWqbXpM*-2kl9KuWB&U7XJ?U`tjyVB`g65E9xGFHKs0}vW`6_ ztE0MJBixjvP_?PX*;n1qW1AE_{9$$KVR>}xNUJH8kt12eEVe!+W*R-$MqaFvxO`@6 zhA}gd@sp(o7eH;Yg=1ujtvg zgibAIp*hw_cm0W;Aoa$G_b1#^GH2{TqMa^!nZ4 z_y`JGOo-!6!qWqWG)Kq*P*Omf2k1YTK{NB~ zF^OWuw1b%0R1n0_`EzDq3*<&1+I~+re*fd?!zKix-erH#>$Oe~_>i@6-Per^hH7vE zsCt8=%~74`2EznMF7F+mY>wz2(DV*4od9>o+c0;m8x#+C#pTh-7I^OJA|+CjjgNHW z?D>=C5zsief4n*FBi;Cw5_vcPL`Pc?d8ixD7$(4S*}u01Nnl>TGE87!)Vyk9f_TY9 zQ{tzq(I<1e%#Ht!Aa#(dwVhbN0ZaU#p8raeBu_DQqu;CGfWgX9kO5~H&}k*Xe3-r| z12%f7OMbmkh)__AE_LJhuu9%rsAJ5^6c2~t+8Rkgb>mTTyp3KugDvzTk;7Hf83@%3 z^wcB1redn7-9|4oi3cboYilJ2gs>)#_NI}9lpjDJAtDifV!XCSQc%c;$?@K_B9ZeW z=w*&g2e}`xZ9~dhUpEbm8XpU}Bsh0q5ic)~j6jd2Wg z<7t4d*ryoV6g_XTrTqr2;5HT5(*Q%8xD}SWkj&s4ba+4I9NN�b7|dU+TTf1Av55qaL#HfiO| z^&@L@43JY^+qPqFo|Pb@Jo9HY;lFVd$L9J00-K=4^E2(@{ME(lx4VfBFz22E1Lbz# zF#(7eY@(+DSJdN+H@ni(V1H^Fd=Gm1;Nk^#H_#Oar25ic(4)OIatSFvKpO{E@qrP& ziSuws-8jFT`(YH+OsHy&Y_l?$lEO6-FAdU_{X{2&-qBap3Pt`c6*Ji&?@Vakd3v^+ zP&V0H!kO$f;b{D!XriVKn+O32z4ImwguJMJxsB_@WMn<(F!h_eU)5_4E2-VaX(%Tq zc3k?w*SZRkV7X4TGk&&>ZU)=vMy4pMp5t$nY5IecZ>gT~eEpaPFuL*R&2C~Eovda| z+bV)FruJQmEjQ4{k`n%YN7`7{*Tz@QFw5^jKLJ{Pn9R`HIudZY@fIz$r!ODwL|5^o z`_Wgz^1gNEVsCw?qCmRw0(+r$<_BVPo}Flo&AcC#ai;gJuj$MQ0zX(=Wdcq&o^@Wb zqn)TLo^?MOOL*S5(iXPs%-2>KgVK$6ohR_`PSnL`+>f#ZxBFI=WiHoN6u{`lew`_>kF`*@7j4~H=zefI^9v`1(+0Wq0(7e#x@^0?(g#8@*4R0T=3f%g=YKz?6uc z=}_W(7ix^ZNnpzYe6Or3O^JZ>5AB%Y5pYBqJX1Z}f zcM$_z^lW`(Oo-SEd>|@OlGvR@*Wx4TnsLqsYt+iBr=w3{&Eki(rw1NVh`T@wr+oXl z0#wPz6igE7he-)r`45)Ff^7-$NW7u9z(Q@>G{E*qzm?z=lB7dGT2Pp{KB5^2%?VK2 z{WPD@mkjCaT&P}fV4paNyh{%gHUH<|RkletAxs6JYhhrHbf7fw!_W_$iBqTqwX_dZ z;?50L==U@<17}W*80|E^FyMIv;?E;o9vazF6T>(5zeB;UKQ4utWv}_a>E?vXl@~b-_aFi7|_ISn=dc7#htf+m*7@9t9%(CvZo`> ziy&+~U@U0E%v}cULPQiBNwYcGMaQNSciFbqBf!y!GfE@fEmQ_#a_EZMTijoW8#iw* z61dgyBX)c}4pO2(+gsJI+cuZlEFwB%h64L3?F?q zA)b%OU&6A<0S$eAl3ve=IvH4igiWxDq?Gdbs^B~4uI!uUtlBW!Fq{=P=boVuR zdw?;7(9an>>_Je1gkR&YR&{(2tFg;YqQc43W*%uYo;gH;umRy)g-aBZDL{ZB>w2;m z@<{e~go7(U^zrtWI4@iuu+JfU_W@*%(d{ox)z^1mN;qK?Uw`B%Y`Pb4lc9+9)+JNy zH3J;Z0Xlzik25f83bu$S|K)9`$%>X4~S`(eW`%Obi+i?I-5GK)#RXJ z8b%rI6)!0kffd~Oj9+Uu2GG#_66=s&>RJI>KBvt-GlzD%=@$vo|5S$J1+k&u-@Zuk z68|y3)NHWTf`d7E>iFOkar3qKG zYAaI6xvfZH8r>UXN~<&B$aSg&W%?^E7x)aZx#U}vY-w;7fu+ylxWcc|dOZn%P`{Uj zWw*As~u4;A{2E( zt6k8wWFYY?x2XtmxxBF~@3w5LTXE}10aCWq4Q9+r@_2>)hbYNrCJC|p*+gaW#D_^tCM{|uXfjfQ zPUt9wjtBA5DLJhrtYmcRI4J_&@EO|O{E`SSy*abFf?FPtu#_2-I0%O?BD0bd-2#CH-G;HL5s8D{%-&PIz7u( literal 4316 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
@@ -684,6 +696,7 @@ document.addEventListener('DOMContentLoaded', function (event) { const streamButton = document.getElementById('toggle-stream') const enrollButton = document.getElementById('face_enroll') const closeButton = document.getElementById('close-stream') + const saveButton = document.getElementById('save-still') const stopStream = () => { window.stop(); @@ -721,6 +734,22 @@ document.addEventListener('DOMContentLoaded', function (event) { updateConfig(enrollButton) } + saveButton.onclick = () => { + var canvas = document.createElement("canvas"); + canvas.width = view.width; + canvas.height = view.height; + document.body.appendChild(canvas); + var context = canvas.getContext('2d'); + context.drawImage(view,0,0); + try { + var dataURL = canvas.toDataURL('image/jpeg'); + saveButton.href = dataURL; + } catch (e) { + console.error(e); + } + canvas.parentNode.removeChild(canvas); + } + // Attach default on change action document .querySelectorAll('.default-action') diff --git a/examples/single_chip/camera_web_server/main/www/index_ov3660.html.gz b/examples/single_chip/camera_web_server/main/www/index_ov3660.html.gz index cf63cd48dcc2253af1d6adb243e129af8eefe180..b99d3255ef38c362a5440a4c8178317667f33f8b 100644 GIT binary patch literal 4685 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 P|4a10c4Lv$V{`xj%HI5% literal 4408 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