Yesterdayโs Making of Ffmpeg Video Overall Effects Tutorialโs โfirst draftโ feel of our inhouse Bookmark Export Filtering web application showed just that. Yes, there was quite a lot to improve on, the way we saw it being โฆ
- adding a (local system) file browsing means (called by our <iframe scrolling=no frameborder=0 id=cbi data-style=โborder-top:1px solid black;border-bottom:1px solid black;border-left:2px solid yellow;border-right:1px solid yellow;โ style=โwidth:173px;height:228px;margin-top:-194px;โ src=โ/HTMLCSS/client_browsing.htm?totype=html&d=189786754โฒ></iframe> file browsing helper) โฆ
function yesthreethree(restis) {
if (document.getElementById('bmkdata')) {
if (restis.indexOf('data:') == 0) {
if (restis.indexOf(';base64,') != -1) {
document.getElementById('bmkdata').value='' + window.atob(restis.split(';base64,')[1]);
analyze(document.getElementById('bmkdata')); //document.getElementById('bmkdata').blur();
} else if (restis.indexOf(';utf8,') != -1) {
document.getElementById('bmkdata').value='' + (restis.split(';utf8,')[1]);
analyze(document.getElementById('bmkdata')); //document.getElementById('bmkdata').blur();
}
} else {
document.getElementById('bmkdata').value=restis;
analyze(document.getElementById('bmkdata')); //document.getElementById('bmkdata').blur();
}
}
}
โฆ by which to add Web Browser Bookmark Exporting Data File Content into that lower HTML textarea element (and unlock the two UL/LI and Table button elements) โฆ as well as โฆ - add a details/summary โrevealโ means by which the user can show working actual HTML elements in addition to the HTML coding weโve only be showing (with that โfirst draftโ)
- add Sharing functionality via either Email or SMS conduits
โฆ and because the amounts of data can be large (and too big for a method=GET HTML form arrangement that clientside HTML/Javascript is capable of servicing) we were glad adding this Sharing functionality that yesterday weโd already started down the line of thinking that the โฆ
- lower HTML textarea content โฆ would always be associated with โฆ
- hashtag โฆ representation
โฆ because with these methodologies the web server restrictions on (address bar) URL lengths (ie. error 414) melt away, at least for data lengths weโve encountered with our testing so far, and that applies also to โฆ
- โmailto:โ โaโ URL links to Email a recipient โฆ or โฆ
- โsms:โ โaโ URL links to SMS a recipient
โฆ Sharing โฆ
var mysubject='My Bookmarked Links ...', xlocationhref='';
if (('' + location.hash).indexOf('bmkdata=') != -1) { locationhash=location.hash; }
function doemail() {
if (document.getElementById('bmkdata').value.trim() != '') {
locationhash='#bmkdata=' + window.btoa(encodeURIComponent(document.getElementById('bmkdata').value));
mysubject='My Bookmarked Links ...';
if (document.getElementById('dtone').value.trim() != '' && document.getElementById('dttwo').value.trim() != '') {
mysubject='My Bookmarked Links from ' + document.getElementById('dtone').value.trim() + ' to ' + document.getElementById('dttwo').value.trim() + ' ... ';
} else if (document.getElementById('dtone').value.trim() != '') {
mysubject='My Bookmarked Links from ' + document.getElementById('dtone').value.trim() + ' ... ';
} else if (document.getElementById('dttwo').value.trim() != '') {
mysubject='My Bookmarked Links up until ' + document.getElementById('dttwo').value.trim() + ' ... ';
}
if (ulli && !utable) {
recipient=prompt('Please enter email address to send to? Will output UL/LI else if some blanks will output Table. Default email Subject is ' + mysubject + ' ... but if you want a different one append a hash (#) followed by your own Subject for the Email.', '');
if (recipient == null) { recipient=''; } else if (recipient.indexOf('@') == -1) { recipient=''; } else if (eval('' + recipient.indexOf('#')) > eval('' + recipient.indexOf('@'))) { mysubject=recipient.split('#')[1]; recipient=recipient.split('#')[0]; }
if (recipient.indexOf(' ') != -1) {
locationhref=document.URL.split('?')[0].split('#')[0] + '?table=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
} else {
locationhref=document.URL.split('?')[0].split('#')[0] + '?ulli=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
}
xlocationhref=locationhref;
if (recipient.trim() != '') {
if (1 == 1) {
processit();
} else {
document.getElementById('spareshare').href='mailto:' + recipient.replace(/\ /g,'') + '?subject=' + encodeURIComponent(mysubject) + '&body=' + encodeURIComponent(locationhref + locationhash);
document.getElementById('spareshare').click();
recipient='';
}
}
} else if (utable) {
recipient=prompt('Please enter email address to send to? Will output UL/LI else if some blanks will output Table. Default email Subject is ' + mysubject + ' ... but if you want a different one append a hash (#) followed by your own Subject for the Email.', '');
if (recipient == null) { recipient=''; } else if (recipient.indexOf('@') == -1) { recipient=''; } else if (eval('' + recipient.indexOf('#')) > eval('' + recipient.indexOf('@'))) { mysubject=recipient.split('#')[1]; recipient=recipient.split('#')[0]; }
if (recipient.indexOf(' ') != -1) {
locationhref=document.URL.split('?')[0].split('#')[0] + '?table=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
} else {
locationhref=document.URL.split('?')[0].split('#')[0] + '?ulli=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
}
xlocationhref=locationhref;
if (recipient.trim() != '') {
if (1 == 1) {
processit();
} else {
document.getElementById('spareshare').href='mailto:' + recipient.replace(/\ /g,'') + '?subject=' + encodeURIComponent(mysubject) + '&body=' + encodeURIComponent(locationhref + locationhash);
document.getElementById('spareshare').click();
recipient='';
}
}
}
}
}
function dosms() {
if (document.getElementById('bmkdata').value.trim() != '') {
locationhash='#bmkdata=' + window.btoa(encodeURIComponent(document.getElementById('bmkdata').value));
if (ulli && !utable) {
recipient=prompt('Please enter SMS number to send to? Will output UL/LI else if some blanks will output Table.', '');
if (recipient == null) { recipient=''; } else if (recipient.trim() != '' && recipient.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != '') { recipient=''; }
if (recipient.indexOf(' ') != -1) {
locationhref=document.URL.split('?')[0].split('#')[0] + '?table=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
} else {
locationhref=document.URL.split('?')[0].split('#')[0] + '?ulli=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
}
xlocationhref=locationhref;
if (recipient.trim() != '') {
if (1 == 1) {
processit();
} else {
document.getElementById('spareshare').href='sms:' + recipient.replace(/\ /g,'') + '&body=' + encodeURIComponent(locationhref + locationhash);
document.getElementById('spareshare').click();
recipient='';
}
}
} else if (utable) {
recipient=prompt('Please enter SMS number to send to? Will output UL/LI else if some blanks will output Table.', '');
if (recipient == null) { recipient=''; } else if (recipient.trim() != '' && recipient.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') != '') { recipient=''; }
if (recipient.indexOf(' ') != -1) {
locationhref=document.URL.split('?')[0].split('#')[0] + '?table=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
} else {
locationhref=document.URL.split('?')[0].split('#')[0] + '?ulli=y&dtone=' + encodeURIComponent(document.getElementById('dtone').value) + '&dttwo=' + encodeURIComponent(document.getElementById('dttwo').value); // + '#bmkdata=' + encodeURIComponent(document.getElementById('bmkdata').value);
}
xlocationhref=locationhref;
if (recipient.trim() != '') {
if (1 == 1) {
processit();
} else {
document.getElementById('spareshare').href='sms:' + recipient.replace(/\ /g,'') + '&body=' + encodeURIComponent(locationhref + locationhash);
document.getElementById('spareshare').click();
recipient='';
}
}
}
}
}
function fillin() {
if (document.getElementById('rt') && document.getElementById('rd') && document.getElementById('rs')) {
if (document.getElementById('rd').innerHTML == document.getElementById('rs').outerHTML) {
document.getElementById('rd').innerHTML=document.getElementById('rs').outerHTML + document.getElementById('rt').value;
}
}
}
// Coming back from an email or SMS link click ...
if (document.URL.indexOf('?') == -1 && ('' + location.hash).indexOf('bmkdata=') != -1) {
setTimeout(function(){
document.getElementById('resulting').innerHTML=decodeURIComponent(('' + location.hash).split('bmkdata=')[1]).replace('><summary', ' open><summary').replace('<details title=', '<details data-title=');
fillin();
}, 5000);
}
โฆ concepts, happily. Keeping it all โjust clientsideโ means we can be talking meaningfully to a larger chunk of audience โฆ if youโre listening, that is?!
So, again, feel free to try our โseconddraftโ dated_bookmarkshtml Dated Bookmark Export web application, yourself, perhaps below.
Previous relevant Making of Ffmpeg Video Overall Effects Tutorial is shown below.
At the end of yesterdayโs Ffmpeg Video Overall Effects Tutorial there was an Unordered List โฆ
- curves โ ffmpeg examples
- Converts GIMP colour curve to something the FFmpeg can read in the curve filter ยท GitHub
- Top 20 best commands for FFmpeg
- Create video with 5 images with fadeIn/out effect in ffmpeg
- ffmpeg Color Correction: Gamma, Brightness and Saturation
- Accidentally applied an โincandescent lightโ video filter on a video I filmed on my Sony RX100. Is there any way to remove or reverse this effect on the video?
- More Cool FFmpeg Tricks
- Creating Retro Glow Effects with FFmpeg
- Is it possible to generate such effects purely with ffmpeg?
- Creating a retro glow effect with FFmpeg
- FFmpeg Filters Documentation
โฆ of links, am sure a lot of you would guess, were gleaned (within our Google Chrome web browser History (of that day)) Bookmarked (by us) webpages. We actually compiled via (the clunky and fairly slow) โฆ
- left half (of screen) with (Google Chrome) History showing, and right half with BBEdit Text Editor open at a new (ostensibly empty) file with loads of empty records available, and dragged URL records (identifiable, for us, via an asterisk, indicating a webpage was Bookmarked) from the left into the right to bring over the URLs (only) above, the rest constructed in a more manual way โฆ and another way could have been โฆ
- use Google Chrome webpage showing Bookmark list and use its Export Bookmarks (no other choice but โAllโ) to a file that could be waded through to derive the list above โฆ and then we thought of chance to code for โฆ
- hybrid โinhouseโ clientside (ie. HTML/Javascript/CSS) web application โฆ
โฆ so far asking for the content of a web browser Export Bookmarks operationโs output fileโs HTML (in the case of Google Chrome) content in an HTML textarea element (the user can fill in themselves), and filterable via two input type=datetime-local starting and ending datetime(s) of interest (the user can fill in, optionally)
โฆ and we wish we could have got that hour and a half back, from yesterday, via swapping yesterday for today?!
Feel free to try our โfirst draftโ proofof concept Dated Bookmark Export web application, yourself.
Did you know?
Not all web browser brands have any Export Bookmarks functionality, like Google Chrome offers here on macOS. Weโre going to be examining others, over time, and try to make our inhouse logic fit in with how that Bookmark data looks, on export, should we find any other Web Browser brands offering this functionality.
Previous relevant Ffmpeg Video Overall Effects Tutorial is shown below.
Todayโs work (all on our macOS MAMP local Apache/PHP/MySQL web server environment) is only โtoe dippingโ in a โgreat big sea of possibilitiesโ regarding the great ffmpegโs โfiltering style abilitiesโ further to yesterdayโs Ffmpeg Video Subliminal Message Tutorial, but โฆ
- as you try out things you discover others โฆ
- can be a foot in the door researching this type of work yourself โฆ
โฆ weโre hoping. And itโs not as if ffmpeg was on itโs own here with the second concept below โฆ
- fade in and fade out video effect โฆ inspired by Top 20 best commands for FFmpeg to try โฆ
ffmpeg -i brush__turkey.m4v -vf "fade=in:0:5,fade=out:73:5" brushturkey_fadein_fadeout.m4v - colour balancing improvements regarding an underexposed video
โฆ as the โฆ
- Gimp image editorโs abilities (matching a lot of what you read Photoshop can help with too) with Curves helped out โฆ along with โฆ
- Python expertly designed to link Gimp and ffmpeg โwhole of videoโ manipulations
โฆ enacting โฆ
- selection of a video still image, ideally not containing the Brush Turkey โฆ
- open image in Gimp
- โAoifeโโesque Colours -> Curvesโฆ
- opens Adjust Colour Curves subwindow (initially a straight line)
- but dragging it to become a curve in a way that brightens the underexposed image to improve โฆ we then โฆ
- click + button to Save presets to a name โฆ
- controlled by left pointing infilled triangle icon click that Manages Presets โฆ and we ended up with โฆ
- bush_-_turkey.presets โฆ
- and then we discovered this Converts GIMP colour curve to something the FFmpeg can read in the curve filter excellent project, the extraction of the Python there allowing us to go โฆ
python3 ../gimp_curves_ffmpeg.py
โฆ to output brush.out โฆ
โฆ - which formed most of the final curves โ ffmpeg examples inspired ffmpeg command โฆ
ffmpeg -y -i brush__turkey.m4v -filter_complex "
[0:v]
curves=
master='0.0/0 0.01171875/0.033751864777061671 0.0234375/0.067435644319434537 0.03515625/0.10098325339242978 0.046875/0.1343266067613586 0.05859375/0.16739761919153215 0.0703125/0.20012820544826168 0.08203125/0.23245028029685835 0.09375/0.26429575850263332 0.10546875/0.29559655483089792 0.1171875/0.32628458404696314 0.12890625/0.35629176091614018 0.140625/0.38555000020374036 0.15234375/0.41399121667507488 0.1640625/0.44154732509545486 0.17578125/0.46815024023019147 0.1875/0.49373187684459596 0.19921875/0.51822414970397945 0.2109375/0.54155897357365324 0.22265625/0.56366826321892849 0.234375/0.58448393340511628 0.24609375/0.6039378988975278 0.2578125/0.62196207446147445 0.26953125/0.63848837486226717 0.28125/0.65344871486521738 0.29296875/0.66677500923563593 0.3046875/0.67964838149075235 0.31640625/0.6910493179152648 0.328125/0.70214399210941336 0.33984375/0.71293769240972005 0.3515625/0.72343570715270744 0.36328125/0.73364332467489723 0.375/0.74356583331281156 0.38671875/0.75320852140297312 0.3984375/0.76257667728190348 0.41015625/0.77167558928612512 0.421875/0.78051054575216006 0.43359375/0.78908683501653032 0.4453125/0.7974097454157586 0.45703125/0.80548456528636625 0.46875/0.81331658296487608 0.48046875/0.82091108678780988 0.4921875/0.82827336509169003 0.50390625/0.83540870621303842 0.515625/0.84232239848837742 0.52734375/0.84901973025422939 0.5390625/0.85550598984711601 0.55078125/0.86178646560355965 0.5625/0.86786644586008233 0.57421875/0.87375121895320629 0.5859375/0.87944607321945378 0.59765625/0.88495629699534695 0.609375/0.89028717861740791 0.62109375/0.89544400642215893 0.6328125/0.90043206874612158 0.64453125/0.90525665392581867 0.65625/0.9099230502977721 0.66796875/0.91443654619850423 0.6796875/0.91880242996453687 0.69140625/0.92302598993239249 0.703125/0.92711251443859277 0.71484375/0.93106729181966053 0.7265625/0.93489561041211733 0.73828125/0.93860275855248565 0.75/0.94219402457728751 0.76171875/0.94567469682304517 0.7734375/0.94905006362628086 0.78515625/0.95232541332351639 0.796875/0.95550603425127423 0.80859375/0.9585972147460764 0.8203125/0.96160424314444504 0.83203125/0.96453240778290228 0.84375/0.96738699699797048 0.85546875/0.97017329912617156 0.8671875/0.97289660250402765 0.87890625/0.97556219546806111 0.890625/0.97817536635479407 0.90234375/0.98074140350074845 0.9140625/0.98326559524244661 0.92578125/0.98575322991641046 0.9375/0.98820959585916268 0.94921875/0.99063998140722487 0.9609375/0.99304967489711937 0.97265625/0.99544396466536833 0.984375/0.9978281390484941 0.99609375/1":red="0.0/0 0.01171875/0.011764705882352943 0.0234375/0.023529411764705879 0.03515625/0.035294117647058816 0.046875/0.047058823529411764 0.05859375/0.058823529411764712 0.0703125/0.07058823529411766 0.08203125/0.082352941176470587 0.09375/0.094117647058823528 0.10546875/0.10588235294117647 0.1171875/0.11764705882352938 0.12890625/0.12941176470588237 0.140625/0.14117647058823532 0.15234375/0.15294117647058825 0.1640625/0.1647058823529412 0.17578125/0.17647058823529413 0.1875/0.18823529411764706 0.19921875/0.20000000000000007 0.2109375/0.21176470588235291 0.22265625/0.22352941176470589 0.234375/0.23529411764705882 0.24609375/0.24705882352941175 0.2578125/0.25882352941176473 0.26953125/0.27058823529411768 0.28125/0.28235294117647064 0.29296875/0.29411764705882348 0.3046875/0.30588235294117649 0.31640625/0.31764705882352934 0.328125/0.3294117647058824 0.33984375/0.3411764705882353 0.3515625/0.35294117647058826 0.36328125/0.3647058823529411 0.375/0.37647058823529411 0.38671875/0.38823529411764712 0.3984375/0.39999999999999997 0.41015625/0.41176470588235292 0.421875/0.42352941176470582 0.43359375/0.43529411764705883 0.4453125/0.44705882352941184 0.45703125/0.45882352941176474 0.46875/0.47058823529411764 0.48046875/0.48235294117647054 0.4921875/0.49411764705882355 0.50390625/0.50588235294117645 0.515625/0.51764705882352946 0.52734375/0.52941176470588236 0.5390625/0.54117647058823526 0.55078125/0.55294117647058827 0.5625/0.56470588235294117 0.57421875/0.57647058823529407 0.5859375/0.58823529411764708 0.59765625/0.59999999999999998 0.609375/0.61176470588235299 0.62109375/0.62352941176470589 0.6328125/0.63529411764705879 0.64453125/0.6470588235294118 0.65625/0.65882352941176481 0.66796875/0.6705882352941176 0.6796875/0.68235294117647061 0.69140625/0.69411764705882351 0.703125/0.70588235294117663 0.71484375/0.71764705882352942 0.7265625/0.7294117647058822 0.73828125/0.74117647058823533 0.75/0.75294117647058822 0.76171875/0.76470588235294112 0.7734375/0.77647058823529425 0.78515625/0.78823529411764703 0.796875/0.80000000000000004 0.80859375/0.81176470588235294 0.8203125/0.82352941176470584 0.83203125/0.83529411764705874 0.84375/0.84705882352941175 0.85546875/0.85882352941176465 0.8671875/0.87058823529411766 0.87890625/0.88235294117647056 0.890625/0.89411764705882357 0.90234375/0.90588235294117636 0.9140625/0.91764705882352937 0.92578125/0.92941176470588238 0.9375/0.94117647058823528 0.94921875/0.95294117647058818 0.9609375/0.96470588235294119 0.97265625/0.97647058823529409 0.984375/0.98823529411764721 0.99609375/1":green="0.0/0 0.01171875/0.011764705882352943 0.0234375/0.023529411764705879 0.03515625/0.035294117647058816 0.046875/0.047058823529411764 0.05859375/0.058823529411764712 0.0703125/0.07058823529411766 0.08203125/0.082352941176470587 0.09375/0.094117647058823528 0.10546875/0.10588235294117647 0.1171875/0.11764705882352938 0.12890625/0.12941176470588237 0.140625/0.14117647058823532 0.15234375/0.15294117647058825 0.1640625/0.1647058823529412 0.17578125/0.17647058823529413 0.1875/0.18823529411764706 0.19921875/0.20000000000000007 0.2109375/0.21176470588235291 0.22265625/0.22352941176470589 0.234375/0.23529411764705882 0.24609375/0.24705882352941175 0.2578125/0.25882352941176473 0.26953125/0.27058823529411768 0.28125/0.28235294117647064 0.29296875/0.29411764705882348 0.3046875/0.30588235294117649 0.31640625/0.31764705882352934 0.328125/0.3294117647058824 0.33984375/0.3411764705882353 0.3515625/0.35294117647058826 0.36328125/0.3647058823529411 0.375/0.37647058823529411 0.38671875/0.38823529411764712 0.3984375/0.39999999999999997 0.41015625/0.41176470588235292 0.421875/0.42352941176470582 0.43359375/0.43529411764705883 0.4453125/0.44705882352941184 0.45703125/0.45882352941176474 0.46875/0.47058823529411764 0.48046875/0.48235294117647054 0.4921875/0.49411764705882355 0.50390625/0.50588235294117645 0.515625/0.51764705882352946 0.52734375/0.52941176470588236 0.5390625/0.54117647058823526 0.55078125/0.55294117647058827 0.5625/0.56470588235294117 0.57421875/0.57647058823529407 0.5859375/0.58823529411764708 0.59765625/0.59999999999999998 0.609375/0.61176470588235299 0.62109375/0.62352941176470589 0.6328125/0.63529411764705879 0.64453125/0.6470588235294118 0.65625/0.65882352941176481 0.66796875/0.6705882352941176 0.6796875/0.68235294117647061 0.69140625/0.69411764705882351 0.703125/0.70588235294117663 0.71484375/0.71764705882352942 0.7265625/0.7294117647058822 0.73828125/0.74117647058823533 0.75/0.75294117647058822 0.76171875/0.76470588235294112 0.7734375/0.77647058823529425 0.78515625/0.78823529411764703 0.796875/0.80000000000000004 0.80859375/0.81176470588235294 0.8203125/0.82352941176470584 0.83203125/0.83529411764705874 0.84375/0.84705882352941175 0.85546875/0.85882352941176465 0.8671875/0.87058823529411766 0.87890625/0.88235294117647056 0.890625/0.89411764705882357 0.90234375/0.90588235294117636 0.9140625/0.91764705882352937 0.92578125/0.92941176470588238 0.9375/0.94117647058823528 0.94921875/0.95294117647058818 0.9609375/0.96470588235294119 0.97265625/0.97647058823529409 0.984375/0.98823529411764721 0.99609375/1":blue="0.0/0 0.01171875/0.011764705882352943 0.0234375/0.023529411764705879 0.03515625/0.035294117647058816 0.046875/0.047058823529411764 0.05859375/0.058823529411764712 0.0703125/0.07058823529411766 0.08203125/0.082352941176470587 0.09375/0.094117647058823528 0.10546875/0.10588235294117647 0.1171875/0.11764705882352938 0.12890625/0.12941176470588237 0.140625/0.14117647058823532 0.15234375/0.15294117647058825 0.1640625/0.1647058823529412 0.17578125/0.17647058823529413 0.1875/0.18823529411764706 0.19921875/0.20000000000000007 0.2109375/0.21176470588235291 0.22265625/0.22352941176470589 0.234375/0.23529411764705882 0.24609375/0.24705882352941175 0.2578125/0.25882352941176473 0.26953125/0.27058823529411768 0.28125/0.28235294117647064 0.29296875/0.29411764705882348 0.3046875/0.30588235294117649 0.31640625/0.31764705882352934 0.328125/0.3294117647058824 0.33984375/0.3411764705882353 0.3515625/0.35294117647058826 0.36328125/0.3647058823529411 0.375/0.37647058823529411 0.38671875/0.38823529411764712 0.3984375/0.39999999999999997 0.41015625/0.41176470588235292 0.421875/0.42352941176470582 0.43359375/0.43529411764705883 0.4453125/0.44705882352941184 0.45703125/0.45882352941176474 0.46875/0.47058823529411764 0.48046875/0.48235294117647054 0.4921875/0.49411764705882355 0.50390625/0.50588235294117645 0.515625/0.51764705882352946 0.52734375/0.52941176470588236 0.5390625/0.54117647058823526 0.55078125/0.55294117647058827 0.5625/0.56470588235294117 0.57421875/0.57647058823529407 0.5859375/0.58823529411764708 0.59765625/0.59999999999999998 0.609375/0.61176470588235299 0.62109375/0.62352941176470589 0.6328125/0.63529411764705879 0.64453125/0.6470588235294118 0.65625/0.65882352941176481 0.66796875/0.6705882352941176 0.6796875/0.68235294117647061 0.69140625/0.69411764705882351 0.703125/0.70588235294117663 0.71484375/0.71764705882352942 0.7265625/0.7294117647058822 0.73828125/0.74117647058823533 0.75/0.75294117647058822 0.76171875/0.76470588235294112 0.7734375/0.77647058823529425 0.78515625/0.78823529411764703 0.796875/0.80000000000000004 0.80859375/0.81176470588235294 0.8203125/0.82352941176470584 0.83203125/0.83529411764705874 0.84375/0.84705882352941175 0.85546875/0.85882352941176465 0.8671875/0.87058823529411766 0.87890625/0.88235294117647056 0.890625/0.89411764705882357 0.90234375/0.90588235294117636 0.9140625/0.91764705882352937 0.92578125/0.92941176470588238 0.9375/0.94117647058823528 0.94921875/0.95294117647058818 0.9609375/0.96470588235294119 0.97265625/0.97647058823529409 0.984375/0.98823529411764721 0.99609375/1'
[v]" -map '[v]' -an brushturkey_better_colour.m4v
โฆ was crucial to our discoveries today โฆ
- fade in and fade out video effect โฆ
- colour balancing improvements regarding an underexposed video โฆ
Further reading for you here, could involve โฆ
- curves โ ffmpeg examples
- Converts GIMP colour curve to something the FFmpeg can read in the curve filter ยท GitHub
- Top 20 best commands for FFmpeg
- Create video with 5 images with fadeIn/out effect in ffmpeg
- ffmpeg Color Correction: Gamma, Brightness and Saturation
- Accidentally applied an โincandescent lightโ video filter on a video I filmed on my Sony RX100. Is there any way to remove or reverse this effect on the video?
- More Cool FFmpeg Tricks
- Creating Retro Glow Effects with FFmpeg
- Is it possible to generate such effects purely with ffmpeg?
- Creating a retro glow effect with FFmpeg
- FFmpeg Filters Documentation
Previous relevant Ffmpeg Video Subliminal Message Tutorial is shown below.
Revisiting the brilliant ffmpeg, as discussed at the recent Ffmpeg Install and Public Face Tutorial โฆ
- the other day we were reading the excellent Fastest way to extract frames using ffmpeg? and noted it down for a future discussion โฆ and then today โฆ
- we were inspired by a Brush Turkey which we videoed via an iPhoneโs Camera appโs Video mode of capture option โฆ
- downloaded to this MacBook Air (via AirDrop โฆ good for Apple sharing when the sizes get big โฆ raw video 1:19s long)
And thatโs where we are at here, thinking this would be a good opportunity to try creating a Subliminal Message video. But before we go on and โgive the game awayโ you may want to see the result of our Subliminal Message insertion via ffmpeg theme to our work, in action, below. Unlock or give up to unlock the content below the video quiz below โฆ
What is the secret word? | |
---|---|
Raw video โฆ to itโs slides โฆ | |
ffmpeg -i ../IMG_2784.MOV -r 1/1 %03d.jpg ffmpeg -i %03d.jpg brush_turkey.m4v |
|
Hard guess? | |
ffmpeg -r 8 -i %03d.jpg brush-turkey.m4v | |
Easier guess? | |
ffmpeg -r 6 -i %03d.jpg brush__turkey.m4v | |
Congratulations! Yes, in between the โRaw Videoโ ffmpeg work and onto the other ffmpeg commands we renamed one slide to a *.jpeg equivalent and then set about replacing the *.jpg original slide with our Subliminal Message slide, as you can see here.
Previous relevant Ffmpeg Install and Public Face Tutorial is shown below.
Our recent web server VPS migration can not only be โฆ
- a migration of functionality (eg. this WordPress blog) โฆ as well as โฆ
- an opportunity to open up new vistas of serverside functionality
โฆ such as todayโs ffmpeg install, which is only feasible because of the โฆ
- additional diskspace โฆ chance on new web server allows for โฆ
- chance to install ffmpeg โฆ
dnf config-manager --set-enabled powertools
dnf install --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm -y
dnf install --nogpgcheck https://mirrors.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-$(rpm -E %rhel).noarch.rpm -y
dnf install ffmpeg
โฆ thanks to this great link, along with ImageMagick โฆ
โฆ on this new โpublic faceโ (even more public when DNS is applied later).
Codewise this involved โฆ
- thechanged macos_ffmpeg_convert
php works the old way and now in the new way โฆ and is helped out by โฆ
- atweaked client_browsing
htm client side HTML and Javascript inhouse helper
โฆ further to recent work touching these ideas with Animated GIF Creator Overlayed Images Top Left Tutorial.
See some of this public install of ffmpeg here.
Previous relevant Animated GIF Creator Overlayed Images Top Left Tutorial is shown below.
To add to the recent Animated GIF Creator Overlayed Images Tutorialโs user interaction logic, we add a way to control those two โoverlayโ CSS properties โฆ
- left
- top
โฆ but more in the sense that we allow CSS โฆ
- margin-eft
- margin-top
โฆ come into the picture, after a dalliance with CSS calc thoughts.
This allows for offsetted images be part of the โoverlay mixโ that you can retry this at ourchanged tutorial_to_animated_gifphp inhouse public domain Animated GIF Creator.
Previous relevant Animated GIF Creator Overlayed Images Tutorial is shown below.
We wanted to add an โOverlayed Imagesโ functionality component to the โAnimated GIF Creatorโ of Animated GIF Creator Video Intranet Tutorial, today.
The work involves both of the HTML design โbig conceptsโ we are keen on at this blog โฆ
- overlay โฆ via CSS control of โฆ
- position:absolute;top:0px;left:0px;
- opacity:1.0;
- z-index:1;
- reveal โฆ lately, mostly, via HTML use of โฆ
- details
- summary
โฆ the latter being the โcontainerโ for our interactive input be able to control overlay items 2 and 3, which affect the โoverlayed imagesโ output display via the clicking of a new โOverlay Imagesโ button. That button โฆ
<input disabled onclick="overlaythem();" id="overlayit" type="button" title='Overlay Images' value='Overlay Images'></input>
โฆ starts off as disabled โฆ and works with new HTML div elements โฆ
<div id=overlayedj><h1> </h1><br></div><div id=overlayedi></div>
โฆ until at least two images are defined, at which time the button becomes enabled โฆ
function onfit(ithis) {
if (ithis.value == '' && ('' + ithis.placeholder).indexOf(']') != -1) {
ithis.value=('' + ithis.placeholder).split('[')[1].split(']')[0];
}
ithis.type='number';
}
function overlayds(inm, newop, newzi) {
var outdets='';
var divrect=null;
var poslt=' data-style=\"position:absolute;left:px;top:px;\" ';
var reposit='';
if (!document.getElementById('detsum' + ('' + inm))) {
if (document.getElementById('overlayedi').innerHTML == '') {
document.getElementById('overlayedi').title='Overlayed Images Below ... Click for It in New Window ...';
document.getElementById('overlayedj').innerHTML='<h1>Overlayed Images Below ...</h1><br>';
divrect=document.getElementById('overlayedi').getBoundingClientRect();
poslt=' data-style=\"position:absolute;left:' + ('' + divrect.left).split('.')[0].trim() + 'px;top:' + ('' + eval(200 + eval('' + ('' + divrect.top).split('.')[0]))).trim() + 'px;\" ';
} else {
poslt=' data-style=\"' + document.getElementById('detsum1').getAttribute('data-style') + '\" ';
}
outdets=' <details ' + poslt + ' id=\"detsum' + ('' + inm) + '\" style=\" display:inline-block; \" open><summary id=\"sumdet' + ('' + inm) + '\">Overlay</summary><input onchange=overlayds(' + inm + ',this.value,String.fromCharCode(32)); onblur=overlayds(' + inm + ',this.value,String.fromCharCode(32)); type=text onfocus=onfit(this); id=\"opacity' + ('' + inm) + '\" style=\" display:inline-block; \" placeholder=\"Opacity [1.00]\" value=\"\" step=0.01 min=0.00 max=1.00></input><br><input onfocus=onfit(this); onchange=overlayds(' + inm + ',String.fromCharCode(32),this.value); onblur=overlayds(' + inm + ',String.fromCharCode(32),this.value); type=text id=\"zindex' + ('' + inm) + '\" style=\" display:inline-block; \" placeholder=\"Z-Index [1]\" value=\"\" min==999 max=999 step=1></input><br></details>';
reposit=poslt.replace(' data-',' ');
reposit=reposit.replace('\"', '\"opacity:1.0;z-index:1;');
if (document.getElementById('overlayedi').innerHTML == '') {
document.getElementById('overlayedi').innerHTML='<img id=\"imgdet' + ('' + inm) + '\" src=\"' + document.getElementById('slideshow' + ('' + inm).replace(/^1$/g,'')).value + '\" ' + reposit + '></img>';
document.getElementById('overlayedi').style.width=('' + document.getElementById('imgdet' + ('' + inm)).width).replace('px','') + 'px';
document.getElementById('overlayedi').style.height=('' + document.getElementById('imgdet' + ('' + inm)).height).replace('px','') + 'px';
document.getElementById('overlayedi').onclick = function(){ var woo=window.open('','_blank','top=100,left=100,width=' + document.getElementById('overlayedi').style.width.replace('px','') + ',height=' + document.getElementById('overlayedi').style.height.replace('px','')); woo.document.write('<html><head><title>Overlayed Images Below ...</title></head><body>' + document.getElementById('overlayedi').outerHTML.replace(/left\:[\ ]*/g,'left:0.0').replace(/top\:[\ ]*/g,'top:0.0') + '</body></html>'); woo.document.title='Overlayed Images Below ...'; };
} else {
document.getElementById('overlayedi').innerHTML+='<img id=\"imgdet' + ('' + inm) + '\" src=\"' + document.getElementById('slideshow' + ('' + inm).replace(/^1$/g,'')).value + '\" ' + reposit + '></img>';
}
} else {
document.getElementById('detsum' + ('' + inm)).style.display='inline-block';
if (newop != ' ') {
if (newop.trim() == '') {
document.getElementById('imgdet' + inm).style.opacity='1.0';
} else {
document.getElementById('imgdet' + inm).style.opacity='' + newop;
}
}
if (newz != ' ') {
if (newz.trim() == '') {
document.getElementById('imgdet' + inm).style.zIndex='1';
} else {
document.getElementById('imgdet' + inm).style.zIndex='' + newzi;
}
}
}
return outdets;
}
function overlaythem() {
var suffidea=1;
while (document.getElementById('slideshow' + ('' + suffidea).replace(/^1$/g, '')).value != '') {
document.getElementById('ours' + ('' + suffidea)).innerHTML+=overlayds(suffidea,'','');
suffidea++;
}
}
You can try this at ourchanged tutorial_to_animated_gifphp inhouse public domain Animated GIF Creator.
Previous relevant Animated GIF Creator Video Intranet Tutorial is shown below.
With the recent Animated GIF Creator Video Revisit Tutorial (preceding Animated GIF Creator Video Share Tutorial) we wrote โฆ
โฆ one reason being that we do not want to install the wonderful ffmpeg (command line video creation tool) on the RJM Programming domain, but, in macOS, here with MAMP, we are quite happy to live with the Homebrew (Terminal applicationโs) install โฆ
โฆ setting up what could be โlost functionalityโ, but today, we come around to either adding a new โฆ
Convert to Video
โฆ dropdown option should all be ritchy ditch, and if not, often we will add new โAdviceโ dropdown options to remind the user what theyโd need to arrange to get to a โConvert to Videoโ scenario.
Selecting โConvert to Videoโ sets up a hydrid โInternet/Intranetโ feeling scenario where โฆ
- the user is using ourchanged tutorial_to_animated_gif
php inhouse public domain Animated GIF Creator containing this new โConvert to Videoโ option off the โImageMagickโ dropdown โฆ
- the user defines some image slide data โฆ eg. browsing to create data-URIs (but careful not to do too many) โฆ
- the user selects that โConvert to Videoโ option โฆ
- a window.open popup calls URL like โฆ
HTTP://localhost:8888/PHP/animegif/tutorial_to_animated_gif.php?video=1687644
โฆ in a new window โฆ - those data-URIs are converted into /tmp/jmtmp0*.[imageExt] files โฆ ready for โฆ
- ffmpeg commands like โฆ
ffmpeg -framerate 0.1 -i /tmp/jmtmp%03d.jpeg -c:v libvpx-vp9 -pix_fmt yuva420p -lossless 1 -c:a copy video.webm; ffmpeg -i video.webm video.mov 2>> video.bad
โฆ be nested in PHP exec (via MAMP local web server incarnation of the inhouse Animated GIF Creator) as a way to create videos โฆ - which can be downloaded within that public domain โparentโ inhouse Animated GIF Creator session
Which begs the question โฆ
How do we know when to offer the "Convert to Video" option on that dropdown?
This logic is centred around a few useful ideas (with this cross domain scenario ruling out Ajax and Iframe src= definitions, as useful ways to go) โฆ
- open the MAMP local web server โHTTP://localhost:8888/PHP/animegif/tutorial_to_animated_gif.phpโ URLs in an iframe (with onload event logics) pointed at by a window.open second argument (effectively avoiding any loose useful or not popup windows hanging around) โฆ
- the most we can ask at the receiver is that window.opener is defined โฆ and if so, just at that discovery โฆ
- an image called โamhere.jpgโ is created via PHP GD functionality โฆ and back at the โpublic domainโ parent within the iframe onload logic (where with contentWindow or contentDocument do not expect a document.body or even a document) โฆ
- we attempt to โhotlinkโ that MAMP local web server image โฆ as per โฆ
var tryit='//localhost:8888/PHP/animegif/amhere.jpg';
document.getElementById('ctvopt').value='advice';
document.getElementById('ctvopt').innerHTML='Advice on Convert to Video';
if (tryit != '') {
var im=new Image();
im.onload = function() {
document.getElementById('ctvopt').value='video';
console.log('this.height=' + eval('' + this.height));
if (eval('' + this.height) >= 20) {
document.getElementById('ctvopt').innerHTML='Convert to Video';
} else {
document.getElementById('ctvopt').innerHTML='Convert to Video (but ffmpeg not installed or in unexpected place)';
}
document.getElementById('imsel').title='All except Convert to Video, which needs ffmpeg installed, use ImageMagick';
};
im.src=tryit;
tryit='';
}
Previous relevant Animated GIF Creator Video Revisit Tutorial is shown below.
We hope you realize that ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator (helped out by achanged emailhtml
php inhouse email creator helper serverside PHP web application) can be accessed โฆ
- in that public RJM Programming mode of use above โฆ but even better can be โฆ
- download relevant code to macOS MAMP local web server places off /Applications/MAMP/htdocs/ $_SERVER[โDOCUMENT_ROOTโ] places โฆ
- GIFEncoder.class.php โฆ thanks โฆ to โPHP/animegif/โ
- tutorial_to_animated_gif
php to โPHP/animegif/โ
- animegif
php to โPHP/animegif/โ
- haiku_animated_gif
html to โPHP/animegif/โ
- macos_ffmpeg_convert
php to $_SERVER[โDOCUMENT_ROOTโ]
- macos_textutil_convert
php to $_SERVER[โDOCUMENT_ROOTโ]
- macos_say_record
php to $_SERVER[โDOCUMENT_ROOTโ]
- client_browsing
htm to โHTMLCSS/โ
- emailhtml
php to โHTMLCSS/โ
- read_exif_off_image_rotate
php to โPHP/โ
โฆ and check the code for the validity of any ImageMagick paths โฆ and if not all these conditions, simulate the same and cobble it together in the code
โฆ one reason being that we do not want to install the wonderful ffmpeg (command line video creation tool) on the RJM Programming domain, but, in macOS, here with MAMP, we are quite happy to live with the Homebrew (Terminal applicationโs) install โฆ
brew install ffmpeg
โฆ to open a whole new woooooorrrrlllllddd of video creation opportunities using this MAMP local web URL โฆ
HTTP://localhost:8888/PHP/animegif/tutorial_to_animated_gif.php# Animated GIF Creator on MAMP local web server
And so, onto yesterdayโs Animated GIF Creator PDF Last Reveal Tutorial we decided to revisit video creation parts of our inhouse Animated GIF Creator on this MacBook Air. We needed to reinstall ffmpeg, and we show that in todayโs animated GIF tutorial picture and also created the โvideo.movโ video below, in the process โฆ
โฆ we tweaked out of โvideo/mp4โ ffmpeg created videos thinking towards โvideo/webmโ or โvideo.movโ ffmpeg created videos that suit the โfew frames but spaced out videoโ we wanted to achieve for all practical purposes, that โvideo/mp4โ playing too fast for us to see anything much but the first and last slide โฆ
<?php
$videofr=" -r " . (1000 / $delay) . " ";
$videofr=" -r " . (1000 / $delay) . " -filter:v setpts=" . ($delay / 1000) . "*PTS ";
$videomime="video/mp4";
$videoext=".mp4";
$videofr=" -framerate 0.1 ";
$videoext=".webm";
$videomime="video/webm";
$videomidbit="-c:v libvpx-vp9 -pix_fmt yuva420p -lossless 1 -c:a copy";
//$videocmd=$videopath . "ffmpeg -r " . (1000 / $delay) . " -filter:v setpts=" . ($delay / 1000) . "*PTS " . " -i " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "%03d.jpg " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.mp4 2> " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.bad";
//$svideocmd="ffmpeg -r " . (1000 / $delay) . " -filter:v setpts=" . ($delay / 1000) . "*PTS " . " -i " . "%03d.jpg " . "video.mp4";
$videocmd=$videopath . "ffmpeg " . $videofr . " -i " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "%03d.jpg " . $videomidbit . " " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video" . $videoext . " 2> " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.bad";
$svideocmd="ffmpeg " . $videofr . " -i " . "%03d.jpg " . $videomidbit . " " . "video" . $videoext;
$videocmd.="; " . $videopath . "ffmpeg -i " . " " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video" . $videoext . " " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.mov 2>> " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.bad";
$svideocmd.="; " . "ffmpeg -i " . " " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video" . $videoext . " " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.mov 2>> " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "video.bad";
$videohtml="<video title='" . $svideocmd . "' controls id=ivideo type='" . $videomime . "'><source src='video.mov'></source><source src='video" . $videoext . "'></source></video>";
$videosuffix="";
?>
Previous relevant Animated GIF Creator PDF Last Reveal Tutorial is shown below.
As a web application programmer we like buttons. There are โbuttonsโ and there are buttons. Yes, there is an HTML button element, and it and the input type=button element render as that part of a webpage most recognizable to users the world over. You click or tap this button and something usually happens.
But we also enjoy โEmoji Buttonsโ for we graphically challenged programmers. Using an emoji text and graphic can make span elements or p elements or lots of other HTML elements that have an innerHTML property, be like a very succinct button like entity, also appreciated around here because it takes up so little webpage โreal estateโ.
And so onto yesterdayโs Animated GIF Creator PDF Order Tutorial we set about, today, โrevealingโ any enduring animated GIF and/or PDF created during a previous session, using Emoji Buttons as the email/SMS sharing action buttons.
We say โrevealingโ because, like the way โEmoji Buttonsโ save webpage โreal estateโ, so can the use of the HTML5 details/summary element combination. It is in that summary โenduringโ header part of that combination we can place some โEmoji Buttonsโ. You will (once you start creating and sharing animated GIFs and/or PDFs) see from ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator (helped out by achanged emailhtml
php inhouse email creator helper serverside PHP web application) that we place three Emoji Buttons โฆ
SMS (Animated GIF or PDF) Limited relevance period (ie. no data URIs involved, so rely on an absolute URL whose content might change or start not to exist down the track) โฆ via โaโ โsms:โ link click/tap
Email (Animated GIF or PDF) Limited relevance period (ie. no data URIs involved, so rely on an absolute URL whose content might change or start not to exist down the track) โฆ via โaโ โmailto:โ link click/tap
Email (Animated GIF or PDF) Enduring relevance (ie. data URIs involved, so do not rely on any absolute URL whose content might change or start not to exist down the track) โฆ via PHP mail function means of sending email with HTML attachment containing the relevant Animated GIF or PDF
Yes, โEmoji Buttonsโ can have their size controlled but not by the usual CSS width and height properties, but by the CSS font-size property. Here is the new Javascript function that those Emoji Button โonclickโ logic points to โฆ
<?php eho โ
function askes(isemail, isoab) {
var esask='', izhr=null, izform=null;
var isoa=document.getElementById(isoab.id.replace('b',''));
if (isemail) {
esask=prompt('Please enter email address to send this to', '');
if (esask != null) {
if (esask.indexOf('@') != -1) {
if (isoa.outerHTML.indexOf('<img') == 0) {
//alert('More Animated GIF to come');
izhr = new XMLHttpRequest();
izform=new FormData();
izform.append('to', esask.trim());
izform.append('inline', '" . dirname(__FILE__) . DIRECTORY_SEPARATOR . server_remote_addr() . ".gif" . "');
izform.append('subj', 'My Latest Animated GIF via RJM Programming ... ');
izform.append('tdhuhta', ('<body><div title=\"" . explode('/animegif',$durlis)[0] . '/animegif/' . server_remote_addr() . "\" style=\"overflow:auto;-webkit-overflow-scrolling:touch;height:100%;\"><img style=\"width:100%;height:900px;\" src=\"" . dirname(__FILE__) . DIRECTORY_SEPARATOR . server_remote_addr() . ".gif" . "\"></img></div></body>'));
izhr.open('post', '//www.rjmprogramming.com.au/HTMLCSS/emailhtml.php', true);
izhr.send(izform);
} else if (isoa.outerHTML.indexOf('<a') != 0) {
//alert('More PDF to come');
izhr = new XMLHttpRequest();
izform=new FormData();
izform.append('to', esask.trim());
izform.append('inline', '" . dirname(__FILE__) . DIRECTORY_SEPARATOR . server_remote_addr() . "_animegif.pdf" . "');
izform.append('subj', 'My Latest PDF via Animated GIF via RJM Programming ... ');
izform.append('tdhuhta', ('<body><div title=\"" . explode('/animegif',$durlis)[0] . '/animegif/' . server_remote_addr() . "_\" style=\"overflow:auto;-webkit-overflow-scrolling:touch;height:100%;\"><object style=\"width:100%;height:900px;\" type=\"application/pdf\" data=\"" . dirname(__FILE__) . DIRECTORY_SEPARATOR . server_remote_addr() . "_animegif.pdf" . "\"></object></div></body>'));
izhr.open('post', '//www.rjmprogramming.com.au/HTMLCSS/emailhtml.php', true);
izhr.send(izform);
} else {
isoa.href='mailto:' + esask.trim() + '?' + isoa.href.split('?')[1];
isoa.click();
}
}
}
} else {
esask=prompt('Please enter SMS number to send this to', '');
if (esask != null) {
if ((esask.trim() != '' && esask.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '')) {
isoa.href='sms:' + esask.trim() + '&' + isoa.href.split('&')[1];
isoa.click();
}
}
}
}
โ; ?>
Cute, huh?!
Previous relevant Animated GIF Creator PDF Order Tutorial is shown below.
Order becomes an interesting subject to us today regarding the PDF conversions possible in amongst the Animated GIF creating of yesterdayโs Animated GIF Creator PDF Share Tutorial.
That is because we may have some advanced users out there that want that possibility of differentiating the data of โฆ
- animated GIF โฆ containing all features asked for, in totality โฆ from the chance for the user to have any of the PDF conversion option sets below โฆ
- PDF โฆ one of โฆ
- no PDF conversion
- full PDF conversion โฆ with the user choices regarding raw image content and title and watermarking and ImageMagick and GD modifiers
- light PDF conversion โฆ with the user choices regarding just raw image content (the only option out of these last three available before todayโs work)
- medium PDF conversion โฆ with the user choices regarding just ImageMagick and GD modifiers
โฆ perhaps as a โbefore and afterโ tool regarding presentations, maybe?
No dropdowns used here (enforcing an order), just the userโs order in which they choose to select the โPDF conversionโ option from the ImageMagick dropdown (in relation to other selections) determining how and when this PDF conversion occurs in the workflow through to creating the animated GIF with ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator serverside PHP web application. Just remember to select PDF Conversion as early as possible to do that โlight PDF conversionโ option above and last thing if you are interested in โfull PDF conversionโ (where you can create PDF documents with the bells and whistles ImageMagick and GD modifiers can offer) and todayโs tutorial picture is an example of โmedium PDF conversionโ (when we ordered our settings by first Grayscale, second PDF conversion and last title and watermarking options). Clicking or tapping the ImageMagick link can get the user to the Javascript popup window where they might define the email or SMS recipient for that PDF conversion data file download.
Previous relevant Animated GIF Creator PDF Share Tutorial is shown below.
To share yesterdayโs Animated GIF Creator PDF Conversion Tutorial PDF data formatted image slides (and then onto an animated GIF) would be a step forward, wouldnโt you say?
What sharing conduits do we code for? We always intended โฆ
- email โฆ but as the day wore on trying to get the usage to work on mobile and non-mobile we decided to relinquish our wish to not have to create a user specific enduring (until that same browser type and user combination share) PDF document for the user request โฆ mainly to get mobile email downloads to be friendly โฆ and so this opened the door for โฆ
- SMS โฆ to access that enduring PDF as a URL in the SMS message (that becomes a link for the recipient)
โฆ the email methodology used being that โmidair feelingโ Ajax/FormData approach in ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator serverside PHP web application โฆ
<?php echo โ
function emailhtmlit() {
var induri=ginduri;
var pemail='" . urldecode($_GET['outpdf']) . urldecode($_POST['outpdf']) . "';
if (pemail != null) {
if (pemail.indexOf('@') != -1 || (pemail.trim() != '' && pemail.trim().replace(/0/g,'').replace(/1/g,'').replace(/2/g,'').replace(/3/g,'').replace(/4/g,'').replace(/5/g,'').replace(/6/g,'').replace(/7/g,'').replace(/8/g,'').replace(/9/g,'') == '')) {
if (induri.trim() == '') {
if (induri == '') {
document.getElementById('pdfproposed').src='./animegif.pdf?rand=' + Math.floor(Math.random() * 19854654);
} else {
ginduri='found';
}
setTimeout(emailhtmlit, 15000);
} else {
ginduri='';
var zhr = new XMLHttpRequest();
var zform=new FormData();
if (pemail.indexOf('@') != -1) { zform.append('to', pemail); }
zform.append('inline', '" . dirname(__FILE__) . DIRECTORY_SEPARATOR . "animegif.pdf" . "');
zform.append('subj', 'My PDF version of Animated GIF via RJM Programming ... ');
zform.append('tdhuhta', ('<body><div title=\"" . explode('/animegif',$durlis)[0] . '/animegif/' . server_remote_addr() . "_\" style=\"overflow:auto;-webkit-overflow-scrolling:touch;height:100%;\"><object style=\"width:100%;height:900px;\" type=\"application/pdf\" data=\"" . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'animegif.pdf' . "\"><embed style=\"width:100%;height:900px;\" type=\"application/pdf\" src=\"" . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'animegif.pdf' . "\"></embed></object></div></body>'));
//zform.append('tdhuhta', ('<body><iframe srcdoc=\"" . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'animegif.pdf' . "\"></iframe></body>'));
zhr.open('post', '//www.rjmprogramming.com.au/HTMLCSS/emailhtml.php', true);
zhr.send(zform);
if (pemail.indexOf('@') == -1) {
var hrefp=document.getElementById('pdfsms').href.split('&body=')[0];
hrefp+=pemail.trim() + '&body=' + document.getElementById('pdfsms').href.split('&body=')[1];
document.getElementById('pdfsms').href=hrefp;
document.getElementById('pdfsms').click();
}
}
}
}
}
โ; ?>
โฆ and this called on our PHP email creator helper to better interface in its $_POST arguments reading section in ourchanged emailhtmlphp inhouse email creator helper serverside PHP web application โฆ
<?php
$psacv="";
$okayin=true;
$subd="";
$subptitle='';
$subdata="";
$subfile="";
$getpostfound=false;
<br>
foreach( $_POST as $name=>$val ) {
if ($val != "") {
// blah blah blah //file_put_contents("jnv." . $name, "jnv.inv00 " . strlen($phpcont));
if ($name == "tdhuhta" && $subfile != "" && $subdata != "" && strpos(str_replace("+"," ",urldecode($val)), $subfile) !== false) {
if (strpos(str_replace("+"," ",urldecode($val)), ' srcdoc="') !== false || strpos(str_replace("+"," ",urldecode($val)), ' data="') !== false) {
if (strpos(str_replace("+"," ",urldecode($val)), ' title="') !== false) { //file_put_contents('haaa.aaa',explode('/animegif/', explode('"', explode(' title="', str_replace("+"," ",urldecode($val)))[1])[0])[1]);
if (!file_exists('../PHP/animegif/' . explode('/animegif/', explode('"', explode(' title="', str_replace("+"," ",urldecode($val)))[1])[0])[1] . 'animegif.pdf')) {
if (file_exists('../PHP/animegif/animegif.pdf')) {
copy('../PHP/animegif/animegif.pdf', '../PHP/animegif/' . explode('/animegif/', explode('"', explode(' title="', str_replace("+"," ",urldecode($val)))[1])[0])[1] . 'animegif.pdf');
}
}
$psacv=explode('"', explode(' title="', str_replace("+"," ",urldecode($val)))[1])[0] . 'animegif.pdf';
$subptitle='<a target=_blank href="' . explode('"', explode(' title="', str_replace("+"," ",urldecode($val)))[1])[0] . 'animegif.pdf">Mobile whole PDF</a><br>';
}
$vrest=explode('"', explode(' srcdoc="',str_replace("+"," ",urldecode($val)))[1])[0];
$val=urlencode("<body>" . $subptitle . "<iframe style='width:100%;height:95vh;overflow:auto;-webkit-overflow-scrolling:touch;' srcdoc='<div style=width:92%;height:95vh;overflow:auto;-webkit-overflow-scrolling:touch;><object id=myobj style=width:95%;height:95vh; type=application/pdf data=\"" . $subdata . "\"></object></div>'></iframe></body>");
}
// blah blah blah
if ($name == "inline") {
if (strpos(str_replace("+"," ",urldecode($val)), 'animegif.pdf') !== false && isset($_POST['tdhuhta'])) {
if (file_exists(str_replace("+"," ",urldecode($val)))) {
$subfile=str_replace("+"," ",urldecode($val));
$subdata='data:application/pdf;base64,' . base64_encode(file_get_contents(str_replace("+"," ",urldecode($val))));
$val="";
$name="x";
$okayin=false;
}
}
// blah blah blah
}
}
?>
Creating the PDFs got helped out in โreliability termsโ via the introduced animegifphp inhouse Wait Around Longer serverside PHP web application.
Previous relevant Animated GIF Creator PDF Conversion Tutorial is shown below.
Up to yesterdayโs Animated GIF Creator Slide Specific Application Tutorial the recent progress had us โฆ
- knowing the good places to intervene between the original slide image data being read in and the animated GIF slide output โฆ and โฆ
- involvement of ImageMagick โฆ so, today, these two help us down the path to โฆ
- adding PDF as an output format possibility, in addition to the animated GIF and other ideas floated as output formats
โฆ with ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator serverside PHP web application.
We have more โreliability workโ and โemail sharing workโ to go after todayโs start, but it primarily called on ImageMagick command lineโs talent for a command like โฆ
convert /tmp/imtmp0*.*[gGmMiI]* /tmp/imtmp000.pdf
โฆ to โconcatenateโ into the one output PDF file (called โ/tmp/imtmp000.pdfโ) the slides, arranged by our code into that โ/tmp/imtmp0*.*[gGmMiI]*โ (file specification) arrangement above. Yes, we meant โconvertโ above, as โmogrifyโ (batch work) appears not to be able to perform this task.
We hope you stay the course!
Previous relevant Animated GIF Creator Slide Specific Application Tutorial is shown below.
Itโs all fine and good improving on the ImageMagick and GD and Exif functionality modifications like with yesterdayโs Animated GIF Creator Exif Rotation Compensation Tutorial, but in reality, if you are going to start creating animated GIFs to explain a process, you are going to want to apply these โslide modifiersโ on a slide by slide basis, rather than enforcing a โwhole of animated GIF slide setโ paradigm, as for the last few days worth of work.
And so, we decided to do what we often do, โsliding inโ more functionality (chortle, chortle). We tend to want to โฆ
- start with hardcoded text (or element) โฆ somewhere โฆ today it happens to be in an HTML span element that once involved just โฆ
<span id="smyim"></span>
โฆ and used to get filled, Javascript DOM wise, when needed via โฆ
document.getElementById('smyim').innerHTML='ImageMagick switches: '; // and yes, it remains that way even now, but read on ... - add intelligence (quite often that being onclick logic(s)) to that hardcoded element via โฆ
<span id=smyim title=Application onclick=applyto(); style=cursor:pointer;text-decoration:underline;></span> - that serves the purpose, as the user clicks/taps it (alerted to that fact, perhaps, because we underline the element and add an appropriate cursor when hovering over it (plus a title)), of calling Javascript โฆ
function applyto() {
var huhto=prompt('Apply ImageMagick and/or GD to which slides, in comma separated list, counting starting with 1? Defaults to applying to all slides. Comma delimit. Negatives mean all but. Ranges can be specified. For example ... 2,4-7,9', document.getElementById('appliedto').value);
if (huhto == null) { huhto=''; }
if (huhto.trim() == '') {
document.getElementById('appliedto').value='';
document.getElementById('smyim').title='Application';
} else {
document.getElementById('appliedto').value=huhto.trim();
document.getElementById('smyim').title=huhto.trim();
}
} - to glean an (often times out of the normal workflow of the web application) informational piece of data, interactively, from the user, via a Javascript prompt popup
So thatโs the clientside of this work โฆ โalerting the user to the existance of the functionalityโ you might say.
And then thereโs โthe applicationโ of that nuanced user requirement. And thatโs where the โinhouse โourโ prefix to wrapper function name paradigmsโ come in handy. We introduced โblanketโ functionality thoughts via this approach, and so to โpartially undoโ that thinking, we make the โourโ prefix conditional, as is available to us with ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator serverside PHP web application (helped out by achanged exif_rotation_check
php inhouse Exif detector PHP helper), as per โฆ
<?php
function ourcomplicated($inio, $iappl) {
$ideasl=explode(",", str_replace(' ','',$iappl));
$xour="our";
for ($iqa=0; $iqa<sizeof($ideasl); $iqa++) {
if (trim($ideasl[$iqa]) != '') {
$xour="";
if (('-' . $inio) == trim($ideasl[$iqa])) { return ""; }
$ideasr=explode("-", str_replace(' ','',trim($ideasl[$iqa])));
for ($iqb=0; $iqb<sizeof($ideasr); $iqb++) {
if (('' . $inio) == trim($ideasr[$iqb])) {
return "our";
}
if ($iqb == 1) {
if (trim($ideasr[1]) == "") { $ideasr[1]="99999999"; }
if ($inio >= $ideasr[0] && $inio <= $ideasr[1]) { return "our"; }
}
}
}
}
return $xour;
}
?>
โฆ teamed with โฆ
<?php
$ours="our";
for ($io=1; $io
// blah blah blah
if (strpos($aphoto[0], ";base64,") !== false) {
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefromstring(base64_decode('" . explode(";base64,",$aphoto[0])[1] . "'));", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachonestring));
} else if (strpos(strtolower($aphoto[0]), "//") !== false) {
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefromstring(@file_get_contents('" . $prefix . $aphoto[0] . "'));", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
} else if (strpos(strtolower($aphoto[0]), ".jp") !== false) {
if (strpos($prefix, "../../") !== false && !file_exists($prefix . $aphoto[0]) && file_exists(str_replace("../../","../",$prefix) . $aphoto[0])) {
$prefix=str_replace("../../","../",$prefix);
}
//file_put_contents('qpqp.qpqp', $eachone . "\n\n" . $atext . "\n\n" . str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefromjpeg('" . $prefix . $aphoto[0] . "');", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
//file_put_contents('qpqpqp.qpqpqp', $gifphp);
} else if (strpos(strtolower($aphoto[0]), ".png") !== false) {
if (strpos($prefix, "../../") !== false && !file_exists($prefix . $aphoto[0]) && file_exists(str_replace("../../","../",$prefix) . $aphoto[0])) {
$prefix=str_replace("../../","../",$prefix);
}
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefrompng('" . $prefix . $aphoto[0] . "');", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
} else if (strpos(strtolower($aphoto[0]), ".gif") !== false) {
if (strpos($prefix, "../../") !== false && !file_exists($prefix . $aphoto[0]) && file_exists(str_replace("../../","../",$prefix) . $aphoto[0])) {
$prefix=str_replace("../../","../",$prefix);
}
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefromgif('" . $prefix . $aphoto[0] . "');", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
} else if (strpos(strtolower($aphoto[0]), ".bmp") !== false) {
if (strpos($prefix, "../../") !== false && !file_exists($prefix . $aphoto[0]) && file_exists(str_replace("../../","../",$prefix) . $aphoto[0])) {
$prefix=str_replace("../../","../",$prefix);
}
$gifphp.=str_replace("imagecreatefromjpeg('source01.jpg');", "" . $ours . "imagecreatefrombmp('" . $prefix . $aphoto[0] . "');", str_replace("\$text='';", "\$text=\"" . str_replace("+"," ",urldecode($atext)) . "\";", $eachone));
}
// blah blah blah
}
?>
We use these โnew abilitiesโ better explaining โthe abscence or otherwise of Exif checkingโ, and the implications of that in the animated GIF creator woooooorrrrrrlllllddd, contrasting the first two slides, showing one with โNo Exif checkingโ (the bad old days) versus โWith Exif checkingโ (the renaissance of liberated thinking in the South South East woooorrrrrlllldddd) in todayโs animated GIF presentation.
Get the picture?!
Previous relevant Animated GIF Creator Exif Rotation Compensation Tutorial is shown below.
The recent couple of days of work like yesterdayโs Animated GIF Creator GD Transformations Interfacing Tutorial have given us โrotation functionalityโ tools to counteract the unusual effects Exif โฆ
Exchangeable image file format (officially Exif, according to JEIDA/JEITA/CIPA specifications) is a standard that specifies the formats for images, sound, and ancillary tags used by digital cameras (including smartphones), scanners and other systems handling image and sound files recorded by digital cameras.
โฆ can have converting mobile device camera created images into animated GIFs via ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator PHP web application.
But with some photos itโs there in the photoโs metadata information letting the future user know what orientation the camera of that mobile device was in as you took the photo. In order to help our animated GIF creator, the first slide image is scoured for Exif metadata and if found, a suitable rotation correction can be applied to the slides there and then. In order to scour for Exif metadata we needed to write a exif_rotation_checkphp inhouse Exif detector PHP helper.
Previous relevant Animated GIF Creator GD Transformations Interfacing Tutorial is shown below.
The PHP GD image library is so much more useful than for the โfiltersโ interfaced to with yesterdayโs Animated GIF Creator GD Filter Interfacing Tutorial. Under an โumbrella termโ transformations, today we add interfacing to GD functionality โฆ
โฆ into ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator PHP web application. We found it more user friendly to tailor the asking of numerical parameters for these GD calls work via โฆ
<?php
$gfcds='';
$gdfs=[];
if (strpos(($imvgn . $imafn . $imqty . $imgds), '|') !== false) {
$gdfs=explode(';', trim(explode('|', $imvgn . $imafn . $imqty . $imgds)[1]));
for ($itf=0; $itf<sizeof($gdfs); $itf++) {
if (trim($gdfs[$itf]) != '') {
if (trim($gdfs[$itf]) == strtolower(trim($gdfs[$itf]))) {
$gfcds.=chr(10) . " imagefilter(" . "$" . "oimo, IMG_FILTER_" . strtoupper(trim($gdfs[$itf])) . "); " . chr(10);
} else if (trim($gdfs[$itf]) == strtoupper(trim($gdfs[$itf]))) {
$gfcds.=chr(10) . " image" . explode(',',explode(" ",strtolower(trim($gdfs[$itf])))[0])[0] . "(" . "$" . "oimo, IMG_" . str_replace(" ","_",strtoupper(trim( str_replace(explode(' ',$gdfs[$itf])[0] . ' ','',$gdfs[$itf]) ))) . "); " . chr(10);
} else if (strpos(strtoupper(trim($gdfs[$itf])), "SCALE") !== false) {
$gfcds.=chr(10) . " $" . "oimo=image" . explode(',',explode(" ",strtolower(trim($gdfs[$itf])))[0])[0] . "(" . "$" . "oimo" . str_replace(" ","_",(trim( str_replace(explode(',',explode(" ",(trim($gdfs[$itf])))[0])[0],'',$gdfs[$itf]) ))) . "); " . chr(10);
} else if (strpos(strtoupper(trim($gdfs[$itf])), "COPY") === false) {
$gfcds.=chr(10) . " image" . explode(',',explode(" ",strtolower(trim($gdfs[$itf])))[0])[0] . "(" . "$" . "oimo" . str_replace(" ","_",(trim( str_replace(explode(',',explode(" ",(trim($gdfs[$itf])))[0])[0],'',$gdfs[$itf]) ))) . "); " . chr(10);
} else {
$gfcds.=chr(10) . " image" . explode(',',explode(" ",strtolower(trim($gdfs[$itf])))[0])[0] . "(" . "$" . "oimo" . "," . "$" . "oimo" . explode("," . "$" . "oimo", $gdfs[$itf])[1] . "); " . chr(10);
}
}
}
}
?>
โฆ to work with modified PHP writes PHP of the ilk โฆ
<?php echo โ
function ourimagecreatefromstring(\$inidis) {
global \$imvgn, \$imafn, \$imqty, \$imgds, \$gfcds;
if ((\$imvgn . \$imafn . \$imqty . \$imgds) != '' && strpos(\$inidis, ';base64,') !== false) {
\$extis=str_replace('jpeg','jpg',explode('/', explode(';base64,', \$inidis)[0])[1]);
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, base64_encode(explode(';base64,', \$inidis)[1]));
\$fzis=filesize(\$sofarout);
if (trim(explode('|', \$imvgn . \$imafn . \$imqty . \$imgds)[0]) != '') {
exec('" . $immogpath . "mogrify ' . explode('|', \$imvgn . \$imafn . \$imqty . \$imgds)[0] . ' /tmp/imtmp.' . \$extis);
}
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false ||
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
\$oimo=null;
if (strtolower(\$extis) == 'png') {
\$oimo=imagecreatefrompng('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strtolower(\$extis) == 'bmp') {
\$oimo=imagecreatefrombmp('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strtolower(\$extis) == 'gif') {
\$oimo=imagecreatefromgif('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
\$oimo=imagecreatefromjpeg('/tmp/imtmp.' . \$extis); " . $gfcds . "
}
if (\$oimo) { return \$oimo; }
} else if ((\$imvgn . \$imafn . \$imqty . \$imgds) != '') {
\$extis=str_replace('jpeg','jpg','" . $inextis . "');
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
if (strpos(strtolower((\$imvgn . \$imafn . \$imqty . \$imgds)), '-format ') === false) { \$imvgn.=' -format " . str_replace('jpg','jpeg',$inextis) . " '; }
if (trim(explode('|', \$imvgn . \$imafn . \$imqty . \$imgds)[0]) != '') {
exec('" . $immogpath . "mogrify ' . explode('|', \$imvgn . \$imafn . \$imqty . \$imgds)[0] . ' /tmp/imtmp.' . \$extis);
}
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
\$oimo=null;
if (strtolower(\$extis) == 'png') {
\$oimo=imagecreatefrompng('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strtolower(\$extis) == 'bmp') {
\$oimo=imagecreatefrombmp('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strtolower(\$extis) == 'gif') {
\$oimo=imagecreatefromgif('/tmp/imtmp.' . \$extis); " . $gfcds . "
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
\$oimo=imagecreatefromjpeg('/tmp/imtmp.' . \$extis); " . $gfcds . "
}
if (\$oimo) { return \$oimo; }
}
return imagecreatefromstring(\$inidis);
}
โ; โ?>
โฆ and to get there clientwise, in the Javascript โฆ
function gdadd(oselo) {
var pari=1, thispari='0';
if (oselo.value != '') {
//alert(oselo.value);
var oselovalue=oselo.value.replace(',' + '$' + 'oimo','~' + '$' + 'oimo').split(',')[0];
//alert(oselovalue);
var oseloval=oselo.value;
if (document.getElementById('imgds')) { if (document.getElementById('imgds').value == '') { document.getElementById('imgds').value='|'; } else { document.getElementById('imgds').value+=';'; } }
oseloval=oseloval.replace(',' + '$' + 'oimo','~' + '$' + 'oimo');
oseloval=oseloval.replace(oseloval.split(',')[0], '');
while (oseloval.indexOf(',') != -1) {
//alert(oseloval);
if ((oseloval + ' ').substring(1).split(',')[0].trim() != '') {
if ((' ' + (oseloval + ' ').substring(1).split(',')[0].trim() + ' ').toLowerCase().indexOf(' colour ') != -1) {
thispari=prompt('Enter' + (' ' + (oseloval + ' ').substring(1).split(',')[0].trim() + ' ').toLowerCase().replace(' colour ', ' red,green,blue colour ') + 'parameter for GD ' + oselo.value.split(',')[0] + ' ' + pari + ' of ' + eval(-1 + oselo.value.replace(',' + '$' + 'oimo','').split(',').length) + '?', '0');
if (thispari == null) {
thispari='0';
} else if (thispari.trim() == '') {
thispari='0';
} else if (thispari.indexOf(',') == -1) {
oselovalue+=',' + thispari + '';
} else {
oselovalue+=',imagecolorallocate(' + '$' + 'oimo,' + thispari + ')';
}
} else {
thispari=prompt('Enter ' + (oseloval + ' ').substring(1).split(',')[0].trim() + ' parameter for GD ' + oselo.value.split(',')[0] + ' ' + pari + ' of ' + eval(-1 + oselo.value.replace(',' + '$' + 'oimo','').split(',').length) + '?', '0');
if (thispari == null) {
thispari='0';
} else {
oselovalue+=',' + thispari;
}
}
oseloval=oseloval.replace(',' + (oseloval + ' ').substring(1).split(',')[0].trim(),'').trim();
} else {
thispari=prompt('Enter numerical parameter for GD ' + oselo.value.split(',')[0] + ' ' + pari + ' of ' + eval(-1 + oselo.value.replace(',' + '$' + 'oimo','').split(',').length) + '?', '0');
oseloval=oseloval.replace(',','');
if (thispari == null) {
thispari='0';
} else {
oselovalue+=',' + thispari;
}
}
//oseloval=oseloval.replace(oseloval.split(',')[0] + ',', '');
//oseloval=oseloval.replace(',','');
pari++;
}
if (document.getElementById('gdopt')) {
document.getElementById('gdopt').innerHTML+=' ' + oselovalue.replace('~',',');
}
if (document.getElementById('imgds')) {
document.getElementById('imgds').value+=oselovalue.replace('~',',');
//document.getElementById('imgds').style.display='inline-block';
//document.getElementById('imgds').style.width='300px';
if (document.getElementById('smyim').innerHTML == '') { document.getElementById('smyim').innerHTML='ImageMagick switches: '; }
} else if (document.getElementById('myim')) {
document.getElementById('myim').innerHTML='<span is=smyim>ImageMagick switches: </span><input id=imqty name=imqty type=text style=display:inline-block; value=\"\"></input><input id=imgds name=imgds type=hidden style=display:inline-block; value=\"|' + oselovalue.replace('~',',') + '\"></input>';
document.getElementById('imqty').style.width='300px';
}
oselo.value='';
}
}
Previous relevant Animated GIF Creator GD Filter Interfacing Tutorial is shown below.
We are into image modification on the way to creating โcompiledโ animated GIF images, at the moment. Yesterdayโs Animated GIF Creator ImageMagick Interfacing Tutorial got us interfacing (or integrating) โฆ
- ImageMagick batch processing โmogrifyโ ideas โฆ and, today, it is the turn of โฆ
- GD image filters โฆ
โฆ into ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator PHP web application.
Previous relevant Animated GIF Creator ImageMagick Interfacing Tutorial is shown below.
Yes, you guessed it! On top of yesterdayโs ImageMagick Vignette Primer Tutorial, today we want to interface the ImageMagick batch processing โmogrifyโ ideas into ourchanged tutorial_to_animated_gifphp inhouse Animated GIF Creator PHP web application.
โInterfacingโ (or integrating) into code often has you asking the question โฆ
Where do we intervene to place our logic?
Weโve decided to โwrapโ our PHP GD calls โฆ
โฆ into inhouse โourโ prefixed function versions as per (PHP writing out PHP) โฆ
<?php echo โ
\$imvgn='" . $imvgn . "'; /" . "/ vignette factor
\$imafn='" . $imafn . "'; /" . "/ affine transformation
\$imqty='" . $imqty . "'; /" . "/ image conversion and/or quality RE jpeg
function ourimagecreatefromstring(\$inidis) {
global \$imvgn, \$imafn, \$imqty;
if ((\$imvgn . \$imafn . \$imqty) != '' && strpos(\$inidis, ';base64,') !== false) {
\$extis=str_replace('jpeg','jpg',explode('/', explode(';base64,', \$inidis)[0])[1]);
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, base64_encode(explode(';base64,', \$inidis)[1]));
\$fzis=filesize(\$sofarout);
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false ||
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
} else if ((\$imvgn . \$imafn . \$imqty) != '') {
\$extis=str_replace('jpeg','jpg','" . $inextis . "');
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
if (strpos(strtolower((\$imvgn . \$imafn . \$imqty)), '-format ') === false) { \$imvgn.=' -format " . str_replace('jpg','jpeg',$inextis) . " '; }
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
}
return imagecreatefromstring(\$inidis);
}
function ourimagecreatefromjpeg(\$inidis) {
global \$imvgn, \$imafn, \$imqty;
if ((\$imvgn . \$imafn . \$imqty) != '') {
\$extis='jpg';
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
}
return imagecreatefromjpeg(\$inidis);
}
function ourimagecreatefrompng(\$inidis) {
global \$imvgn, \$imafn, \$imqty;
if ((\$imvgn . \$imafn . \$imqty) != '') {
\$extis='png';
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
}
return imagecreatefrompng(\$inidis);
}
function ourimagecreatefromgif(\$inidis) {
global \$imvgn, \$imafn, \$imqty;
if ((\$imvgn . \$imafn . \$imqty) != '') {
\$extis='gif';
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
}
return imagecreatefromgif(\$inidis);
}
function ourimagecreatefrombmp(\$inidis) {
global \$imvgn, \$imafn, \$imqty;
if ((\$imvgn . \$imafn . \$imqty) != '') {
\$extis='bmp';
\$inextis=\$extis;
\$sofarout='/tmp/imtmp.' . \$extis;
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
unlink(\$imfilename);
}
file_put_contents(\$sofarout, \$inidis);
\$fzis=filesize(\$sofarout);
exec('" . $immogpath . "mogrify ' . \$imvgn . \$imafn . \$imqty . ' /tmp/imtmp.' . \$extis);
foreach (glob('/tmp/imtmp.*') as \$imfilename) {
if (filesize(\$imfilename) != \$fzis) { // strpos(\$imfilename, '.' . \$extis) === false) {
\$sofarout=\$imfilename;
\$extis=explode('.', \$imfilename)[1];
}
}
if (strtolower(\$extis) == 'png') {
return imagecreatefrompng('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'bmp') {
return imagecreatefrombmp('/tmp/imtmp.' . \$extis);
} else if (strtolower(\$extis) == 'gif') {
return imagecreatefromgif('/tmp/imtmp.' . \$extis);
} else if (strpos(strtolower(\$extis), 'jp') !== false) {
return imagecreatefromjpeg('/tmp/imtmp.' . \$extis);
}
}
return imagecreatefrombmp(\$inidis);
}
โ; ?>
โฆ and change existant calls into (equivalent inhouse) โourโ function calls as above.
Previous relevant ImageMagick Vignette Primer Tutorial is shown below.
Continuing on with the ImageMagick batch processing โmogrifyโ ideas of yesterdayโs ImageMagick Batch Image Conversion Affine Transformation Tutorial and the โvignetteโ image editing ideas of Gimp Vignette Primer Tutorial, as below, today, we took some pet photos with an iPadโs Camera app and shared them off the Photos app via two Mail sharing option emails containing seven attachments each. Using an iPad, the JPEG โjpgโ output files were too big for our inhouse Animated GIF Creator PHP web application to handle, and so to perform the โฆ
- animated GIF presentation, off these downloaded email photo attachments โฆ and along the way โฆ
- quality adjusted them (yes, โmogrifyโ does not stuff JPG to JPG conversions, and we used โmogrifyโ -quality 20% switch here) โฆ and โฆ
- rotate them 180 degrees (โmogrifyโ uses switches -affine -1,0,0,-1,0,0 -transform +repage here) โฆ and โฆ
- vignette 50% (โmogrifyโ uses switch -vignette 50 here)
โฆ on the way to compiling into an animated GIF image, and we turned to ImageMagick again, using its affine transformation talents, along with its awesome vignetting talents โฆ
โฆ where the last two dropdown options will be similar, the last showing the input image into ImageMagick can be an animated GIF that is truely treated like an animated GIF.
By the way, should you be interested in photo orientation off a mobile device camera, have a read of PHP Exif Image Information Revisit Tutorial.
Nala and Luna and Charlie bid you a fond farewell!
Previous relevant Gimp Vignette Primer Tutorial is shown below.
The last time we talked about the miraculous, redolent and amazing image editor called Gimp am sure there was someone in a shower โฆ it stands to reason โฆ and one of those showerers, surely, would have been singing The Gimp Song โฆ and if not โฆ why not? โฆ but we digress โฆ anyway we had the Gimp Transparency Primer Tutorial as shown below go into some image transparency issues with Gimp.
In todayโs tutorial we make use of a great tutorial (even so far as with direct quotes below) called Add a Vignette to a Photograph with GIMP (thanks) to try a photographic technique called vignetting on one of the photographs we added, recently, into the mix of those of the Custom Header Image mix at this blog โฆ specifically the one of Nala, the dog, on the door ledge. Need to warn you here and now that if there was the time all over again, it would be better achieved that second time around, but this is not the point with learning, but rather getting some starting point with a great โproductโ like Gimp, and trying it yourself, once you have a method. It boils down to:
- Open Gimp graphical editor application
- File->Open โฆ pick your image file
- Layer->New Layer (weโll call โVgโ) โฆ pick Foreground Colour
- In the Layers dialog, click on your โVgโ layer to select it, and select Soft light from the โModeโ drop-down box
- Right click on your โVgโ layer and go to Add Layer Mask. In the dialog that pops up, you want โInitialise Layer Mask toโ set to โWhite (full opacity)โ. Click โAddโ
- Below Opacity bar select Link icon next to Eye icon, which will already be showing
- Use the freeform select tool (press F to bring this up) and draw a selection somewhere around the primary point of interest in your photo
- Use your bucket tool (Shift+B) and click within the selection to fill it
- Deselect your selection with Select->None
- Go to Filters->Blur->Gaussian Blur. In the dialog that comes up, you want โRadiusโ set to a very large amount; a tenth of the longest edge of the photo is not too much
- Click on your โVgโ layer to select it (if it isnโt already selected), and then slide the opacity slider towards the right until the effect is subtle enough. Our (ever so subtle) example of Nala, in the tutorial, used an opacity of about 66%
- Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)
Here is an image comparison link.
As with most Gimp ideas, jump in and give it a go, as youโll find your own ways and means of using this great product โฆ am pretty sure.
Link to Gimp โspiritual homeโ โฆ here.
Link to Gimp forum โฆ here.
Previous relevant Gimp Transparency Primer Tutorial is shown below.
Here is a tutorial that adds to a previous Gimp Layers Primer Tutorial as shown below, and gives you more insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.
Todayโs tutorial where we construct a Birthday Card that needs tweaking for the words in front to be seen a bit more clearly, by making the image behind a bit more transparent, changes the transparency of a single image via:
- Open Gimp graphical editor application
- File->Open Layers โฆ pick your image file
- If Layers window not showing, make it show via Windows->Layers โ Brushes
- Below Opacity bar select Link icon next to Eye icon, which will already be showing
- Change Opacity bar setting to a value of Transparency (100% is Opaque, 0% is Transparent) that suits โฆ today we do 70%
- File->Export
- Click Export button in two windows (NB. this overwrites the image file, so if this is not desirable, export to a different image file name and/or type)
As with most Gimp ideas, jump in and give it a go, as youโll find your own ways and means of using this great product โฆ am pretty sure.
Link to Gimp โspiritual homeโ โฆ here.
Link to Gimp forum โฆ here.
Previous relevant Gimp Layers Primer Tutorial is shown below.
Here is a tutorial that gives you an insight into the massive possibilities of using a sophisticated image editor and use layers with various amounts of transparency, especially suited to use with png image files.
Transparency (or its obverse, opacity) can be used to have the one image achieve several โendsโ (ie. purposes). Although it is a bit of a clumsy example in the tutorial, you can see that the technique can be used for artistic purposes โฆ often called โPhotoshoppingโ (named after the more famous, and also brilliant, rival product, Photoshop).
Lots of those classic โPhotoshoppingโ techniques can be achieved in Gimp, and some other tutorials at this blog touch on that.
Am sure you can imagine what the concept of a layer is with regard to image manipulation. Within Gimp, for beginners not used to this concept, you find yourself underestimating and underplaying what can be achieved with the various layers of a multi-layered image. In simplistic terms each layer has the functionality in Gimp to be treated as a whole new image, and this is the best way to think of it when trying to achieve what you want to achieve with Gimp.
Link to Gimp โspiritual homeโ โฆ here.
Link to Gimp forum โฆ here.
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.
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.