Get colour sample from transparent pixel - transparency

I'm trying detect if a pixel is complete transparent or not. More specifically, if an image is on a transparent background or not. I thought that
// Add a Color Sampler at a given x and y coordinate in the image.
var pointSample = app.activeDocument.colorSamplers.add([(x),(y)]);
// Obtain array of RGB values.
var rgb = [
pointSample.color.rgb.red,
pointSample.color.rgb.green,
pointSample.color.rgb.blue
];
would work - and it does...
Unless the pixel has 0% opacity (ie 100% transparent) in which case Photoshop throws a General 8800 error. I would use the above with a try catch but that probably isn't the way to go about it.
Any ideas?

Well I found a way to determine if an image has transparency or not:
delete_all_colour_samples();
var isImageTransparent = has_transparency();
var x = 0;
var y = 0;
alert(isImageTransparent ? "Image has transparency." : "Image is opaque.");
if (isImageTransparent)
{
// do stuff
}
else
{
// get colour sample
// Add a Color Sampler at a given x and y coordinate in the image.
var pointSample = app.activeDocument.colorSamplers.add([(x),(y)]);
// Obtain array of RGB values.
var rgb = [
pointSample.color.rgb.red,
pointSample.color.rgb.green,
pointSample.color.rgb.blue
];
}
// function to see if image has transparency
function has_transparency()
{
var desc52 = new ActionDescriptor();
var ref47 = new ActionReference();
ref47.putProperty( charIDToTypeID('Chnl'), charIDToTypeID('fsel') );
desc52.putReference( charIDToTypeID('null'), ref47 );
var ref48 = new ActionReference();
ref48.putEnumerated( charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Trsp') );
desc52.putReference( charIDToTypeID('T '), ref48 );
desc52.putBoolean( charIDToTypeID('Invr'), true );
try
{
executeAction( charIDToTypeID('setd'), desc52, DialogModes.NO );
}
catch(eek)
{
return false;
}
activeDocument.selection.deselect();
return true;
}
function delete_all_colour_samples()
{
// Kill all colour samples
app.activeDocument.colorSamplers.removeAll();
}

Related

send p5.js image to server

I captured an image from createcapture() through a webcam. Using image(), I got the image onto the canvas. Using saveframes(), and a callback, I was able to send the image to a server, but the image size is very big and I want the image to be 100 x 100 pixels every time whatever may be the size of image from saveframes() before sending it to server.
var x = window.innerWidth * 0.5;
var y = window.innerHeight * 0.75;
function setup()
{
cnv = createCanvas(x, y);
videoInput = createCapture(VIDEO);
videoInput.size(x, y);
videoInput.hide();
}
function draw()
{
if (videoInput) {
image(videoInput, 0, 0, x, y);
}
}
function image()
{
saveFrames('out','png',1,1,
function(im) {
console.log(im);
console.log(typeof im[0]);
// image Data is stored in im[0].imageData
// convert the image to smaller size
data.imageData = im[0].imageData;
// data.imageData = Math.random();
}
);
$.post('addname',data,function(result) {
console.log("data sent", result);
});
}

three.js, dat.GUI slider controlled by code, morph targets do not move

I work on a human face that the mouth should move about external coordinates (OpenCV and dlibs). In a first step I try to control the dat.GUI by code, which already works. But now I have the problem that the morph targets do not move when I control by code. The sliders move, but the face doesn't. When I use the mouse, they work perfectly. I ask for help with this problem.
<script>
// Laden der 3DScene
var scene = new THREE.Scene();
// Laden der Kamear Perspektive
var camera = new THREE.PerspectiveCamera(15, window.innerWidth/window.innerHeight, 1, 10000);
camera.position.z = 17;
camera.position.y = 3;
// Laden des Renderers
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Laden des Orbitcontrollers
var controls = new THREE.OrbitControls( camera, renderer.domElement );
// Laden der Lichter (Beleuchtung)
var ambientLight = new THREE.AmbientLight(0x111111);
scene.add(ambientLight);
var light = new THREE.PointLight( 0xFFFFDD );
light.position.set( -15, 10, 15 );
scene.add(light);
// Laden des Json Modells
var loader = new THREE.JSONLoader();
loader.load( "./three/models/JSON/test/mkh_shapes.json", function (geometry) {
var material = new THREE.MeshLambertMaterial({morphTargets: true});
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.set(1.2,1.2,1.2); //Modellgrösse die angezeigt wird
mesh.position.x = 0; //Position (x = nach rechts+ links-)
mesh.position.y = -19; //Position (y = nach oben +, unten-)
mesh.position.z = 0; //Position (z = nach vorne +, hinten-)
scene.add(mesh);
//dat.Gui
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var shape = {
mouth_open: 0.0, //Anfangsposition 0.0
};
var gui = new dat.GUI();
var folder = gui.addFolder( 'Morph Targets' );
folder.add( shape, 'mouth_open', 0, 1 ).step( 0.01 ).name('mouth_open').listen().onChange ( function( a ) { mesh.morphTargetInfluences[ 40 ] = a;} );
folder.open();
var updateGui = function() {
for (var i in folder.__controllers) {
folder.__controllers[i].updateDisplay();
}
}
var time = Date.now() * 0.003;
shape.mouth_open = 0.50 //* Math.sin( 0.5 * time ) + 0.3;
//scene.add(shape);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
});
function animate() {
render();
requestAnimationFrame( animate );
}
function render() {
renderer.clear();
renderer.render( scene, camera );
}
animate();
</script>
I have made my own version with extra features like :
Gui auto resize based on content div.
Improved slidecontroller as unique controller (slide or number insert);
Multi language automatic support
Auto check for conflicts in options, then ask for confirm or cancel.
Auto Show/hide other controllers when option selected deselected (example show color list only if "custom color is selected")
ecc.. ecc..
here is the Video
Now is more confortable and easy to use.

Crispy GridLineDashStyle

The gridlines when set to "ShortDot", or any Dots, are always two pixels tall in SVG, and research says it can be fixed via
a) transform(0.5,0.5) -- moves it half a pixel so drawing is in one pixel,
or
b) add style='shape-rendering:crispEdges' to the element
See demo here:
http://jsfiddle.net/aerialflyer/o2d9w6up/
Here's the SVGElement prototype from Highcharts.js
SVGElement.prototype = {
dashstyleSetter: function (value) {
var i;
value = value && value.toLowerCase();
if (value) {
value = value
.replace('shortdashdotdot', '3,1,1,1,1,1,')
.replace('shortdashdot', '3,1,1,1')
.replace('shortdot', '1,1,')
.replace('shortdash', '3,1,')
.replace('longdash', '8,3,')
.replace(/dot/g, '1,3,')
.replace('dash', '4,3,')
.replace(/,$/, '')
.split(','); // ending comma
i = value.length;
while (i--) {
value[i] = pInt(value[i]) * this['stroke-width'];
}
value = value.join(',')
.replace('NaN', 'none'); // #3226
this.element.setAttribute('stroke-dasharray', value);
}
}
}
How can this be updated to include either the transform, or the 'style' (preferred)??
i.e.
Add
this.element.setAttribute('style', 'shape-rendering:crispEdges');
Can the SVGElement prototype be updated (fails so far)
// Make grid lines crispt to prevent anti-alias
SVGElement.prototype['dashstyleSetter'] = SVGElement.prototype.dashstyleSetter = function (value) {
var i;
value = value && value.toLowerCase();
if (value) {
value = value
.replace('shortdashdotdot', '3,1,1,1,1,1,')
.replace('shortdashdot', '3,1,1,1')
.replace('shortdot', '1,1,')
.replace('shortdash', '3,1,')
.replace('longdash', '8,3,')
.replace(/dot/g, '1,3,')
.replace('dash', '4,3,')
.replace(/,$/, '')
.split(','); // ending comma
i = value.length;
while (i--) {
value[i] = pInt(value[i]) * this['stroke-width'];
}
value = value.join(',')
.replace('NaN', 'none'); // #3226
this.element.setAttribute('stroke-dasharray', value);
this.element.setAttribute('style', 'shape-rendering:crispEdges');
}
};
Highcharts Demo:
http://jsfiddle.net/aerialflyer/yj1s5xps/
See how dot is just a long gray line
It is possible to extend Highcharts and set shape-rendering to crispEdges (because shape-rendering is attribute set directly, not in style - MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering) in dashstyleSetter of SVGElement.
Wrapper:
(function (H) {
H.wrap(H.SVGElement.prototype, 'dashstyleSetter', function (proceed) {
// Run original proceed method
proceed.apply(this, [].slice.call(arguments, 1));
if(arguments[1]) {
this.element.setAttribute('shape-rendering', 'crispEdges');
}
});
}(Highcharts));
JSFiddle example: http://jsfiddle.net/yurn5oz5/
Docs reference for extending Highcharts

