Huh?! Well, you know those street names that baffle? Or are we easily baffleable?! Anyway, you had to be there. And if you ever feel you’re alone with an interest, just look it up in Wikipedia or Google and you’re almost sure to find out …
you are not alone
Yes, our Wikipedia page mentioned Australian Street Type Designations with their lawyerly Australian Street Type Descriptions. Who could ask for more? Well?!
It can be interesting turning a “concept” (or even a “proof of concept” web application) into an, on the side, “game” web application, and that way, learn what’s possible via user action. This is how we felt about yesterday’s Experimental Drag and Drop Primer Tutorial and that teamed with the wonder about how we could add some useful complexity to our “Experimental Drag and Drop” web application’s …
Drop Zone
Can “inheritance” be harnessed to make it work for some complexity of nested HTML elements inside that “Drop Zone” element when the document.body’s onload event happens? We wondered whether a Brady Bunch style 3×3 table could be the go? And whether the nine cells could have a “score” associated with them, and that set of scores be changing over time to make the game more challenging and interesting? Well …
We’ve added the word experimental into today’s blog posting title, mainly because our first of two inspirational webpage sources (last modified on 23/02/2023) regarding somewhat alternative “Drag and Drop” functionalities told us, regarding the DataTransfer object informational “DataTransfer” webpage …
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
… but our testing of the methodologies on various platforms hasn’t totally failed yet on any of the several desktop and mobile platform scenarios we’ve tried. On mobile, we just held on for a sustained touch (down) to make it possible. So maybe the industry has caught up with the ideas? We’re hoping so, because “drag and drop” is a kind of natural thing online users think of to do, and people associate it with “getting things done” we reckon.
Anyway, we relied on the great source code of the second of two inspirational webpages DataTransfer: setData() method, thanks …
The DataTransfer.setData() method sets the drag operation’s drag data to the specified data and type. If data for the given type does not exist, it is added at the end of the drag data store, such that the last item in the types list will be the new type. If data for the given type already exists, the existing data is replaced in the same position. That is, the order of the types list is not changed when replacing data of the same type.
Animated GIF Creation Slide Specific Effects Tutorial
With our animated GIF creator, last referenced with Ffmpeg Shelling Peas Tutorial, we wanted to nuance the way the ImageMagick and GD effects could operate …
they being only applicable to the entire animated GIF output image … before today’s work which makes it so that …
optionally they can be turned on or off for individual animated GIF slides
… thereby allowing more flexibility for the user, we’re hoping.
Please note double click toggles the negation of any GD rotations etcetera for this slide only and will become pale yellow here when in negated status, and that a 4x click on first selection reverses logic to be only 2x click selections from then on for a pale orange slide textbox background.
Well, our wish to “shell peas” setting up more ffmpeg media options based on the excellent FFmpeg cheat sheet, thanks, today, had its ups and downs for speed of progress, but, yes, to have a solid “framework” to work within, that you are happy with, barring those tweaks you inevitably discover in projects as they gain complexity, is the best first endeavour you might need to do, to feel more relaxed about the parts of the project requiring that third party expertise, which it is your job to test that you have successfully merged into the project. And so, onto yesterday’s Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Linear Gradient Tutorial, we have included new …
?>
<?php echo ”
var ffstr=' Concat demuxer, Display the frame number on each frame, Trimming, Delay video, Delay audio, Extract a frame per second, Extract the frames from a video, Mute some of the audio, Extract one frame, Create a video slideshow from images,', offstr=null, kffstr=0, affstr=[];
//
// And then ... later ...
//
if (newv == 'Trimming') {
document.getElementById('minusi').innerHTML='-r 1/5 -i ';
document.getElementById('minusi').title='Parameter -r marks the image framerate (inverse time of each image); -vf fps=25 marks the true framerate of the output';
document.getElementById('sswitches').innerHTML='-ss 00:00:10.000<span id=svframes contenteditable=false> -vframes 1 </span>';
document.getElementById('sswitches').title='Extract one frame at 10 second mark';
document.getElementById('mysub').value=newv;
}
“; ?>
… ffmpeg media functionality talents for you to try yourself, today, in the changedvoiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).
it is hard to “hover swipe” with no linework to show where one option starts and another ends, in Y (or top) co-ordinates … and …
the user has trouble knowing whether their swipe attempt worked
… for which we supply ideas …
linear-gradient background, in the form of a colourful “underlay” div element under (now transparent backgrounded) select (ie. dropdown) element (and associated “overlay” div) … and …
emoji for swipe left ⬅ (⬅) and for swipe right ➡ (➡) shown briefly
class a swipe right (if deltax > 0) else swipe left … resulting in …
immediately show next option innerText if swipe right and show previous option innerText if swipe left
… for you to try for yourself …
Media and document action items … please note you can hover swipe right or left, accurately, and with panache, regarding animated options to speed up transitions between option values
Ffmpeg and Pandoc and ImageMagick and Pdfimages Dropdown Onhover Marquee Tutorial
The non-mobile platforms have that useful wooooorrrrllllddd, the “onhover wooooorrrrllllddd” (to be precise) that can be a great partner for Javascript Ajax methodologies. This onhover (actually the “onmouseover”) event is also useful whereby as a user hovers over an HTML element, and that element’s title attribute has a value, then the user can see that value displayed.
… regarding the dropdown option innerText “look”, there is, for non-mobile, this “onhover wooooorrrrllllddd” we can use to try a form of marquee “look” there, as per …
Proof positive that emojis are text, and can help provide a graphic display interest for a webpage. As well, as a CSS means by which we stop “dropdown Y jitteriness”, we introduce the use of an emoji ⚪ (⚪ or ⚪) for most option element Clayton innerText parts, always …
<?php
var mlook=false, kcnt=0, kprefix='', ksuffix='';
var imstr=' Images to PDF, Images to GIF,', oimstr=null, kimstr=0, aimstr=[];
var pdstr=' PDF to Images, PDF to HTML, PDF to XML,', opdstr=null, kpdstr=0, apdstr=[];
var pastr=' Text to HTML, Text to Rich Text, Text to Word,', opastr=null, kpastr=0, apastr=[];
var ffstr=' Concat demuxer, Display the frame number on each frame,', offstr=null, kffstr=0, affstr=[];
the wording of option elements within the dropdown … and though we’re not going “full marquee Eat at Joes” we are accentuating “midway”, today, by …
adding emoji 🔵 (🔵) movement to the animation for interest sake, as well as being informative (in that the user can anticipate when the new innerText text will arrive, as the emoji moves from left to right)
… that we team with more instances of multiple animation settings …
<?php echo ”
var mlook=false, kcnt=0, kprefix='', ksuffix='';
var imstr=' Images to PDF, Images to GIF,', oimstr=null, kimstr=0, aimstr=[];
var pdstr=' PDF to Images, PDF to HTML, PDF to XML,', opdstr=null, kpdstr=0, apdstr=[];
var pastr=' Text to HTML, Text to Rich Text, Text to Word,', opastr=null, kpastr=0, apastr=[];
var ffstr=' Concat demuxer, ', offstr=null, kffstr=0, affstr=[];
“; ?>
… and a new “between the 8 second setInterval wording refreshes” Javascript function …
function andthen(iidea) {
var outidea=iidea;
var fndpos=-1;
var optsare=document.getElementsByTagName('option'), ioptsare=0;
var iimstr=(imstr.indexOf(',') == -1 ? -1 : outidea.indexOf(imstr.split(',')[0].trim() + ','));
mlook=false;
if (iimstr != -1) {
if ((imstr.split(',')[0].trim() + ',') != imstr.trim()) {
if (document.getElementById('oimagemagick')) {
oimstr=document.getElementById('oimagemagick');
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == imstr.split(',')[0].trim()) {
oimstr=optsare[ioptsare];
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(imstr.split(',')[0].trim(), imstr.split(',')[0].trim() + '' + (imstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipdstr=(pdstr.indexOf(',') == -1 ? -1 : outidea.indexOf(pdstr.split(',')[0].trim() + ','));
if (ipdstr != -1) {
if ((pdstr.split(',')[0].trim() + ',') != pdstr.trim()) {
if (document.getElementById('opdfimages')) {
opdstr=document.getElementById('opdfimages');
mlook=true;
apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pdstr.split(',')[0].trim()) {
opdstr=optsare[ioptsare];
mlook=true;
apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pdstr.split(',')[0].trim(), pdstr.split(',')[0].trim() + '' + (pdstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipastr=(pastr.indexOf(',') == -1 ? -1 : outidea.indexOf(pastr.split(',')[0].trim() + ','));
if (ipastr != -1) {
if ((pastr.split(',')[0].trim() + ',') != pastr.trim()) {
if (document.getElementById('opandoc')) {
opastr=document.getElementById('opandoc');
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pastr.split(',')[0].trim()) {
opastr=optsare[ioptsare];
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pastr.split(',')[0].trim(), pastr.split(',')[0].trim() + '' + (pastr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var iffstr=(ffstr.indexOf(',') == -1 ? -1 : outidea.indexOf(ffstr.split(',')[0].trim() + ','));
if (iffstr != -1) {
if ((ffstr.split(',')[0].trim() + ',') != ffstr.trim()) {
if (document.getElementById('offmpeg')) {
offstr=document.getElementById('offmpeg');
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == ffstr.split(',')[0].trim()) {
offstr=optsare[ioptsare];
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(ffstr.split(',')[0].trim(), ffstr.split(',')[0].trim() + '' + (ffstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
if (mlook) { setInterval(eatatjoes, 8000); }
return outidea;
}
“; ?>
… helped out via the original setInterval Javascript “eatatjoes” function (all kicked off via modified document.body onload logic document.getElementById(‘mainspan’).title = andthen(document.getElementById(‘schoices’).innerText.replace(/\ \;/g,’ ‘).replace(/\ \ /g,’, ‘)); ), as modified, above.
Ffmpeg and Pandoc and ImageMagick and Pdfimages Animated Dropdown Tutorial
Lemon curry?! Animated dropdown?! What gives? Well, it’s not “shelling peas”, yet!
Yes, there is another “framework” step forward we wanted to implement before the peas. And yes, no surprises there, the “framework” work relates to adding functionality to our main dropdown. We’re adding a layer of functionality we’re going to refer to as “animated dropdown”. It amounts to …
has size attribute equal to the number of option elements it contains
logic wise, because our non-nothing option innerTexts have equalled option values (if you Javascript trim() the option innerText, that is), we have the opportunity to start taking more notice of the …
<?php echo ”
function process(tv, tvo) {
var newval='';
var ourtv=tvo.value;
if (tv != '') {
ourtv=tvo.options[tvo.selectedIndex].innerText.trim();
}
if (origval == '') { origval=document.getElementById('mydefopt').title; }
if (tv == '') {
document.getElementById('mainspan').innerHTML=document.getElementById('mydefopt').title;
} else {
document.getElementById('mydefopt').title=ourtv; //tv;
document.getElementById('mainspan').innerHTML=document.getElementById('mydefopt').title;
document.getElementById('schoices').value='';
}
newval=document.getElementById('mydefopt').title;
//alert('origval,newval=' + origval + ' ' + newval);
if (newval != origval) {
origval=newval;
wentfrom(origval, newval);
} else {
origval=newval;
}
}
“; ?>
… option innerHTML as above, meaning …
we can set up Javascript code facilitating the animated feel of some option innerHTML looks that are taken notice of as selected via …
Global variables arranged via each “verb” involved … for today’s “proof of concept” we add one extra Pandoc “Text to Rich Text” option, for now, before the flood of peas arrives …
<?php echo ”
var mlook=false;
var imstr=' Images to PDF, ', oimstr=null, kimstr=0, aimstr=[];
var pdstr=' PDF to Images, ', opdstr=null, kpdstr=0, apdstr=[];
var pastr=' Text to HTML, Text to Rich Text,', opastr=null, kpastr=0, apastr=[];
var ffstr=' Concat demuxer, ', offstr=null, kffstr=0, affstr=[];
“; ?>
As heading title is determined at document.body onload document.getElementById(‘mainspan’).title=andthen(document.getElementById(‘schoices’).innerText.replace(/\ \;/g,’ ‘).replace(/\ \ /g,’, ‘)); …
<?php echo ”
function andthen(iidea) {
var outidea=iidea;
var fndpos=-1;
var optsare=document.getElementsByTagName('option'), ioptsare=0;
var iimstr=(imstr.indexOf(',') == -1 ? -1 : outidea.indexOf(imstr.split(',')[0].trim() + ','));
mlook=false;
if (iimstr != -1) {
if ((imstr.split(',')[0].trim() + ',') != imstr.trim()) {
if (document.getElementById('oimagemagick')) {
oimstr=document.getElementById('oimagemagick');
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == imstr.split(',')[0].trim()) {
oimstr=optsare[ioptsare];
mlook=true;
aimstr=imstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(imstr.split(',')[0].trim(), imstr.split(',')[0].trim() + '' + (imstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipdstr=(pdstr.indexOf(',') == -1 ? -1 : outidea.indexOf(pdstr.split(',')[0].trim() + ','));
if (ipdstr != -1) {
if ((pdstr.split(',')[0].trim() + ',') != pdstr.trim()) {
if (document.getElementById('opdfimages')) {
opdstr=document.getElementById('opdfimages');
mlook=true;
aipdtr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pdstr.split(',')[0].trim()) {
opdstr=optsare[ioptsare];
mlook=true;
apdstr=pdstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pdstr.split(',')[0].trim(), pdstr.split(',')[0].trim() + '' + (pdstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var ipastr=(pastr.indexOf(',') == -1 ? -1 : outidea.indexOf(pastr.split(',')[0].trim() + ','));
if (ipastr != -1) {
if ((pastr.split(',')[0].trim() + ',') != pastr.trim()) {
if (document.getElementById('opandoc')) {
opastr=document.getElementById('opandoc');
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == pastr.split(',')[0].trim()) {
opastr=optsare[ioptsare];
mlook=true;
apastr=pastr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(pastr.split(',')[0].trim(), pastr.split(',')[0].trim() + '' + (pastr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
var iffstr=(ffstr.indexOf(',') == -1 ? -1 : outidea.indexOf(ffstr.split(',')[0].trim() + ','));
if (iffstr != -1) {
if ((ffstr.split(',')[0].trim() + ',') != ffstr.trim()) {
if (document.getElementById('offmpeg')) {
offstr=document.getElementById('offmpeg');
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
} else {
for (ioptsare=0; ioptsare<optsare.length; ioptsare++) {
if (optsare[ioptsare].value == ffstr.split(',')[0].trim()) {
offstr=optsare[ioptsare];
mlook=true;
affstr=ffstr.trim().replace(/\,\ \ /g,',').replace(/\,\ /g,',').replace(/\,$/g,'').split(',');
}
}
}
outidea=outidea.replace(ffstr.split(',')[0].trim(), ffstr.split(',')[0].trim() + '' + (ffstr.replace(imstr.split(',')[0],'').trim() + ',').replace(',,',',').replace(/\,$/g,''));
}
}
if (mlook) { setInterval(eatatjoes, 8000); }
return outidea;
}
“; ?>
… the appeal of all this being that the dropdown height can be controlled by swapping animation for height extension (and user experience downgrades)
Animated dropdown setInterval Javascript function (bit like marquee Eat at Joes type of animation (we’ll see if it gets more like it into the future, perhaps?)) …
ffmpeg … two more media manipulation “verb” stars today …
ImageMagick (can help us with new “Images to PDF” option)
pdfimages (can help us with new “PDF to Images” option) … “verb” collection, today, we wanted to add …
pandoc (can help us with new “Text to HTML” option) …
If you need to convert files from one markup format into another, pandoc is your swiss-army knife.
… to help improve the “one stop shop” aspects, especially regarding “documents”, to our current Intranet feeling web application in the changedvoiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there).
We now present those four in “an expanded out” (at least on non-mobile) dropdown HTML element. Maybe you can guess why?
… and today we are deploying the framework parts and two new media manipulation options regarding PDF that add to our PHP web application’s functionality.
Operating system commands can be thought of to start with …
an action item (to be precise a desktop software file specification) … and, what we often think is, like …
the command’s “verb” part (as funny as that is to think of a “noun” sounding desktop software file specification being like a “verb”) … verbs being action items in a sentence … down to being essential in any sentence … to the point a “verb” can be the whole sentence
We want to add functionality by adding to our first “verb” …
ffmpeg … two more media manipulation “verb” stars today …
ImageMagick (can help us with new “Images to PDF” option)
pdfimages (can help us with new “PDF to Images” option)
…
<select size=7 onchange=process(this.value,this); style=display:inline-block;font-size:8px; id=schoices><option style=text-align:center; id=mydefopt title='Add Voiceover Audio to Video' value=''>⤵ Image⬇Magick ⤶</option><option value='Add Voiceover Audio to Video'> Add Voiceover Audio to Video </option><option style='text-align:center;' value='Images to PDF'> Images to PDF</option><option style='text-align:right;' value='PDF to Images'> PDF to Images</option><option value='Burn subtitles'> Burn subtitles</option><option value='Concat demuxer'> Concat demuxer</option><option value='Rotate a video'> Rotate a video</option></select>
… and then in order to offer the “center” ImageMagick be a link back to the product we introduce some new overlay code …
<?php echo ”
function overlay() {
origval=document.getElementById('schoices').value;
var rect=document.getElementById('fcommand').getBoundingClientRect();
document.getElementById('moreb').style.position='absolute';
document.getElementById('moreb').style.left='' + rect.left + 'px';
document.getElementById('moreb').style.top='' + rect.top + 'px';
document.getElementById('moreb').style.width='96%'; //' + rect.width + 'px';
document.getElementById('moreb').style.height='' + rect.height + 'px';
document.getElementById('moreb').style.border='1px solid black';
document.getElementById('moreb').style.paddingLeft='20px';
document.getElementById('moreb').style.backgroundColor='#f9f9f9';
document.getElementById('fcommand').style.opacity='0.0';
document.getElementById('fcommand').style.cursor='pointer';
document.getElementById('moreb').innerHTML='<span id=precmds></span><span id=verb>ffmpeg" . $ffmpegsuf . "</span> <span id=prescbi></span><span id=minusi> -i </span><span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&left=y\"></iframe></span> <span id=betweenis></span> <span id=secondi>-i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=69075964842271&right=y\"></iframe></span></span> <span id=sswitches>-c copy -map 0:v:0 -map 1:a:0 -shortest</span> out.mp4 > <a target=_blank title=ffimpdf.bad onclick=getvb(); style=cursor:pointer;text-decoration:underline; data-href=./ffimpdf.bad>ffimpdf.bad</a>';
if (firstdivih == '') { firstdivih=document.getElementById('moreb').innerHTML; }
if (firstbutval == '') { firstbutval=document.getElementById('mysub').value; }
document.getElementById('schoices').style.display='inline-block';
function fhoc() {
var rectx=document.getElementById('schoices').getBoundingClientRect();
document.getElementById('doverlay').style.left='' + rectx.left + 'px';
document.getElementById('doverlay').title=document.getElementById('mydefopt').title;
if (document.getElementById('scbi')) {
if (document.getElementById('scbi').innerHTML.indexOf('<') == -1) {
if (document.getElementById('scbi').innerHTML.trim().indexOf(' ') != -1) {
if (document.getElementById('scbi').innerHTML.trim().indexOf(String.fromCharCode(34)) == -1) {
document.getElementById('scbi').innerHTML=String.fromCharCode(34) + document.getElementById('scbi').innerHTML.trim() + String.fromCharCode(34);
}
}
}
}
if (document.getElementById('scbix')) {
if (document.getElementById('scbix').innerHTML.indexOf('<') == -1) {
if (document.getElementById('scbix').innerHTML.trim().indexOf(' ') != -1) {
if (document.getElementById('scbix').innerHTML.trim().indexOf(String.fromCharCode(34)) == -1) {
document.getElementById('scbix').innerHTML=String.fromCharCode(34) + document.getElementById('scbix').innerHTML.trim() + String.fromCharCode(34);
}
}
}
}
}
“; ?>
Javascript to set up the HTML div contenteditable=true look for these two new options …
<?php echo ”
if (newv == 'PDF to Images') {
document.getElementById('moreb').innerHTML=firstdivih.replace(' out.mp4',' " . $minuspng . "');
document.getElementById('secondi').innerHTML='';
document.getElementById('sswitches').innerHTML=\"<span id=sfolder contenteditable=false>newfolder_" . rand(0,784534) . str_replace("\\","\\\\",$ddn) . "\" + '</span>ideas';
It’s getting closer to “shelling peas”, are today’s “Rotate a video via ffmpeg” changes, but we are not there yet. Yes, most programmers want to be “shelling peas” adding functionality to web applications, once they have set up a framework in which they are happy to work. Yesterday’s Ffmpeg Concat Demuxer Tutorial“defence talk” is getting us closer to that “shelling peas” “homeostasis feel” (with an “Intranet” pike, no doubt?!) as you can see from a Javascript “Rotate a video” code snippet below …
<?php echo ”
if (newv == 'Rotate a video') {
document.getElementById('moreb').innerHTML=firstdivih;
… ffmpeg switch definition, by the user, to changing that 1 above as per the hover over advice, to help the user, straight from Mux Video and Audio from another Video, thanks, to advise …
<?php
$rotateadvice="Rotate a video
Rotate 90 clockwise:
ffmpeg -i in.mov -vf \"transpose=1\" out.mov
For the transpose parameter you can pass:
0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip
Use -vf \"transpose=2,transpose=2\" for 180 degrees.";
?>
Yes, the user can still put a bad entry there, but at least the web application has attempted to point them in the right direction, here.
If you examine the changes the changedvoiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder and which you can run that PHP there), am sure that you will concur …
Concat demuxer concatenation of videos ffmpeg functionality, onto the “as of yesterday” …
Voiceovers … and …
Burn subtitles
Rotate a video
… was the simplest functionality component, yet, of the four. We now present those four in “an expanded out” (at least on non-mobile) dropdown HTML element. Maybe you can guess why?
Concat demuxer concatenation of videos ffmpeg functionality, onto the “as of yesterday” …
Voiceovers … and …
Burn subtitles
… progress.
What’s different this time? Well, ffmpeg works the command, we again thank Mux Video and Audio from another Video for (regarding “the plan”), using an interim file …
… and for File API browsing (with our, once again, tweaked inhouse client_browsing.htm) there will be a delay, deriving the file path in “second call PHP”. We handle this by writing two new Javascript functions …
<?php echo ”
var ifile=0, ibfile=0;
function takeoffone() {
ibfile--;
if (ibfile <= 0) {
document.getElementById('mysub').style.cursor='pointer';
} else {
document.getElementById('mysub').style.cursor='progress';
}
}
… available to call from child iframes via parent.takeoneoff(); (from voiceover.php second PHP call) and parent.organizefilenamesize(files[ij].name, files[ij].size); (from client_browsing.htm) respectively, to facilitate a progress cursor on the submit button to remind the user we’d like more time. Along the way, too, we found …
… are the SpongeBob, Patrick, and Squidward of the online woooorrrrllllddd, in an “offence” line of “piecing together an operating system command” thinking, thinking “defence” regarding this we added one (we were pleasantly surprised to discover worked, so as) to have …
div contenteditable=true
spanizing within that div
innerText
mask off parts the programmer wants left untouched via span contenteditable=false
… being like the Hall and Oates meets Everything But the Girl (on a yacht, of course) step back into the ’80s!
The initial inspiration for this current ffmpeg themed series of blog posting was, and still is, Mux Video and Audio from another Video, thanks. So many great ideas, we found, that today we add onto the …
first idea of Voiceovers we’ve established to work with MAMP in macOS and Windows over the previous days, allowing us to now think to add a first suboption idea of …
Burn subtitles … as per our link’s …
Burn subtitles
Use the libass library (make sure your ffmpeg install has the library in the configuration –enable-libass).
First convert the subtitles to .ass format:
ffmpeg -i sub.srt sub.ass
Then add them using a video filter:
ffmpeg -i in.mp4 -vf ass=sub.ass out.mp4
… as a useful video piece of functionality we’d say.
To get this going, easily (from a programming perspective) …
our textarea element remains as the form conduit to the ffmpeg command via the onsubmit event final analysis of the …
underlying div contenteditable=true is “spanned” up a lot more as per …
<?php echo ”
document.getElementById('moreb').innerHTML='<span id=precmds></span><span id=verb>ffmpeg" . $ffmpegsuf . "</span> -i <span id=scbi><iframe onload=checkif(this,\"inv.mp4\"); scrolling=no frameborder=0 id=cbi data-type=file data-value=inv.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:92px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=9075964842271&left=y\"></iframe></span> <span id=betweenis></span> <span id=secondi>-i <span id=scbix><iframe onload=checkiftwo(this,\"inva.mp4\"); scrolling=no frameborder=0 id=cbix data-type=file data-value=inva.mp4 data-accept=\"video/*\" style=\"display:inline-block;height:40px;width:106px;vertical-align:middle;\" src=\"/HTMLCSS/client_browsing.htm?d=9075964842271&right=y\"></iframe></span></span> <span id=sswitches>-c copy -map 0:v:0 -map 1:a:0 -shortest</span> out.mp4 > <a target=_blank title=ffm.bad onclick=getvb(); style=cursor:pointer;text-decoration:underline; data-href=./ffm.bad>ffm.bad</a>';
“; ?>
… and at the onsubmit event Javascript the innerText attribute usage makes it fairly easy to say …
<?php echo ”
function mergechanges() {
if (document.getElementById('scbi').innerHTML.indexOf('<') == -1) {
if (document.getElementById('precmds').innerHTML != '') {
document.getElementById('fcommand').value=document.getElementById('moreb').innerText;
} else {
document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inv.mp4 ', ' ' + document.getElementById('scbi').innerHTML + ' ');
}
//alert('not oops ' + document.getElementById('fcommand').value);
} //else {
//alert('oops');
//}
if (document.getElementById('scbix').innerHTML.indexOf('<') == -1) {
//alert('zoops');
document.getElementById('fcommand').value=document.getElementById('fcommand').value.replace(' inva.mp4 ', ' ' + document.getElementById('scbix').innerHTML + ' ');
}
if (document.getElementById('moreb').innerText.indexOf(' -c ') != -1 && document.getElementById('fcommand').value.indexOf(' -c ') != -1) {
//alert('azoops');
if (document.getElementById('moreb').innerText.split(' -c ')[1] != document.getElementById('fcommand').value.split(' -c ')[1]) {
//alert('bzoops');
document.getElementById('fcommand').value=document.getElementById('fcommand').value.split(' -c ')[0] + ' -c ' + document.getElementById('moreb').innerText.split(' -c ')[1];
}
}
return true;
}
“; ?>
… to slice through that “span” complexity like margarine (or butter that’s been left out on a hot day for approximately 7 hours 17 minutes 23 seconds)
… to work out a file path when supplied a file base name and a file size and you call as above with starting folders. That works well (for deriverability (if that is a word!)) in the “cmd” window but not when called under the auspices of PHP exec or shell_exec. It could be that you lose a lot of a Windows user environment when asking PHP to do some operating system work.
… was “only partially” the story. We found out that that ” | find ” command piping could cause problems on Windows MAMP using shell_exec or exec to do some operating system functionality. But before your enthusiasm oozes over the edges, Windows “forfiles” is still very hard to get working with PHP shell_exec or exec, even using PHP to perform that ” | find ” filtering of results.
Ffmpeg Mux Video and Audio Windows Media Browsing Tutorial
You know it’s “Intranet feely land”?
You look out the train window (tee hee) and see macOS racing through their usual routine.
Of course you’ll pick the buffet car containing the rice bubbles ahead of the vegemite corn flakes?!
But do we need to reiterate that in “Intranet feely land” you’ve got your macOS typose of work not suiting “arch Windows” methodologies? Take the case of …
At least, with macOS MAMP there is the excellent command line “file” we can use to show information about some potential input files you could use in this, so far, user unfriendly, “first draft” version of the PHP.
I command thee mux, hey you, with audible you, over yonder, by dale and meadow be, yea!
… when it occurred to us we could turn the base filename parts of those “file.exe” reports into links that when clicked mapped those clicked files into place into the “ffmpeg” command being developed above (as alternative input file designator idea to browsing or div contenteditable=true typing ways), in the changedvoiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder) and which you can run that PHP there.
There be a flowerin’ of inner warmth and glo’ towards all our readers, youngins and oldins alike … like!
Yes, we’re involving good ol’ HTML5 File API Object Javascript logic, so our “Intranet” savvy downloaders out there …
Full o’ inner warmth and glo’ towards each other … like!
… can easily browse for their two media input files, and for the first time ever integrating our ever tweaked inhouse client_browsing.htm (also a standalone proposition) (we’d like you to download to MAMP Document Root’s HTMLCSS subfolder) we add “oncontextmenu” event changes to its input type=file browser hosting parent iframe element onload event Javascript function as per …
<?php echo ”
var voaf='', voaftwo='';
function checkif(iois, ival) {
if (iois.src.indexOf('?d=') != -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }
if (aconto.getElementById('files')) {
if (voaf == '') {
voaf=iois.src;
iois.setAttribute('data-parentspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
document.getElementById('myh1').title='s' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix');
document.getElementById('myh1').setAttribute('data-url', iois.src);
setInterval(voaff, 1000);
} else if (voaftwo == '') {
voaftwo=iois.src;
iois.setAttribute('data-parentspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
document.getElementById('myh3').title='s' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix');
document.getElementById('myh3').setAttribute('data-url', iois.src);
//alert(iois.id + ' data-parentspan=' + iois.getAttribute('data-parentspan'));
}
//alert(iois.id + ' data-parentspan=' + iois.getAttribute('data-parentspan'));
aconto.getElementsByTagName('h1')[0].style.opacity='0.0';
//alert('here');
aconto.getElementById('files').style.position='absolute';
aconto.getElementById('files').style.left='0px';
aconto.getElementById('files').style.top='0px';
aconto.getElementById('files').style.zIndex='99';
aconto.getElementById('files').style.marginLeft='10px';
aconto.getElementById('files').style.marginTop='8px';
aconto.getElementById('files').style.visibility='visible';
aconto.getElementById('files').style.display='block';
aconto.getElementById('files').style.backgroundColor='#eeeeee';
aconto.getElementById('files').setAttribute('data-hostcont', ival);
aconto.getElementById('files').setAttribute('data-hostspan', 's' + ival.replace('inv.mp4','cbi').replace('inva.mp4','cbix'));
aconto.getElementById('files').oncontextmenu = function(event) { var suf=event.target.getAttribute('data-hostspan'); parent.document.getElementById(suf).innerHTML=\"" . str_replace("\\","\\\\",dirname(__FILE__) . DIRECTORY_SEPARATOR) . "\" + event.target.getAttribute('data-hostcont'); }
if (ival == 'inv.mp4') {
aconto.getElementById('files').accept='video/*';
aconto.getElementById('files').title='Click to browse for video else right click or two finger gesture to make disappear.';
} else {
aconto.getElementById('files').accept='video/*,audio/*';
aconto.getElementById('files').title='Click to browse for video or audio else right click or two finger gesture to make disappear.';
}
//alert('there');
aconto.getElementById('dwstyle').innerHTML+=\"<style> #files::before { content: '\" + ival + \"'; } </style>\";
}
}
}
}
“; ?>
… to allow a user who prefers the overlayed div contenteditable=true alternative (which speaks back to the HTML form textarea conduit when that form’s “onsubmit” event is called) onto yesterday’s exclusively textarea methodology …
… reign supreme collecting their media file specification information in the changedvoiceover.php PHP (we’d want you to download to a local MAMP Apache web server’s Document Root folder) and which you can run that PHP there.
The previous work of Animated GIF Creation Install Paths Tutorial‘s thread of blog postings has been a great help with this ffmpeg “Intranet feeling” integration work we use, around here, in conjunction with macOS or Windows operating system MAMP Apache local web server environments.
We’ve got another “Intranet feeling” PHP web application “first draft” for you today. The reason we’re opting for “Intranet feeling” (ie. we’re asking you to download the voiceover.php PHP to a local MAMP Apache web server and run the PHP there from its Document Root folder) is that we want to further explore the brilliant …
At least, with macOS MAMP there is the excellent command line “file” we can use to show information about some potential input files you could use in this, so far, user unfriendly, “first draft” version of the PHP.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
We’re glad today’s “Image Filter Display Tutorial” blog posting title is shorter than yesterday’s “Animated GIF Duration Calculation Filter Browsing Tutorial” because the main task today was …
to take all our “proof of concept” web applications and distil them down to an “Image Filter Display” web application of far greater simplicity … and along that way …
we had to play around with one more “proof of concept” idea, that of allowing the user to control the content of the CSS filters dropdown, and our first “out there” thought that contenteditable=true could be applied to all the dropdown’s option elements to achieve this needed to be disproved (as it took two hours to be sure of … to be sure) … in favour of a new dropdown “Change” option solution …
function callresell() {
var oselo=document.getElementById('simgag');
var svalis='';
var sc=';';
var changefound=false;
if (document.getElementById('imgag')) {
oselo.value=document.getElementById('imgag').title;
}
var reselit=prompt('Please change the semicolon separated options list. Optionally hash # separate a CSS filter refresh interval in seconds (currently ' + eval(Math.abs(ingifint) / 1000.000) + ' seconds).', oselo.innerText);
if (reselit != null) {
if (reselit.indexOf('#') != -1) {
if (ingifint < 0) {
ingifint=Math.round(eval(-1000.0 * eval('' + reselit.split('#')[1].split(';')[0])));
} else {
ingifint=Math.round(eval(1000.0 * eval('' + reselit.split('#')[1].split(';')[0])));
}
reselit=reselit.replace('#' + reselit.split('#')[1].split(';')[0], '');
}
}
if (reselit == null) {
return '';
} else if (reselit != oselo.innerText) {
var sih=oselo.innerHTML;
var vsl=reselit.split(';');
var shi=sih.split('</option>');
var ssize='' + oselo.size;
var vssize=0;
var newih='';
for (var ihi=0; ihi<vsl.length; ihi++) {
if (vsl[ihi].trim() != '') {
if (vsl[ihi].trim() == 'Change') { changefound=true; sc=''; } else { sc=';'; }
if (eval('' + shi.length) > ihi) {
if (eval('' + (shi[ihi] + '</option>').split(vsl[ihi].trim() + sc).length) == 3) {
newih+=shi[ihi] + '</option>';
vssize++;
} else {
svalis=shi[ihi].split(' value="')[1].split('"')[0];
newih+=shi[ihi].split('>')[0].replace(svalis, vsl[ihi].trim() + sc) + '>' + vsl[ihi].trim() + sc + '</option>';
vssize++;
}
} else if (vsl[ihi].trim().indexOf('filter:') == 0) {
newih+='<option contenteditable=true value="' + vsl[ihi].trim() + sc + '">' + vsl[ihi].trim() + sc + '</option>';
vssize++;
} else {
newih+='<option contenteditable=true value="' + vsl[ihi].trim() + '">' + vsl[ihi].trim() + '' + '</option>';
vssize++;
}
}
}
if (!changefound) {
newih+='<option contenteditable=true value="Change">Change</option>';
vssize++;
}
oselo.innerHTML=newih;
if (eval('' + ssize) != eval('' + vssize)) {
oselo.size='' + eval('' + vssize);
}
}
return '';
}
Can a “proof of concept” arrangement last three blog postings? If there’s more you want to prove, ahead of committing to the final product that might hone in on the specificity of the idea, and another iframe hosted web application joins in on “proof of concept” goings on and will be useful into the future, we’d say it’s possible, yes. But we would say that, wouldn’t we?!
In our defence, it is easier to prove all solutions to all the contentious issues, and then hone in and reduce to make a specific new web application, rather than extending and still needing to prove as you go along, not knowing whether an issue will cause you insurmountable issues in the future.
A quirk with our new HTML button element within an HTML form had us, initially, before realizing …
onmousedown event event.stopPropagation() usage can be used to cancel a following onclick event on non-mobile … and …
ontouchdown (yay!!!) event event.stopPropagation() usage can be used to cancel a following onclick event on mobile
… as in …
<button title='Click or touch here, as required, for chance to browse for Animated GIF' ontouchdown='event.stopPropagation(); spagif();' onmousedown='event.stopPropagation(); spagif();'><sup>Animated</sup><sub>GIF</sub></button>
Can a “proof of concept” arrangement last two blog postings? If there’s more you want to prove, ahead of committing to the final product that might hone in on the specificity of the idea, we’d say it’s possible, yes. And so, continuing on from the recent Animated GIF Duration Calculation Primer Tutorial we tweak its PHP hosting “proof of concept” parent web application to try out our second point we’re out to prove …
We want to prove that CSS filter works for animated GIFs as well as it appears to work with other image types of elements.
Conservative worry, we grant you, but we did want to make sure this all worked, and happily, it was all fine …
var ingif='', ingifstyle='filter: none;', ingifint=0, ingifchosen=false;
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
ingif=whatgifmaybe;
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
We’ve got a new (mini-?)project developing. No, it doesn’t hurt in the “you know what”! But thanks for your concern?!
It’s a project that reminds us about an adage regarding projects, that might seem pretty obvious, but is worth mentioning …
Many projects being 90% perspiration, 10% inspiration, there might be the “not sure we can do” items that should be tackled first.
That truism is all well and good, but not always possible, of course, when you have to set up the difficult environment ahead of testing this unknown. Not so, with the “unknown” of our new project …
We want to know whether we can detect an animated GIF media file playing duration, ideally in client side Javascript, and if not possible there, we would settle for a server side PHP solution.
We slotted its thinking (and Javascript (via PHP) …
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
/** @param {Uint8Array} uint8 */
function isGifAnimated (uint8) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
let duration = 0;
for (let i = 0, len = uint8.length; i < len; i++) {
if (uint8[i] == 0x21
&& uint8[i + 1] == 0xF9
&& uint8[i + 2] == 0x04
&& uint8[i + 7] == 0x00)
{
const delay = (uint8[i + 5] << 8) | (uint8[i + 4] & 0xFF);
duration += delay < 2 ? 10 : delay;
}
}
//alert('' + eval(duration / 100));
if (eval(duration / 100) > 0.11) {
if (document.getElementById('aside')) {
document.getElementById('aside').innerHTML=' (<?php echo $image; ?> animated GIF duration is ' + eval(duration / 100) + ' seconds)';
}
}
document.body.style.cursor='pointer';
return duration / 100; // if 0.1 is not an animated GIF
}
... logic), you might say in a "kludgy" way (but, for us, serving a "proof of concept" purpose), that allows us to proceed on other aims of our project that will become apparent into the near future. No, we are not totally "out of the woods" yet regarding "unknowns" but today's changedread_exif_off_image_rotate.phpPHP image exif reporter web application) into the "onblur" logic of an image URL textbox HTML element, that web application talked about when we presented Gimp Guillotine Image File Browse Media Tutorial. You might try it yourself, but not sure "animated GIF and exif" mix, if you get my meaning, but if your image is an animated GIF you should be informed of its duration, in seconds, up the top of the webpage (given permissions and all, that is)?
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
Can a “proof of concept” arrangement last three blog postings? If there’s more you want to prove, ahead of committing to the final product that might hone in on the specificity of the idea, and another iframe hosted web application joins in on “proof of concept” goings on and will be useful into the future, we’d say it’s possible, yes. But we would say that, wouldn’t we?!
In our defence, it is easier to prove all solutions to all the contentious issues, and then hone in and reduce to make a specific new web application, rather than extending and still needing to prove as you go along, not knowing whether an issue will cause you insurmountable issues in the future.
A quirk with our new HTML button element within an HTML form had us, initially, before realizing …
onmousedown event event.stopPropagation() usage can be used to cancel a following onclick event on non-mobile … and …
ontouchdown (yay!!!) event event.stopPropagation() usage can be used to cancel a following onclick event on mobile
… as in …
<button title='Click or touch here, as required, for chance to browse for Animated GIF' ontouchdown='event.stopPropagation(); spagif();' onmousedown='event.stopPropagation(); spagif();'><sup>Animated</sup><sub>GIF</sub></button>
Can a “proof of concept” arrangement last two blog postings? If there’s more you want to prove, ahead of committing to the final product that might hone in on the specificity of the idea, we’d say it’s possible, yes. And so, continuing on from the recent Animated GIF Duration Calculation Primer Tutorial we tweak its PHP hosting “proof of concept” parent web application to try out our second point we’re out to prove …
We want to prove that CSS filter works for animated GIFs as well as it appears to work with other image types of elements.
Conservative worry, we grant you, but we did want to make sure this all worked, and happily, it was all fine …
var ingif='', ingifstyle='filter: none;', ingifint=0, ingifchosen=false;
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
ingif=whatgifmaybe;
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
We’ve got a new (mini-?)project developing. No, it doesn’t hurt in the “you know what”! But thanks for your concern?!
It’s a project that reminds us about an adage regarding projects, that might seem pretty obvious, but is worth mentioning …
Many projects being 90% perspiration, 10% inspiration, there might be the “not sure we can do” items that should be tackled first.
That truism is all well and good, but not always possible, of course, when you have to set up the difficult environment ahead of testing this unknown. Not so, with the “unknown” of our new project …
We want to know whether we can detect an animated GIF media file playing duration, ideally in client side Javascript, and if not possible there, we would settle for a server side PHP solution.
We slotted its thinking (and Javascript (via PHP) …
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
/** @param {Uint8Array} uint8 */
function isGifAnimated (uint8) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
let duration = 0;
for (let i = 0, len = uint8.length; i < len; i++) {
if (uint8[i] == 0x21
&& uint8[i + 1] == 0xF9
&& uint8[i + 2] == 0x04
&& uint8[i + 7] == 0x00)
{
const delay = (uint8[i + 5] << 8) | (uint8[i + 4] & 0xFF);
duration += delay < 2 ? 10 : delay;
}
}
//alert('' + eval(duration / 100));
if (eval(duration / 100) > 0.11) {
if (document.getElementById('aside')) {
document.getElementById('aside').innerHTML=' (<?php echo $image; ?> animated GIF duration is ' + eval(duration / 100) + ' seconds)';
}
}
document.body.style.cursor='pointer';
return duration / 100; // if 0.1 is not an animated GIF
}
... logic), you might say in a "kludgy" way (but, for us, serving a "proof of concept" purpose), that allows us to proceed on other aims of our project that will become apparent into the near future. No, we are not totally "out of the woods" yet regarding "unknowns" but today's changedread_exif_off_image_rotate.phpPHP image exif reporter web application) into the "onblur" logic of an image URL textbox HTML element, that web application talked about when we presented Gimp Guillotine Image File Browse Media Tutorial. You might try it yourself, but not sure "animated GIF and exif" mix, if you get my meaning, but if your image is an animated GIF you should be informed of its duration, in seconds, up the top of the webpage (given permissions and all, that is)?
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
PicPick Windows Audio and Screenshot Presentations Primer Tutorial
Thanks to the heads up from the APC magazine, in a recent issue, we were really interested to download and try a Windows desktop application called PicPick which can help with Screen Capture Presentations Without or With Audio. It was that “or With Audio” of huge interest to us, and yes, our …
downloading and install … then …
simple GIF presentation … then …
simple MP4 video presentation (with audio) …
… was all great! The only gripe here being the huge disk size of the (5 seconds worth of recording equating to 25mB) GIF, totally overridden by the excitement of the “audio overlay in MP4 video” (though we’d much prefer Stephen Fry to “yours truly”?!)
Another issue that may surprise is that the Windows PrtScn button (screenshooting functionality) is fed into PicPick (workflows), if you have PicPick installed. It took us about a minute to get used to that, but we thought we should mention that, as it is definitely worthwhile you experiment with the myriad PicPick “presentation helpers” in PicPick’s main menu that you can see in today’s animated GIF presentation of our first look at PicPick.
If this was interesting you may be interested in this too.
Can a “proof of concept” arrangement last two blog postings? If there’s more you want to prove, ahead of committing to the final product that might hone in on the specificity of the idea, we’d say it’s possible, yes. And so, continuing on from the recent Animated GIF Duration Calculation Primer Tutorial we tweak its PHP hosting “proof of concept” parent web application to try out our second point we’re out to prove …
We want to prove that CSS filter works for animated GIFs as well as it appears to work with other image types of elements.
Conservative worry, we grant you, but we did want to make sure this all worked, and happily, it was all fine …
var ingif='', ingifstyle='filter: none;', ingifint=0, ingifchosen=false;
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
ingif=whatgifmaybe;
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
We’ve got a new (mini-?)project developing. No, it doesn’t hurt in the “you know what”! But thanks for your concern?!
It’s a project that reminds us about an adage regarding projects, that might seem pretty obvious, but is worth mentioning …
Many projects being 90% perspiration, 10% inspiration, there might be the “not sure we can do” items that should be tackled first.
That truism is all well and good, but not always possible, of course, when you have to set up the difficult environment ahead of testing this unknown. Not so, with the “unknown” of our new project …
We want to know whether we can detect an animated GIF media file playing duration, ideally in client side Javascript, and if not possible there, we would settle for a server side PHP solution.
We slotted its thinking (and Javascript (via PHP) …
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
/** @param {Uint8Array} uint8 */
function isGifAnimated (uint8) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
let duration = 0;
for (let i = 0, len = uint8.length; i < len; i++) {
if (uint8[i] == 0x21
&& uint8[i + 1] == 0xF9
&& uint8[i + 2] == 0x04
&& uint8[i + 7] == 0x00)
{
const delay = (uint8[i + 5] << 8) | (uint8[i + 4] & 0xFF);
duration += delay < 2 ? 10 : delay;
}
}
//alert('' + eval(duration / 100));
if (eval(duration / 100) > 0.11) {
if (document.getElementById('aside')) {
document.getElementById('aside').innerHTML=' (<?php echo $image; ?> animated GIF duration is ' + eval(duration / 100) + ' seconds)';
}
}
document.body.style.cursor='pointer';
return duration / 100; // if 0.1 is not an animated GIF
}
... logic), you might say in a "kludgy" way (but, for us, serving a "proof of concept" purpose), that allows us to proceed on other aims of our project that will become apparent into the near future. No, we are not totally "out of the woods" yet regarding "unknowns" but today's changedread_exif_off_image_rotate.phpPHP image exif reporter web application) into the "onblur" logic of an image URL textbox HTML element, that web application talked about when we presented Gimp Guillotine Image File Browse Media Tutorial. You might try it yourself, but not sure "animated GIF and exif" mix, if you get my meaning, but if your image is an animated GIF you should be informed of its duration, in seconds, up the top of the webpage (given permissions and all, that is)?
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
The other day, out and about using an iPhone, we started out with the battery at 100% but within 5 minutes it had gone to about 85%, if my memory serves me correctly. Ideally, we wanted the iPhone to last another 4 hours, so the projections for that were not good.
Am sure am no Robinson Crusoe getting this scenario happen?! So, what are some steps mere mortals can apply, given you cannot get to a power source (and these days, there are those portable power sources available) to try to prolong the life of the battery on the iPhone in situ? Today’s animated GIF presentation shows some of what we suggest below, and it goes without saying your own research can be great here, and the wooooorrrrrlllldddd knowledge on this matter is huuuuuuuuggggggeee.
First off, we find the most natural approach is to double touch the iPhone’s Home Button to see a horizontally cascading view of applications open, that you can swipe up to close as you think necessary, is a first good starting point.
Next might be, even so, take a more scientific approach and go to …
Settings -> Battery
… and see what applications are using power, and plan further as to what needs changing, perhaps, within that app’s Settings, to help. Also, within the “Settings -> Battery” realm, there is a “Low Power Mode” switch you could turn on, even before you are prompted for it, to …
Low Power Mode temporarily reduces background activity like downloads and mail fetch until you can fully charge your iPhone.
For us though, what seemed to be the most effective idea, as we talked about with Location Services iPad Battery Loss Issue Tutorial, was to turn off all “Location Services” functionality immediately via …
Settings -> Privacy -> Location Services ... turn off switch
… which, in practice, being as we cannot commit this to memory, we got to the steps above via “Settings -> Search … typed in Location Services”.
Also notorious for eating up battery, can be any Weather app you have set to be always monitoring. Perhaps a look, in Settings, at an app itself, inside its subsettings might help here? We turned off a Weather app’s ability to access “Mobile Data” on our iPhone, for example.
Also an option is to dim the display (or … gasp … power it off) via, for us, a bottom left diagonal swipe towards top right, causing the menu with display brightness be adjustable, in order for you to turn it down lower, as another idea (not shown on today’s presentation animated GIF). (And isn’t the torch marvellous to find and bring your pooch back in at 2am in the morning?!)
The upshot? Taking these steps well and truly got us through the 4 hours needed, with lots of battery power yet to be used up. But if it hadn’t worked, what then? There are thoughts that some malware these days can hang around your iPhone goings on, maybe, but that some of these might be neutralized via powering your iPhone off, and then (as required) back on (and if that helped, perhaps you should be looking into Malware Removal apps).
Location Services iPad Battery Loss Issue Tutorial
Do you own an iPad that loses battery power too fast?
We were, and the kind and honest people at iExperts set us right that we had the “Location Services” setting set to on.
As related at this useful link here are good steps to remedy this issue …
First, go to the iPad’s Settings by touching the Setting icon. It looks like gears in motion.
Next, scroll down the left-side menu and tap “Privacy.”
If you want to completely turn off Location Services, tap the button at the top of the screen next to Location Services, as you can see with today’s tutorial picture.
If you just want to turn it off in a single app, scroll down the list until you see the app’s name. You can choose to “Never” allow an app access, to “Always” allow an app access, or to only allow access “While Using the App.”
Share My Location will show your location in text messages sent through iMessage and through the Find My Friends app. If you are only turning off location services for individual apps, you may want to turn this setting off as well.
… and, if you are like us, what you will see is that your iPad battery fully charged will last hours longer than it used to, presumably because it will have periods now where nothing is asked of it, whereas having “Location Services” set to “on” requires some power virtually the whole time.
Well, this fix, using just its first 3 steps, above, might be thought of as a bit crude. What if there is good use made of “Location Services”? Well, a less crude method is outlined at this link … thanks. We used its methodology to arrive at the Weather app component (used by Notification Services) and set it to be “Never” rather than “Always”, the “Always” apps being the ones that badly affect the battery life of the iPad. So we show this less crude approach with the images below.
Trap for young … cough, cough … players, we presume?!
If this was interesting you may be interested in this too.
If this was interesting you may be interested in this too.
We’ve got a new (mini-?)project developing. No, it doesn’t hurt in the “you know what”! But thanks for your concern?!
It’s a project that reminds us about an adage regarding projects, that might seem pretty obvious, but is worth mentioning …
Many projects being 90% perspiration, 10% inspiration, there might be the “not sure we can do” items that should be tackled first.
That truism is all well and good, but not always possible, of course, when you have to set up the difficult environment ahead of testing this unknown. Not so, with the “unknown” of our new project …
We want to know whether we can detect an animated GIF media file playing duration, ideally in client side Javascript, and if not possible there, we would settle for a server side PHP solution.
We slotted its thinking (and Javascript (via PHP) …
function prefetch(whatgifmaybe) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
if ((whatgifmaybe.toLowerCase().trim().split('#')[0] + '?').indexOf('.gif?') != -1) {
document.body.style.cursor='progress';
fetch(whatgifmaybe)
.then(res => res.arrayBuffer())
.then(ab => isGifAnimated(new Uint8Array(ab)))
.then(console.log);
}
}
/** @param {Uint8Array} uint8 */
function isGifAnimated (uint8) { // thanks to https://stackoverflow.com/questions/69564118/how-to-get-duration-of-gif-image-in-javascript#:~:text=Mainly%20use%20parseGIF()%20%2C%20then,duration%20of%20a%20GIF%20image.
let duration = 0;
for (let i = 0, len = uint8.length; i < len; i++) {
if (uint8[i] == 0x21
&& uint8[i + 1] == 0xF9
&& uint8[i + 2] == 0x04
&& uint8[i + 7] == 0x00)
{
const delay = (uint8[i + 5] << 8) | (uint8[i + 4] & 0xFF);
duration += delay < 2 ? 10 : delay;
}
}
//alert('' + eval(duration / 100));
if (eval(duration / 100) > 0.11) {
if (document.getElementById('aside')) {
document.getElementById('aside').innerHTML=' (<?php echo $image; ?> animated GIF duration is ' + eval(duration / 100) + ' seconds)';
}
}
document.body.style.cursor='pointer';
return duration / 100; // if 0.1 is not an animated GIF
}
... logic), you might say in a "kludgy" way (but, for us, serving a "proof of concept" purpose), that allows us to proceed on other aims of our project that will become apparent into the near future. No, we are not totally "out of the woods" yet regarding "unknowns" but today's changedread_exif_off_image_rotate.phpPHP image exif reporter web application) into the "onblur" logic of an image URL textbox HTML element, that web application talked about when we presented Gimp Guillotine Image File Browse Media Tutorial. You might try it yourself, but not sure "animated GIF and exif" mix, if you get my meaning, but if your image is an animated GIF you should be informed of its duration, in seconds, up the top of the webpage (given permissions and all, that is)?
If this was interesting you may be interested in this too.