http://www.anattatechnologies.com/q
Anatta Technologies
Sat, 09 Aug 2014 17:12:37 +0000
en-US
hourly
1
scripting Photoshop for stop motion
http://www.anattatechnologies.com/q/2012/12/scripting-photoshop-for-stop-motion/
Tue, 25 Dec 2012 23:16:51 +0000
Continue reading ]]>
I would like a simple and quick way to save a copy of an image in Photoshop, with an auto-incrementing filename. Ideally, a single button to capture a frame in a stop motion animation. In other words, I would like to save a copy of the working image as a JPEG without any interactive prompts and the filename will automatically increment a count.
For example, if I’m working with a file “test.psd”, I want a single action that will save a copy “test_0001.jpg”, and subsequent calls will save “test_0002.jpg”, “test_0003.jpg”, and so on.
By default, Photoshop will overwrite existing files, and it would be quite tedious to manually “Save As” for hundreds or thousands of images. Fortunately, Photoshop offers a scripting interface to call user defined scripts. Custom scripts can even be loaded into Photoshop and executed as an Action.
The following snippet can be saved as [Photoshop Directory]/Presets/Scripts/saveFrame.jsx, and after restarting Photoshop you should see “saveFrame” under File -> Scripts.
main();
/***
* Scripted “save as” with incrementing filename
*
e.g., test_0001.jpg, test_0002.jpg, …
*
***/
function main() {
if (!documents.length)
return;
cnt = 1;
try {
var Name = decodeURI(activeDocument.name).replace(/\.[^\.]+$/, ”);
var Path = decodeURI(activeDocument.path);
var saveFrame = Path + “/” + Name + “_” + zeroPad(cnt,4) + “.jpg”;
//
// find the next available filename
while ( File(saveFrame).exists ) {
cnt++;
saveFrame = Path + “/” + Name + “_” + zeroPad(cnt,4) + “.jpg”;
}
//
// save as, change the default JPEG quality here as needed
SaveJPEG(File(saveFrame), 9);
} catch(e) {
alert(e + “\r@ Line ” + e.line);
}
}
function SaveJPEG(saveFile, jpegQuality) {
var doc = activeDocument;
if (doc.bitsPerChannel != BitsPerChannelType.EIGHT)
doc.bitsPerChannel = BitsPerChannelType.EIGHT;
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = jpegQuality;
activeDocument.saveAs(saveFile, jpgSaveOptions, true, Extension.LOWERCASE);
}
function zeroPad(n, s) {
n = n.toString();
while (n.length < s)n = '0' + n;return n;};Using Photoshop scripts you can automate any task and even create animation effects. In CS6 you can render a series of images as a video, alternatively, you can create the image frames in Photoshop and use ffmpeg to render the video.If you want to use ffmpeg to render a series of images, you could use the following command,$ ffmpeg -r 30 -f image2 -i test_%04d.jpg -vb 1M -r 30 test.webmHere is a simple (90 frame loop) example animating a series of scripted lighting effects,The above video is embedded in this page using the following html,
]]>
HTML5 canvas Mandelbrot
http://www.anattatechnologies.com/q/2011/08/html5-canvas-mandelbrot/
Sun, 28 Aug 2011 00:17:50 +0000
Continue reading ]]>
I would like to create an animated Mandelbrot visualization using JavaScript on an HTML5
In JavaScript, the escape function can be written as follows:
Mandelbrot.prototype.escapeFunc = function(x, y) {
r = 0.0; i = 0.0; m = 0.0;
j = 0;
while ((j < this.max) && (m < 4.0)) {j++;m = r * r - i * i;i = 2.0 * r * i + y;r = m + x;}return j;}For a given HTML5 canvas element, such as
A Manelbrot set over the complex plane can be represented with the follow object
function Mandelbrot(m) {
this.m = m;
this.c = m.getContext(“2d”);
this.width = m.width;
this.height = m.height;
this.SX = -1.75; // start value real
this.EX = 0.6;
// end value real
this.SY = -1.125; // start value imaginary
this.EY = 1.125;
// end value imaginary
this.xzoom = (this.EX – this.SX) / (this.width*1.0);
this.yzoom = (this.EY – this.SY) / (this.height*1.0);
}
Given these functions, rendering a Mandelbrot set on an HTML5 canvas element is as simple as looping through each of the pixels of the canvas, calculating the escape value, and drawing the pixel.
Here is a simple render function:
Mandelbrot.prototype.render = function() {
var prev_h = 0;
for (var x = 0; x < this.width; x=x+1) {for (var y = 0; y < this.height; y=y+1) {esc = this.escapeFunc(this.SX + x*this.xzoom, this.SY + y*this.yzoom);h = 360 * (esc/this.max)if (h != prev_h) {perc = Math.floor(100*(h/360))this.c.fillStyle='hsla('+ h + ','+ (perc+100) +'%,'+ (60-perc) +'%,'+ this.opacity+')';prev_h = h;}this.c.fillRect(x,y,1,1);}}}If you have an HTML5 compatible browser you should see an animated example below:your browser does not support the HTML5 canvas element]]>
javascript keyboard buffer, part 4
http://www.anattatechnologies.com/q/2011/07/javascript-keyboard-buffer-part-4/
Wed, 20 Jul 2011 18:28:18 +0000
Continue reading ]]>
Previously, we created a JavaScript keyboard buffer that can edit text in a static html page as well as .
I would like to combine all of this into a single JavaScript include called , and rather than specify each div that I want to edit I’d like to specify a classname such that all elements of that class will become editable, e.g.,
Spam and eggs are fantastic, although on second though…
Spam and eggs are fantastic, although on second thought…
Please see the example, , that uses multiple editable div’s in one page.
The editableByClassname(cls) function registers onclick events that will activate the keyboard buffer, editor, and replay functions for every element of the specified class.
//
// attach onclick event handlers by classname
function editableByClassname(cls) {
editable = $$(cls);
for (var i = 0; i < editable.length; i++) {editable[i].onclick = initEditable;}}There are two utility functions, $ and $$.The single $ is a shortcut to document.getElementById and the double $$ returns all elements by classname. I.e.,//// shortcut to getElementByIdfunction $(el) {return document.getElementById(el);}//// a simple getElementsByClassname implementationfunction $$(cl) {var retnode = [];var myclass = new RegExp('\\b'+cl+'\\b');var elem = document.getElementsByTagName('*');for (var i = 0; i < elem.length; i++) {var classes = elem[i].className;if (myclass.test(classes)) retnode.push(elem[i]);}return retnode;}]]>
css opacity in javascript
http://www.anattatechnologies.com/q/2011/07/css-opacity/
Thu, 14 Jul 2011 07:18:38 +0000
Continue reading ]]>
I want register JavaScript events to toggle CSS opacity on selectable images.
For example, given a div with a list of images like the following,
…
I would like these images to be 50% transparent but 80% visible during a mouseover. I would also like these images to be selectable, i.e., an image should become fully visible after clicking it.
I would like to do this in JavaScript without having to modify the html image list.
We could add transparency in the stylesheet, as well as the mouseover effect, e.g.,
#foo_images img {
filter: alpha(opacity=50);
opacity: 0.5;
}
#foo_images img:hover {
filter: alpha(opacity=80);
opacity: 0.8;
}
In practice, it is highly recommended to keep all presentation elements in the stylesheet, but for the sake of example we can adjust an objects transparency using JavaScript, e.g.,
//set obj transparency to 50%
obj.style.opacity = 0.5; //non-IE browsers
obj.style.filter = ‘alpha(opacity=50)’; //IE
Using this approach, we can register events with JavaScript so that the transparency will change as the cursor hovers over, e.g.,
obj.onmouseover = function() {
obj.style.opacity = 0.8;
obj.style.filter = ‘alpha(opacity=80)’;
}
obj.onmouseout = function() {
obj.style.opacity = 0.5;
obj.style.filter = ‘alpha(opacity=50)’;
}
This would obviously be a lot of repeated code so we can use JavaScript closures, e.g.,
function opacityC(obj, value) {return function() {
obj.style.opacity = value/100;
obj.style.filter = ‘alpha(opacity=’ + value + ‘)’;
}}
obj.onmouseover = opacityC(obj,80);
obj.onmouseout = opacityC(obj,50);
Next, to make the images selectable we can assign onclick events. We’ll need to toggle between selected and not-selected, so we’ll dynamically add a selected attribute to the image object. We can use the same closure approach to assign a function to the onclick event, e.g.,
function toggleSelectC(obj) {return function() {
if (obj.selected != ‘selected’) {
opacityC(obj, 100)();
obj.onmouseout = opacityC(obj, 100);
obj.style.border = ‘1px solid black’;
obj.selected = ‘selected’;
} else {
obj.onmouseout = opacityC(obj, 50);
obj.style.border = ‘1px solid white’;
obj.selected = ”;
}
}}
image1.onclick = toggleSelectC(image1);
image2.onclick = toggleSelectC(image2);
Finally, we will loop through all of the images in the div, set the initial transparency and add event handlers, e.g.,
var obj = document.getElementById(‘foo_images’);
var images = obj.getElementsByTagName(“img”);
for (var i = 0; i < images.length; i++) {var img = images[i];opacityC(img,50)();img.onmouseover = opacityC(img, 80);img.onmouseout = opacityC(img, 50);img.onclick = toggleSelectC(img);}Putting this all together, you would have the following HTML and JavaScript:
Applying the above code to the three sample images will produce the following results:
]]>
html footer at the bottom
http://www.anattatechnologies.com/q/2011/07/footer-at-the-bottom/
Thu, 14 Jul 2011 00:56:55 +0000
Continue reading ]]>
I want the footer of an html page to never be higher than the bottom of the browser window. In other words, if there’s not enough content to fill a webpage, I want the footer to be at the bottom of the page (rather than hovering underneath the content).
See this .
Assuming a standard html div layout, e.g.,
There is cross-browser approach to keep the footer at the bottom of the page. I have seen various approaches to this issue and all of them rely on a similar trick: First, enforce a min-height, and second, use margin/padding to position a fixed-height footer.
The cross-browser minimum height trick looks like this:
html, body {
height: 100%;
}
#page {
min-height: 100%;
height: auto !important;
height: 100%;
}
Non-IE (and newer IE) browsers will understand the min-height style, older versions require the height: auto !important; height: 100%; styles.
Next, we position a fixed-height footer. You can do this through a negative-margin that overlaps the body, or use position: absolute;. I prefer the latter approach as it looks cleaner.
Either way, remember to pad the bottom of your body content so that the footer will never overlap actual content, e.g.,
#body {
padding-bottom: 3em;
}
#footer {
position: absolute;
bottom: 0;
height: 3em;
}
The footer height must be fixed, and the padding-bottom should be greater than or equal to the fixed footer height.
Putting it all together, please see this
which uses the following sticky footer css:
/* sticky footer */
html, body {
height: 100%;
}
#page {
min-height: 100%;
height: auto !important;
height: 100%;
position: relative;
}
#body {
padding-bottom: 3em;
}
#footer {
position: absolute;
bottom: 0;
height: 3em;
}
]]>
scraping and parsing html
http://www.anattatechnologies.com/q/2011/05/scraping-and-parsing-html/
Thu, 26 May 2011 05:58:13 +0000
http://www.anattasoftware.com/blog/?p=31
Continue reading ]]>
I would like to read J. Krishnamurti books on my Kindle. Unfortunately, no ebooks were available although I did find that
has an extensive collection of books on their website.
At present there is no full download, only a per-chapter html viewer, and some of the books ran over 80 chapters, which is more than I am going to copy+paste into a text file.
I decided I’d use python and the HTMLParser library and write a throw-away parser.
I realized parsing multi-page websites into text files might be useful for other purposes so I wrote a simple closure that requires two parse functions and returns a custom scraper function that will scrape all pages of an article or book and save it as a single plain text file.
One parse function must return the URL of the next webpage to scrape, and the other parse function must return the HTML of the readable text.
Basically, pass in two parse functions (specific for whatever website you’re attempting to scrape) into the closure and it will return a scraper utilizing those parse functions.
from posixpath import basename, dirname
from traceback import print_exc
import urllib, StringIO, HTMLParser, re, sys
def make_scraper(findtext, findnext):
def scraper(inurl, outfilename):
base_url = dirname(inurl)
next_url = basename(inurl)
chapter = 1
while True:
html = urllib.urlopen(base_url + ‘/’ + next_url).read()
match = findtext(html)
if match:
print “chapter %s – %s” % (chapter, next_url)
f = open(outfilename, ‘a’)
f.write(‘nnCHAPTER %snn%s’ % (chapter, dehtml(match.group(1))) )
f.close
next_match = findnext(html)
if next_match:
next_url = next_match.group(1)
chapter += 1
else:
break
else:
break
return scraper
The dehtml function is a very simple HTMLParser implementation that strips out all the HTML tags and maintains line and paragraph breaks.
class _DeHTMLParser(HTMLParser.HTMLParser):
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self.__text = []
def handle_data(self, data):
text = data.strip()
if len(text) > 0:
text = re.sub(‘[ trn]+’, ‘ ‘, text)
self.__text.append(text + ‘ ‘)
def handle_starttag(self, tag, attrs):
if tag == ‘p’:
self.__text.append(‘nn’)
elif tag == ‘br’:
self.__text.append(‘n’)
def handle_startendtag(self, tag, attrs):
if tag == ‘br’:
self.__text.append(‘nn’)
def text(self):
return ”.join(self.__text).strip()
def dehtml(text):
try:
parser = _DeHTMLParser()
parser.feed(text)
parser.close()
return parser.text()
except:
print_exc(file=sys.stderr)
return text
For example, I want to scrape and parse books from
so I will use the following parse functions to create my custom scraper.
## custom parse functions
nextchapter = re.compile(‘
re.M | re.S).search
parsetext = re.compile(‘
‘(.*)s*
re.M | re.S).search
## create custom parser/scraper
get_jkrish_text = make_scraper(parsetext, nextchapter)
I can now use get_jkrish_txt(). Here it is downloading a shorter (9 chapter) book,
>>> get_jkrish_txt(jkrish_url, ‘flameofattention.txt’)
chapter 1 – view-text.php?tid=29&chid=56860&w=
chapter 2 – view-text.php?tid=29&chid=56861&w=
chapter 3 – view-text.php?tid=29&chid=56862&w=
chapter 4 – view-text.php?tid=29&chid=56863&w=
chapter 5 – view-text.php?tid=29&chid=56864&w=
chapter 6 – view-text.php?tid=29&chid=56865&w=
chapter 7 – view-text.php?tid=29&chid=56866&w=
chapter 8 – view-text.php?tid=29&chid=56867&w=
chapter 9 – view-text.php?tid=29&chid=56868&w=
>>>
]]>