Restrict Pan outside WMS extent in OpenLayers3

I have rectangle WMS of small area and want to restrict panning outside WMS extends, so there aren't white or black area outside the map visible at all.
Adding extent to View does not work for me and in documentation about this option is written
The extent that constrains the center, in other words, center cannot
be set outside this extent.
But as I understand this if center is in the area of extent, but on the very corner, it will show white area outside this extent, but I don't want to see white area at all.
Is it possible to achieve this with OL3?
Here's my solution. I wrote it just now, and so it is not extensively tested. It would probably break if you start rotating the map, for example, and it may be glitchy if you zoom out too far.
var constrainPan = function() {
var visible = view.calculateExtent(map.getSize());
var centre = view.getCenter();
var delta;
var adjust = false;
if ((delta = extent[0] - visible[0]) > 0) {
adjust = true;
centre[0] += delta;
} else if ((delta = extent[2] - visible[2]) < 0) {
adjust = true;
centre[0] += delta;
}
if ((delta = extent[1] - visible[1]) > 0) {
adjust = true;
centre[1] += delta;
} else if ((delta = extent[3] - visible[3]) < 0) {
adjust = true;
centre[1] += delta;
}
if (adjust) {
view.setCenter(centre);
}
};
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);
This expects the variables map, view (with obvious meanings) and extent (the xmin, ymin, xmax, ymax you want to be visible) to be available.
Here's a more robust implementation that should work really well in any case. It's written in ES6, and requires isEqual method (from lodash or anything else ...)
const extent = [-357823.2365, 6037008.6939, 1313632.3628, 7230727.3772];
const view = this.olMap.getView();
const modifyValues = {};
// Trick to forbid panning outside extent
let constrainPan = (e) => {
const type = e.type;
const newValue = e.target.get(e.key);
const oldValue = e.oldValue;
if (isEqual(oldValue, newValue)) {
// Do nothing when event doesn't change the value
return;
}
if (isEqual(modifyValues[type], newValue)) {
// Break possible infinite loop
delete modifyValues[type];
return;
}
if (type === 'change:resolution' && newValue < oldValue) {
// Always allow zoom-in.
return;
}
const visibleExtent = view.calculateExtent(this.olMap.getSize());
const intersection = ol.extent.getIntersection(visibleExtent, extent);
const modify = !isEqual(intersection, visibleExtent);
if (modify) {
if (type === 'change:center') {
const newCenter = newValue.slice(0);
if (ol.extent.getWidth(visibleExtent) !== ol.extent.getWidth(intersection)) {
newCenter[0] = oldValue[0];
}
if (ol.extent.getHeight(visibleExtent) !== ol.extent.getHeight(intersection)) {
newCenter[1] = oldValue[1];
}
modifyValues[type] = newCenter;
view.setCenter(newCenter);
} else if (type === 'change:resolution') {
modifyValues[type] = oldValue;
view.setResolution(oldValue);
}
}
};
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);
This is an extension to #tremby answer, but to long for a comment.
First of all, his solution works really well for me, but it was called way to often. Therefore I wrapped it in a debounce function.
So
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);
becomes
var dConstrainPan = debounce(constrainPan);
view.on('change:resolution', dConstrainPan);
view.on('change:center', dConstrainPan);
This will result in a slight flicker, when moving outside the bounding box, bot zooming/ moving works without delay.
Still not perfect but a useful improvement from my point of view.
Debounce code:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
Soruce: https://davidwalsh.name/javascript-debounce-function , in underscore.js

