I have this for-loop:
y1 = 0; y2 = 3264; x1 = 0; x2 = 4928; uc = 1; vc = 1; scale = 1;
for (var y = y1; y < y2; y++) {
for (var x = x1; x < x2; x++) {
sumR = 0;
sumG = 0;
sumB = 0;
i = 0;
for (var v = -vc; v <= vc; v++) {
for (var u = -uc; u <= uc; u++) {
if (kernel[i] != 0) {
var tempX = x + u < 0 ? 0 : x + u;
var tempY = y + v < 0 ? 0 : y + v;
tempX = tempX >= width ? width - 1 : tempX;
tempY = tempY >= height ? height - 1 : tempY;
sumR += pixels.data[((tempY * (pixels.width*4)) + (tempX * 4)) + 0] * kernel[i];
sumG += pixels.data[((tempY * (pixels.width*4)) + (tempX * 4)) + 1] * kernel[i];
sumB += pixels.data[((tempY * (pixels.width*4)) + (tempX * 4)) + 2] * kernel[i];
}
i++;
}
}
tempArray.push(sumR * scale, sumG * scale, sumB * scale, 255);
}
console.log(y + "|" + y2);
}
So basically it's about image processing, the loop stops at y = 3115 without any error, everything after the loop isn't computed it just "crashes" there. Do you guys have any ideas how this could happen? Can there be a problem with memory?
UPDATE: I think I made this abit unclear: if I use this algorithm for a image with size y2 = 1000 and x2 = 1000 everything is working fine. But if the images get bigger it just stopps working, there is no errormessage in the console!
uc + vc = 1; is a invalid statement,
uc and vc don't seem to be defined anywhere,
scale isn't defined anywhere.
The second x1 here should probably be x2:
x1 = 0; x1 = 4928;
//Should probably be:
x1 = 0; x2 = 4928;
This pretty much comes down to: "debug your code".
Okay finally I found the problem,
I initialized the array this way: var tempArray = []; above the for-loops, next step was that I tried to initialize it this way : var tempArray = new Array(width * height * 4)
The browser just stopped at that position now and didn't even enter the for-loops. So I guess the Array is just to big to create.
Solution: I am using a Typed Array now and everything is working:
var tempArray = new Uint8ClampedArray(width * height * 4);
Related
I'm using Json Daives' D3 word cloud in R. I have generated the word cloud but the problem I face is that the shape of the word cloud is not circular. I was going through d3.layout.cloud.js file to try and modify the code to achieve this but in vain. The file has a function called "place" which defines the shape of the cloud. But I could not figure out how to modify this function so as to achieve the circular shape. Has anyone else tried to achieve this circular representation? I am pasting the code of the place function below.
function place(board, tag, bounds) {
var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}],
startX = tag.x,
startY = tag.y,
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]),
s = spiral(size),
dt = Math.random() < .5 ? 1 : -1,
t = -dt,
dxdy,
dx,
dy;
while (dxdy = s(t += dt)) {
dx = ~~dxdy[0];
dy = ~~dxdy[1];
if (Math.min(dx, dy) > maxDelta) break;
tag.x = startX + dx;
tag.y = startY + dy;
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
// TODO only check for collisions within current bounds.
if (!bounds || !cloudCollide(tag, board, size[0])) {
if (!bounds || collideRects(tag, bounds)) {
var sprite = tag.sprite,
w = tag.width >> 5,
sw = size[0] >> 5,
lx = tag.x - (w << 4),
sx = lx & 0x7f,
msx = 32 - sx,
h = tag.y1 - tag.y0,
x = (tag.y + tag.y0) * sw + (lx >> 5),
last;
for (var j = 0; j < h; j++) {
last = 0;
for (var i = 0; i <= w; i++) {
board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0);
}
x += sw;
}
delete tag.sprite;
return true;
}
}
}
return false;
}
This is video Length in seconds : 145
and i want to out put this value like this ,80,74,2, How can i get Length Seconds 145 to Convert like ,80,74,2, in PHP
{"length_seconds":"145"} how to i covert length_seconds 145 in this format 80,74,2
For this example JavaScript
videojs('mint').thumbnails(eval("("+mksb('G_0TziI12SE',80,74,2,'wa1cIFpwGxMNbz9bRlRFZCkjlOc')+")"));
Alright, by digging through the source code, I found mksb() in videojs.thumbnails.js:
function mksb(vid, img_width, frames, interval, sihg) {
var r = '';
counter = 0;
for (k = 0; k < 50; k++) {
for (j = 0; j < 10; j++) {
for (i = 0; i < 10; i++) {
if (counter == frames) break;
x1 = img_width * i;
x2 = x1 + 40;
x3 = x1 + 80;
y1 = j * 45;
y2 = y1 + 60;
y3 = y1 + 45;
x4 = frames - k * 100;
if (x4 < 100) {
x4 = Math.ceil(x4 / 10) * 45;
} else {
x4 = 450;
};
m = '//img.ytapi.com/sb/' + vid + '/storyboard3_L1/M' + k + '.jpg?sigh=' + sihg;
r += counter++ * interval + ":{src:'" + m + "',style:{left:'-" + x2 + "px',width:'" + img_width * 10;
r += "px',height:'" + x4 + "px',top:'-" + y2 + "px',clip:'rect(" + y1 + "px," + x3 + "px," + y3 + "px," + x1 + "px)'}},";
}
}
}
return '{' + r + '}';
}
So, 'G_0TziI12SE' is the video ID, 80 is the thumbnail width, 74 seems to be a frame count, 2 seems to be an interval in seconds, and I have no idea what 'wa1cIFpwGxMNbz9bRlRFZCkjlOc' is, but perhaps a cryptographic signature?
So, 74 * 2 is 148, which is fairly close to 145, but that's as close as I can get. This basically seems to be a "frames # frame-rate" type of expression. So, to convert seconds into this type of expression, you'd just do (int) $seconds / 2.
That's all I've got, but I hope it helps point you in the right direction.
I have been trying to implement Bradley Adaptive thresholding. I know there is a python code in one of the stack overflow questions. But i am struggling to implement the same in JS by following that. Can anyone please help me? So far my code is:
function computeAdaptiveThreshold (imagetest,imageWidth,imageHeight,callback)
{
var size = imageWidth*imageHeight*4;
var s = imageWidth/8;
var s2=s>>1;
var t=0.15;
var it=1.0-t;
var i,j,diff,x1,y1,x2,y2,ind1,ind2,ind3;
var sum=0;
var ind=0;
var integralImg = [];
var canvas = document.createElement('canvas');
var bin = canvas.getContext('2d').createImageData(imageWidth, imageHeight);
for(i=0;i<imageWidth;i++)
{
sum = 0;
for(j=0;j<imageHeight;j++)
{
index = i *imageHeight + j;
sum += imagetest.data[index];
if(i== 0)
{
integralImg[index] = sum;
}
else
{
//index = (i-1) * height + j;
integralImg[index] = integralImg[(i-1) * imageHeight + j] + sum;
}
}
}
x1=0;
for(i=1;i<imageWidth;++i)
{
sum=0;
ind=i;
ind3=ind-s2;
if(i>s)
{
x1=i-s;
}
diff=i-x1;
for(j=0;j<imageHeight;++j)
{
sum+=imagetest.data[ind];// & 0xFF;
integralImg[ind] = integralImg[(ind-1)]+sum;
ind+=imageWidth;
if(i<s2)continue;
if(j<s2)continue;
y1=(j<s ? 0 : j-s);
ind1=y1*imageWidth;
ind2=j*imageWidth;
if (((imagetest.data[ind3])*(diff * (j - y1))) < ((integralImg[(ind2 + i)] - integralImg[(ind1 + i)] - integralImg[(ind2 + x1)] + integralImg[(ind1 + x1)])*it)) {
bin.data[ind3] = 0;
} else {
bin.data[ind3] = 255;
}
ind3 += imageWidth;
}
}
y1 = 0;
for( j = 0; j < imageHeight; ++j )
{
i = 0;
y2 =imageHeight- 1;
if( j <imageHeight- s2 )
{
i = imageWidth - s2;
y2 = j + s2;
}
ind = j * imageWidth + i;
if( j > s2 ) y1 = j - s2;
ind1 = y1 * imageWidth;
ind2 = y2 * imageWidth;
diff = y2 - y1;
for( ; i < imageWidth; ++i, ++ind )
{
x1 = ( i < s2 ? 0 : i - s2);
x2 = i + s2;
// check the border
if (x2 >= imageWidth) x2 = imageWidth - 1;
if (((imagetest.data[ind])*((x2 - x1) * diff)) < ((integralImg[(ind2 + x2)] - integralImg[(ind1 + x2)] - integralImg[(ind2 + x1)] + integralImg[(ind1 + x1)])*it)) {
bin.data[ind] = 0;
} else {
bin.data[ind] = 255;
}
}
}
callback(bin);`
I am getting very bad images. I should say i cannot call it as a image.
I think your first effort should be to refactor your code : it will be much easier to handle the index.
Then you'll see that you have issues with your indexes : an image -even a gray one- is an RGBA Array, meaning 4 bytes = 32 bits per pixel.
You could handle this by doing a conversion RGBA-> b&W image, then thresholding, then doing b&w -> RGBA back.
...Or handle the RGBA components as you go. Notice that here you only want to output black or white, so you can create an Int32 view on the array, and write at once R,G,B,A for each pixels.
So some code (working here : http://jsfiddle.net/gamealchemist/3zuopz19/8/ ) :
function computeAdaptiveThreshold(sourceImageData, ratio, callback) {
var integral = buildIntegral_Gray(sourceImageData);
var width = sourceImageData.width;
var height = sourceImageData.height;
var s = width >> 4; // in fact it's s/2, but since we never use s...
var sourceData = sourceImageData.data;
var result = createImageData(width, height);
var resultData = result.data;
var resultData32 = new Uint32Array(resultData.buffer);
var x = 0,
y = 0,
lineIndex = 0;
for (y = 0; y < height; y++, lineIndex += width) {
for (x = 0; x < width; x++) {
var value = sourceData[(lineIndex + x) << 2];
var x1 = Math.max(x - s, 0);
var y1 = Math.max(y - s, 0);
var x2 = Math.min(x + s, width - 1);
var y2 = Math.min(y + s, height - 1);
var area = (x2 - x1 + 1) * (y2 - y1 + 1);
var localIntegral = getIntegralAt(integral, width, x1, y1, x2, y2);
if (value * area > localIntegral * ratio) {
resultData32[lineIndex + x] = 0xFFFFFFFF;
} else {
resultData32[lineIndex + x] = 0xFF000000;
}
}
}
return result;
}
function createImageData(width, height) {
var canvas = document.createElement('canvas');
return canvas.getContext('2d').createImageData(width, height);
}
function buildIntegral_Gray(sourceImageData) {
var sourceData = sourceImageData.data;
var width = sourceImageData.width;
var height = sourceImageData.height;
// should it be Int64 Array ??
// Sure for big images
var integral = new Int32Array(width * height)
// ... for loop
var x = 0,
y = 0,
lineIndex = 0,
sum = 0;
for (x = 0; x < width; x++) {
sum += sourceData[x << 2];
integral[x] = sum;
}
for (y = 1, lineIndex = width; y < height; y++, lineIndex += width) {
sum = 0;
for (x = 0; x < width; x++) {
sum += sourceData[(lineIndex + x) << 2];
integral[lineIndex + x] = integral[lineIndex - width + x] + sum;
}
}
return integral;
}
function getIntegralAt(integral, width, x1, y1, x2, y2) {
var result = integral[x2 + y2 * width];
if (y1 > 0) {
result -= integral[x2 + (y1 - 1) * width];
if (x1 > 0) {
result += integral[(x1 - 1) + (y1 - 1) * width];
}
}
if (x1 > 0) {
result -= integral[(x1 - 1) + (y2) * width];
}
return result;
}
I want an array looking like this:
[
[0,0,1,1,1,0,0],
[0,1,1,1,1,1,0],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,1,1,1,1],
[0,1,1,1,1,1,0],
[0,0,1,1,1,0,0],
]
My first approach was to get the circumference
var steps = 100;
var coord = [];
var x,y;
for (var i = 0; i < steps; i++) {
var phase = 2 * Math.PI * i / steps;
x = Math.round(cenx + range * Math.cos(phase));
y = Math.round(ceny + range * Math.sin(phase))
if(x>=0 && y >=0){
coord.push([x,y]);
}
}
and with the resulting coords i could have juggled around to get the circular area. but i doubt that would be performant.
So my second approach would be to check every entry of the array whether it has a certain distance (i.e. radius) to the center of my circle. but for huge maps that wouldnt be performant either. perhaps checking only in a reasonable frame would be wiser.
but im certain there is a better approach for this problem.
im needing this for a fog of war implementation.
Your second suggested approach of testing each point in the array will be simple to implement, and can be optimized to just one subtract, one multiply and one test per element in the inner loop.
The basic test is ((x - centerX) * (x - centerX)) + ((y - centerY) * (y - centerY)) > radiusSq, but since ((y - centerY) * (y - centerY)) will be constant for a given row you can move that outside the loop.
Given that you have to visit each element in the array and set it anyway (meaning your algorithm will always be O(n2) on the circle radius), the test is a negligible cost:
// circle generation code:
function makeCircle(centerX, centerY, radius, a, arrayWidth, arrayHeight)
{
var x, y, d, yDiff, threshold, radiusSq;
radius = (radius * 2) + 1;
radiusSq = (radius * radius) / 4;
for(y = 0; y < arrayHeight; y++)
{
yDiff = y - centerY;
threshold = radiusSq - (yDiff * yDiff);
for(x = 0; x < arrayWidth; x++)
{
d = x - centerX;
a[y][x] = ((d * d) > threshold) ? 0 : 1;
}
}
}
// test code:
var width = 7;
var dim = (width * 2) + 1;
var array = new Array(dim);
for(row = 0; row < dim; row++)
array[row] = new Array(dim);
makeCircle(width, width, width, array, dim, dim);
for(var y = 0, s = ""; y < dim; y++)
{
for(var x = 0; x < dim; x++)
{
s += array[y][x];
}
s += "<br>";
}
document.body.innerHTML += s + "<br>";
I would use the mid-point circle algorithm and see the array as a bitmap.
I did this JavaScript implementation a while back, modified here to use an array as target source for the "pixel". Just note that a circle will produce odd widths and heights as the distance is always from a single center point and we can only use integer values in this case.
Tip: For speed improvements you could use typed array instead of a regular one (shown below).
Example
Make sure to use integer values as input, the code will clip values outside the "bitmap"/array -
var width = 7, height = 7,
array = new Uint8Array(width * height);
// "draw" circle into array
circle(3, 3, 3);
renderDOM();
// circle example 2
width = height = 17;
array = new Uint8Array(width * height);
circle(8, 8, 8);
renderDOM();
function circle(xc, yc, r) {
if (r < 1) return;
var x = r, y = 0, // for Bresenham / mid-point circle
cd = 0,
xoff = 0,
yoff = r,
b = -r,
p0, p1, w0, w1;
while (xoff <= yoff) {
p0 = xc - xoff;
p1 = xc - yoff;
w0 = xoff + xoff;
w1 = yoff + yoff;
hl(p0, yc - yoff, yc + yoff, w0); // fill a "line"
hl(p1, yc - xoff, yc + xoff, w1);
if ((b += xoff+++xoff) >= 0) {
b -= --yoff + yoff;
}
}
// for fill
function hl(x, y1, y2, w) {
w++;
var xw = 0;
while (w--) {
xw = x + w;
setPixel(xw, y1);
setPixel(xw, y2);
}
}
function setPixel(x, y) {
if (x < width && y < height && x >= 0 && y >= 0)
array[y * width + x] = 1;
}
}
function renderDOM() {
for(var i = 0, str = ""; i < array.length; i++) {
if (i > 0 && !(i % width)) str += "<br>";
str += array[i];
}
document.body.innerHTML += str + "<br><br>";
}
body {font:18px monospace}
For an odd-sized array (2r+1 x 2r+1),
for (row= 0; row < 2 * r + 1; row++)
{
f= (row + 1) * (row - 2 * r - 1) + r * r + r;
for (col= 0; col < 2 * r + 1; f+= 2 * (col - r) + 1; col++)
{
array[row][col]= f >= 0;
}
}
I am trying to grab the nearest plotted point that the cursor is to. I
I found the findNearbyItem function in the jquery.flot.js source that seems to be able to do this, but when I trie calling it manually, I received the ReferenceError: findNearbyItem is not defined error.
This is the function I am referring to:
function findNearbyItem(mouseX, mouseY, seriesFilter) {
var maxDistance = options.grid.mouseActiveRadius,
smallestDistance = maxDistance * maxDistance + 1,
item = null, foundPoint = false, i, j, ps;
for (i = series.length - 1; i >= 0; --i) {
if (!seriesFilter(series[i]))
continue;
var s = series[i],
axisx = s.xaxis,
axisy = s.yaxis,
points = s.datapoints.points,
mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
my = axisy.c2p(mouseY),
maxx = maxDistance / axisx.scale,
maxy = maxDistance / axisy.scale;
ps = s.datapoints.pointsize;
// with inverse transforms, we can't use the maxx/maxy
// optimization, sadly
if (axisx.options.inverseTransform)
maxx = Number.MAX_VALUE;
if (axisy.options.inverseTransform)
maxy = Number.MAX_VALUE;
if (s.lines.show || s.points.show) {
for (j = 0; j < points.length; j += ps) {
var x = points[j], y = points[j + 1];
if (x == null)
continue;
// For points and lines, the cursor must be within a
// certain distance to the data point
if (x - mx > maxx || x - mx < -maxx ||
y - my > maxy || y - my < -maxy)
continue;
// We have to calculate distances in pixels, not in
// data units, because the scales of the axes may be different
var dx = Math.abs(axisx.p2c(x) - mouseX),
dy = Math.abs(axisy.p2c(y) - mouseY),
dist = dx * dx + dy * dy; // we save the sqrt
// use <= to ensure last point takes precedence
// (last generally means on top of)
if (dist < smallestDistance) {
smallestDistance = dist;
item = [i, j / ps];
}
}
}
if (s.bars.show && !item) { // no other point can be nearby
var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
barRight = barLeft + s.bars.barWidth;
for (j = 0; j < points.length; j += ps) {
var x = points[j], y = points[j + 1], b = points[j + 2];
if (x == null)
continue;
// for a bar graph, the cursor must be inside the bar
if (series[i].bars.horizontal ?
(mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
my >= y + barLeft && my <= y + barRight) :
(mx >= x + barLeft && mx <= x + barRight &&
my >= Math.min(b, y) && my <= Math.max(b, y)))
item = [i, j / ps];
}
}
}
if (item) {
i = item[0];
j = item[1];
ps = series[i].datapoints.pointsize;
return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
dataIndex: j,
series: series[i],
seriesIndex: i };
}
return null;
}
If there are alternate ways of solving this problem, please let me know.
What's your use case for this? If you increase the mouseActiveRadius option to something large flot will find the closest point to the cursor for you.
var options = {
grid: {
hoverable: true,
mouseActiveRadius: 1000
}
}
Example here.
EDIT
Yes, you can use the plothover event to retrieve the highlighted point.
$("#placeholder").bind("plothover", function (event, pos, item) {
if (item){
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
console.log("x:" + x + ", " + "y:" + y);
}
});
Updated Fiddle here.
That's an internal function of flot, but you can easily recreate the same functionality yourself. All you need to do is iterate through the points in your data series and compare their location to your mouse pointer (Pythagoras should be able to help you here).
As for the reason why you see: ReferenceError: findNearbyItem is not defined see this.
Applying this little patch by hand will make function public.