Titanium ImageView animation width and height

I try to create an ImageView in Titanium like this:
var animationView = Titanium.UI.createImageView
(
{
images:animationImages,
duration:50,
repeatCount:0,
width: '90dp',
height: '270dp'
}
);
On android it gets its size as expected, but on IOS, it simply doesn't gets scaled. Is there something, i'm doing wrong? Or should i do it frame by frame by creating the ImageViews manually then changing them with setInterval?
This is actually not a consistent solution, it should be a comment, but since I don't have enough rep I have to write it as an answer.
For starters I would try to give it a top and left properties.
Secondly, are those images retrieved from a remote URL? Remote URLs are only supported in Android. If that is the case you could do a workaround as you said in the question.
Finally, the 'dp' only works for android, so it won't scale at all in iOS, it will simply erase the 'dp' and use the number as "points", on non-retina screens it will be the same number of pixels and on a retina display it will be the double.
I finally decided to create my own animation class, which look like this:
function Animation(data)
{
var width = data.hasOwnProperty("width") ? data.width : Ti.UI.SIZE;
var height = data.hasOwnProperty("height") ? data.height: Ti.UI.SIZE;
var duration = data.hasOwnProperty("duration") ? data.duration : 50;
var imageFiles = data.hasOwnProperty("images") ? data.images : [];
var images = [];
var container = Ti.UI.createView
(
{
width:width,
height: height
}
);
for(var i=0; i<imageFiles.length; i++)
{
var image = Ti.UI.createImageView
(
{
image:imageFiles[i],
width:width,
height:height
}
);
if(i!=0)
image.setVisible(false);
container.add(image);
images.push(image);
}
container.activeImage = 0;
container.intervalId = null;
container.setActiveImage = function(index)
{
if(container.intervalId == null)
container.activeImage = index;
}
container.start = function()
{
var callback = function()
{
for(var i=0; i<images.length; i++)
{
if(i == container.activeImage)
images[i].setVisible(true);
else
images[i].setVisible(false);
}
container.activeImage = (container.activeImage + 1) % images.length;
}
container.intervalId = setInterval ( callback, duration );
}
container.stop = function()
{
clearInterval(container.intervalId);
container.intervalId = null;
}
return container;
}
module.exports = Animation;
And you can use it like this:
var Animation = require('...path to your animation file');
var myAnimation = new Animation
(
{
width:'100dp',
height:'100dp',
duration:50, //duration while one frame is showing
images:['one.png', 'two.png'...], //full paths
}
);
//start:
myAnimation.start();
//stop
myAnimation.stop();

Resources