calculated histogram doesn't look as expected - javascript

I'm trying to implement histogram RGB but my algorithm doesn't produce similarly look like surface as in graphics programs. For example image on this site:
OpenCV histogram
My version looks like:
As I understood it correctly, RGB Histogram just measuring how often each value occured in specific channel. So I implement it in such way:
public Process(layerManager: dl.LayerManager) {
var surface = layerManager.GetCurrent();
var components = new Uint8Array(1024);
surface.ForEachPixel((arr: number[], i: number): void => {
components[arr[i]] += 1;
components[arr[i + 1] + 256] += 1;
components[arr[i + 2] + 512] += 1;
components[arr[i + 3] + 768] += 1;
});
var histogram = layerManager.GetHistogram();
histogram.Clear();
var viewPort = layerManager.GetHistogramViewPort();
viewPort.Clear();
this.DrawColor(histogram, components, 0, new ut.Color(255, 0, 0, 255));
//histogram.SetBlendMode(ds.BlendMode.Overlay);
//this.DrawColor(histogram, components, 256, new ut.Color(0, 255, 0, 255));
//this.DrawColor(histogram, components, 512, new ut.Color(0, 0, 255, 255));
}
private DrawColor(surface: ds.ICanvas, components: Uint8Array, i: number, fillStyle: ut.Color) {
var point = new ut.Point(0, 255);
surface.BeginPath();
surface.FillStyle(fillStyle.R, fillStyle.G, fillStyle.B, fillStyle.A);
surface.RGBAStrokeStyle(fillStyle.R, fillStyle.G, fillStyle.B, fillStyle.A);
surface.LineWidth(1);
surface.MoveTo(point);
for (var j = i + 256; i < j; ++i) {
point = new ut.Point(point.X + 1, 255 - components[i]);
surface.ContinueLine(point);
}
surface.ClosePathAndStroke();
var viewPort = layerManager.GetHistogramViewPort();
viewPort.DrawImage(surface.Self<HTMLElement>(), 0, 0, 255, 255, 0, 0, viewPort.Width(), viewPort.Height());
}
Am I missing something?

You have a Uint8Array array to hold the results, but the most common RGB values are occurring more than 255 times. This causes an overflow and you end up seeing a histogram of the values modulo 256, which is effectively random for high values. That's why the left and middle parts of the graph (where values are less than 255) are correct, but the higher-valued areas are all over the place.
Use a larger data type to store the results, and normalize to the size of your output canvas before drawing.

Related

JavaScript TypedArray mixing types

I'm trying to use WebGL and would like to mix some different types into one buffer of bytes. I understand TypedArrays serve this purpose but it's not clear if I can mix types with them (OpenGL vertex data is often floats mixed with unsigned bytes or integers).
In my test I want to pack 2 floats into a UInt8Array using set(), but it appears to just place the 2 floats into the first 2 elements of the UInt8Array. I would expect this to fill the array of course since we have 8 bytes of data.
Is there anyway to achieve this in JavaScript or do I need to keep all my vertex data as floats?
src = new Float32Array(2); // 2 elements = 8 bytes
src[0] = 100;
src[1] = 200;
dest = new UInt8Array(8); // 8 elements = 8 bytes
dest.set(src, 0); // insert src at offset 0
dest = 100,200,0,0,0,0,0,0 (only the first 2 bytes are set)
You can mix types by making different views on the same buffer.
const asFloats = new Float32Array(2);
// create a uint8 view to the same buffer as the float32array
const asBytes = new Uint8Array(asFloats.buffer);
console.log(asFloats);
asBytes[3] = 123;
console.log(asFloats);
The way TypeArrays really work is there is something called an ArrayBuffer which is a certain number of bytes long. To view the bytes you need an ArrayBufferView of which there are various types Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array.
You can create the ArrayBuffer from scratch.
const buffer = new ArrayBuffer(8);
const asFloats = new Float32Array(buffer);
asFloats[0] = 1.23;
asFloats[1] = 4.56;
console.log(asFloats);
Or you can do the more normal thing which is to create an ArrayBufferView of a specific type and it will create both the ArrayBufferView of that type and create the ArrayBuffer for it as well if you don't pass one into the constructor. You can then access that buffer from someArrayBufferView.buffer as shown in the first example above.
You can also assign a view an offset in the ArrayBuffer and a length to make it smaller than the ArrayBuffer. Example:
// make a 16byte ArrayBuffer and a Uint8Array (ArrayBufferView)
const asUint8 = new Uint8Array(16);
// make a 1 float long view in the same buffer
// that starts at byte 4 in that buffer
const byteOffset = 4;
const length = 1; // 1 float32
const asFloat = new Float32Array(asUint8.buffer, byteOffset, length);
// show the buffer is all 0s
console.log(asUint8);
// set the float
asFloat[0] = 12345.6789
// show the buffer is affected at byte 4
console.log(asUint8);
// set a float out of range of its length
asFloat[1] = -12345.6789; // this is effectively a no-op
// show the buffer is NOT affected at byte 8
console.log(asUint8);
So if you want to for example mix float positions and Uint8 colors for WebGL you might do something like
// we're going to have
// X,Y,Z,R,G,B,A, X,Y,Z,R,G,B,A, X,Y,Z,R,G,B,A,
// where X,Y,Z are float32
// and R,G,B,A are uint8
const sizeOfVertex = 3 * 4 + 4 * 1; // 3 float32s + 4 bytes
const numVerts = 3;
const asBytes = new Uint8Array(numVerts * sizeOfVertex);
const asFloats = new Float32Array(asBytes.buffer);
// set the positions and colors
const positions = [
-1, 1, 0,
0, -1, 0,
1, 1, 0,
];
const colors = [
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
];
{
const numComponents = 3;
const offset = 0; // in float32s
const stride = 4; // in float32s
copyToArray(positions, numComponents, offset, stride, asFloats);
}
{
const numComponents = 4;
const offset = 12; // in bytes
const stride = 16; // in bytes
copyToArray(colors, numComponents, offset, stride, asBytes);
}
console.log(asBytes);
console.log(asFloats);
function copyToArray(src, numComponents, offset, stride, dst) {
const strideDiff = stride - numComponents;
let srcNdx = 0;
let dstNdx = offset;
const numElements = src.length / numComponents;
if (numElements % 1) {
throw new Error("src does not have an even number of elements");
}
for (let elem = 0; elem < numElements; ++elem) {
for(let component = 0; component < numComponents; ++component) {
dst[dstNdx++] = src[srcNdx++];
}
dstNdx += strideDiff;
}
}

Pixi.js - Draw Rectangle with Gradient Fill

I'm using the Pixi.js v4 graphics library to make a game with JavaScript. I know that I can draw a black + rounded rectangle like so:
const rectangle = new pixi.Graphics();
rectangle.beginFill(0); // Color it black
rectangle.drawRoundedRect(
0,
0,
100, // Make it 100x100
100,
5, // Make the rounded corners have a radius of 5
);
rectangle.endFill();
stage.addChild(rectangle);
How do I draw a rounded rectangle with a gradient from white to black?
How do I draw a rounded rectangle that has gradual opacity such that it fades in from left to right?
It looks like it's not possible to implement what you need with pixi.js without additional code, but we can do some magic to make it happen. Here's the result of what I've got: https://jsfiddle.net/exkf3zfo/21/
The bottom color is a pure red with 0.2 alpha.
I would split the whole process to the next steps:
Drawing the gradient
Masking the gradient with the rounded mask
Here is the code itself:
var app = new PIXI.Application(800, 600, {
antialias: true
});
document.body.appendChild(app.view);
// Functions
// param color is a number (e.g. 255)
// return value is a string (e.g. ff)
var prepareRGBChannelColor = function(channelColor) {
var colorText = channelColor.toString(16);
if (colorText.length < 2) {
while (colorText.length < 2) {
colorText = "0" + colorText;
}
}
return colorText;
}
// Getting RGB channels from a number color
// param color is a number
// return an RGB channels object {red: number, green: number, blue: number}
var getRGBChannels = function(color) {
var colorText = color.toString(16);
if (colorText.length < 6) {
while (colorText.length < 6) {
colorText = "0" + colorText;
}
}
var result = {
red: parseInt(colorText.slice(0, 2), 16),
green: parseInt(colorText.slice(2, 4), 16),
blue: parseInt(colorText.slice(4, 6), 16)
};
return result;
}
// Preparaiton of a color data object
// param color is a number [0-255]
// param alpha is a number [0-1]
// return the color data object {color: number, alpha: number, channels: {red: number, green: number, blue: number}}
var prepareColorData = function(color, alpha) {
return {
color: color,
alpha: alpha,
channels: getRGBChannels(color)
}
}
// Getting the color of a gradient for a very specific gradient coef
// param from is a color data object
// param to is a color data object
// return value is of the same type
var getColorOfGradient = function(from, to, coef) {
if (!from.alpha && from.alpha !== 0) {
from.alpha = 1;
}
if (!from.alpha && from.alpha !== 0) {
to.alpha = 1;
}
var colorRed = Math.floor(from.channels.red + coef * (to.channels.red - from.channels.red));
colorRed = Math.min(colorRed, 255);
var colorGreen = Math.floor(from.channels.green + coef * (to.channels.green - from.channels.green));
colorGreen = Math.min(colorGreen, 255);
var colorBlue = Math.floor(from.channels.blue + coef * (to.channels.blue - from.channels.blue));
colorBlue = Math.min(colorBlue, 255);
var rgb = prepareRGBChannelColor(colorRed) + prepareRGBChannelColor(colorGreen) + prepareRGBChannelColor(colorBlue);
return {
color: parseInt(rgb, 16),
alpha: from.alpha + coef * (to.alpha - from.alpha)
};
}
var startTime = Date.now();
console.log("start: " + startTime);
// Drawing the gradient
//
var gradient = new PIXI.Graphics();
app.stage.addChild(gradient);
//
var rect = {
width: 200,
height: 200
};
var round = 20;
//
var colorFromData = prepareColorData(0xFF00FF, 1);
var colorToData = prepareColorData(0xFF0000, 0.2);
//
var stepCoef;
var stepColor;
var stepAlpha;
var stepsCount = 100;
var stepHeight = rect.height / stepsCount;
for (var stepIndex = 0; stepIndex < stepsCount; stepIndex++) {
stepCoef = stepIndex / stepsCount;
stepColor = getColorOfGradient(colorFromData, colorToData, stepCoef);
gradient.beginFill(stepColor.color, stepColor.alpha);
gradient.drawRect(
0,
rect.height * stepCoef,
rect.width,
stepHeight
);
}
// Applying a mask with round corners to the gradient
var roundMask = new PIXI.Graphics();
roundMask.beginFill(0x000000);
roundMask.drawRoundedRect(0, 0, rect.width, rect.height, round);
app.stage.addChild(roundMask);
gradient.mask = roundMask;
var endTime = Date.now();
console.log("end: " + endTime);
console.log("total: " + (endTime - startTime));
The interesting thing is that it takes only about 2-5 ms for the whole process!
If you wan't to change colors of the gradient to white>black (as described in the question), just change the next params:
var colorFromData = prepareColorData(0xFF00FF, 1);
var colorToData = prepareColorData(0xFF0000, 0.2);
To:
var colorFromData = prepareColorData(0xFFFFFF, 1);
var colorToData = prepareColorData(0x000000, 0.2);
Not full answer but some extra information
As far I know, you can't use gradient for PIXI.Graphics even for sprites you need extra canvas
Just draw the gradient you want to a canvas:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient
Then use that canvas as a texture: Texture.fromCanvas(canvas);
Look at this article.
For gradual opacity, Alpha Mask can help
http://pixijs.io/examples/#/demos/alpha-mask.js
P.S Maybe phaser.js can do more
Did you ever figure this out? I couldn't find a solution online either, so I implemented it myself using a filter. Have a look: https://codepen.io/Lancer611/pen/KodabK.
Some of the pixi code:
function newGradientPoly(poly, fill, fillSize){
var container = new PIXI.Sprite();
app.stage.addChild(container);
var shape = new PIXI.Graphics();
shape.beginFill(0xffffff)
.lineStyle(1, 0x333333)
.drawPolygon(poly);
var mask = new PIXI.Graphics();
mask.beginFill(0xffffff, 1)
.drawPolygon(poly);
container.mask = mask;
container.addChild(shape);
var fshaderCode = document.getElementById("fragShader").innerHTML;
fogShader = new PIXI.Filter(null, fshaderCode);
fogShader.uniforms.resolution = [width, height];
fogShader.uniforms.segments = poly.slice();
fogShader.uniforms.count = poly.length/2;
fogShader.uniforms.gSize = fillSize;
fogShader.uniforms.fill = fill;
shape.filters=[fogShader];
}
I've created a pixi plugin for displaying vector drawings in Pixi. The main limitation is that you need to draw your rectangle in the vector art program Omber first, so you need to know the size of your rectangle beforehand (since everything is vector-based, you could theoretically scale things later, but then the rounded corners would end up being a little uneven). The workflow is similar to using sprites: 1. draw your rectangles in Omber 2. export them to gltf 3. load the gltf files in your Pixi program 4. position the rectangles where you want them.
Another possibility is that you could create the gradient as a separate object, and then you can mask it out with a polygon. Here's an example. In that example, I'm using a vector drawing for the gradient, but since gradients don't become blurry when resized, you could probably use a sprite for that as well. I'm not sure if masks have good performance, but if you just need a few of them, then it's probably fine.

Adding up values of nested objects

I have an object which contains multiple objects. Each object has a height and a width, which I need to add together to get a total height and width. I need to update the totals on input from the user.
Object:
$scope.myObj = {
wall1: {
wFeet: 0,
wInches: 0,
hFeet: 0,
hInches: 0,
totalWidth: 0,
totalHeight: 0
},
wall2: {
wFeet: 0,
wInches: 0,
hFeet: 0,
hInches: 0,
totalWidth: 0,
totalHeight: 0
},
wall3: {
wFeet: 0,
wInches: 0,
hFeet: 0,
hInches: 0,
totalWidth: 0,
totalHeight: 0
}
};
Right Now I have a function that takes the feet and inches values, converts to decimal feet and adds them up to give the total width and height for each wall.
$scope.setTotalWidthAndHeight = function() {
angular.forEach($scope.walls, function(wall) {
//first convert inches to decimal of ft
angular.forEach(wall, function(dim, dimKey) {
if(dimKey === 'wInches') {
wall.wallWidth = wall.wFeet + (0.0833 * dim);
}
if(dimKey === 'hInches') {
wall.wallHeight = wall.hFeet + (0.0833 * dim);
}
})
});
};
What's Im having a problem with now is adding up all the totalWidth and totalHeight values from each object to get one final width and height for all walls combines. There has to be a better way to do it than below.
For example:
var allTotalWidths = $scope.myObj.wall1.totalWidth + $scope.myObj.wall2.totalWidth + $scope.myObj.wall3.totalWidth;
Your function can be optimised a little and I'm going to assume where you've currently got wall.wallWidth = and wall.wallHeight = you meant to have wall.totalWidth = and wall.totalHeight = as the previous properties don't exist in your example data and will have likely thrown an error.
var totalWidths = 0,
totalHeights = 0;
$scope.setTotalWidthAndHeight = function()
{
angular.forEach($scope.walls, function(wall)
{
wall.totalWidth = wall.wFeet + (0.0833 * wall.wInches);
wall.totalHeight = wall.hFeet + (0.0833 * wall.hInches);
totalWidths += wall.totalWidth;
totalHeights += wall.totalHeight;
});
};
I've altered your function to do all the totalling in one swoop. It will populate the totalWidth/Height properties of your initial object and also keep a running total of all widths and heights in the totalWidths and totalHeights variables.

Javascript - Array Assignment

I am currently taking a course on Javascript at Khan Academy and Im having some trouble with one of the assignments. I have posted the question there, but I have noticed that there is less volunteers willing to help there, so I thought I`d ask here.
I have an Assignment on JS Arrays ( https://www.khanacademy.org/computing/computer-programming/programming/arrays/p/project-make-it-rain ) with the following requirements:
To make an animation of rain, it's best if we use arrays to keep track of the drops and their different properties.
Start with this simple code and build on it to make a cool rain animation. Here are some ideas for what you could do:
Add more drops to the arrays.
Make it so that the drops start back at the top once they've reached the bottom, using a conditional.
Make an array of colors, so that every drop is a different color.
Make other things rain, like snowflakes (using more shape commands) or avatars (using the image commands).
Make it so that when the user clicks, a new drop is added to the array.
Initialize the arrays using a for loop and random() function, at the beginning of the program.
Question 1)
I've got it to use a random colour when the raindrop is called, but it overwrites the previous drop's colour if you call it before the previous drop goes off screen. I've tried moving the fill function outside the loop, and around the loop to no avail. Can anyone give me some insight on this? What am I doing wrong?
Question 2)
I've got a conditional (if/else) to make the raindrop start back at the top, but it drops much slower the second time, and only repeats once. Having trouble figuring out the logic of why this is happening in order to "debug" it.
Current code:
var xPositions = [100];
var yPositions = [0];
var colors = [
color(255, 0, 0),
color(255, 128, 0),
color(255, 255, 0),
color(0, 255, 0),
color(0, 0, 255),
color(128, 0, 255)
];
background(204, 247, 255);
fill(colors[Math.floor(Math.random() * colors.length)]);
// Raindrops (random color)
draw = function() {
background(204, 247, 255);
for (var i = 0; i < xPositions.length; i++) {
if (yPositions[i] < 400) { // if the raindrop hasnt hit the bottom
noStroke();
ellipse(xPositions[i], yPositions[i], 10, 10);
yPositions[i] += 5;
} else { // when it hits the bottom, set the yPositions variable to 0 and restart
ellipse(xPositions[i], yPositions.push(0), 10, 10);
yPositions[i] += 5;
}
}
};
var mouseClicked = function() {
xPositions.push(mouseX);
yPositions.push(mouseY);
fill(colors[Math.floor(Math.random() * colors.length)]);
draw();
};
Question 1)
You need to make a fill call for each raindrop that is drawn, per iteration of the for loop inside draw. For a raindrop to maintain its color as it falls (between draw calls) you need to store its color in an additional array, and initialize the corresponding color when you create new drops.
Question 2)
Simply reset the y value in the y array to make the drop start over. I'm not sure what the ellipse call was doing in your code - see below.
// initial raindrop values
var xPositions = [100];
var yPositions = [0];
var colors = [
color(255, 0, 0),
color(255, 128, 0),
color(255, 255, 0),
color(0, 255, 0),
color(0, 0, 255),
color(128, 0, 255)
];
// initialize the first raindrop to a random color
var dropColors = [colors[Math.floor(Math.random() * colors.length)]];
background(204, 247, 255);
draw = function() {
background(204, 247, 255);
for (var i = 0; i < xPositions.length; i++) {
if (yPositions[i] < 400) { // if the raindrop hasnt hit the bottom
noStroke();
// set the fill color for this drop
fill(dropColors[i]);
ellipse(xPositions[i], yPositions[i], 10, 10);
yPositions[i] += 5;
} else { // when it hits the bottom, set the yPositions variable to 0
yPositions[i] = 5;
}
}
};
var mouseClicked = function() {
xPositions.push(mouseX);
yPositions.push(mouseY);
dropColors.push(colors[Math.floor(Math.random() * colors.length)]);
draw();
};

CSS matrix calculation

Been trying to sort this out for a few days and I am not sure if the CSS matrix is different from standard graphics matrices, or if I have something wrong (likely I have something wrong).
I am primarily trying to figure out how to rotate on the X and Y axis. When I use "transform: rotateX(2deg) rotateY(2deg) translate3d(0px, -100px, 0px);" and I use javascript to grab the matrix style, this is what I am able to output.
0.9993908270190958, -0.001217974870087876, -0.03487823687206265, 0,
0, 0.9993908270190958, -0.03489949670250097, 0,
0.03489949670250097, 0.03487823687206265, 0.9987820251299122, 0,
0, -99.93908270190957, 3.489949670250097, 1
But if I try to calculate the matrix using javascript (with 2 degrees on both X and Y) I get
0.9993908270190958, 0, -0.03489949670250097, 0,
-0.001217974870087876, 0.9993908270190958, -0.03487823687206265, 0,
0.03487823687206265, 0.03489949670250097, 0.9987820251299122, 0,
0.1217974870087876, -99.93908270190957, 3.487823687206265, 1
Now while several numbers are different in the second one, I believe one number is causing the problem. Note the numbers in row 1/column 2 and in row 2/column 1, for both matrices. The "-0.001217974870087876" looks to be switched. And if I understand how everything is calculated that is likely throwing off all the other numbers.
Here's the code I am using to create the second matrix
var basematrix = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, -100, 0, 1]
];
function RotateWorld(y, x)
{
var halfrot = Math.PI / 180;
var xcos = Math.cos(x * halfrot);
var xsin = Math.sin(x * halfrot);
var ycos = Math.cos(y * halfrot);
var ysin = Math.sin(y * halfrot);
var ymatrix = [
[ycos, 0, -ysin, 0],
[0, 1, 0, 0],
[ysin, 0, ycos, 0],
[0, 0, 0, 1]
];
var xmatrix = [
[1, 0, 0, 0],
[0, xcos, xsin, 0],
[0, -xsin, xcos, 0],
[0, 0, 0, 1]
];
var calcmatrix = MatrixMultiply(ymatrix, basematrix);
calcmatrix = MatrixMultiply(xmatrix, calcmatrix);
calcmatrix = TransMultiply(calcmatrix);
for (var i = 0; i < 4; i++)
{
for (var j = 0; j < 4; j++)
{
document.getElementById('info').innerHTML += calcmatrix[i][j] + ', ';
}
}
}
function MatrixMultiply(matrixa, matrixb)
{
var newmatrix = [];
for (var i = 0; i < 4; ++i)
{
newmatrix[i] = [];
for (var j = 0; j < 4; ++j)
{
newmatrix[i][j] = matrixa[i][0] * matrixb[0][j]
+ matrixa[i][1] * matrixb[1][j]
+ matrixa[i][2] * matrixb[2][j]
+ matrixa[i][3] * matrixb[3][j];
}
}
return newmatrix;
}
function TransMultiply(matrix)
{
var newmatrix = matrix;
var x = matrix[3][0];
var y = matrix[3][1];
var z = matrix[3][2];
var w = matrix[3][3];
newmatrix[3][0] = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0];
newmatrix[3][1] = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1];
newmatrix[3][2] = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2];
newmatrix[3][3] = x * matrix[0][3] + y * matrix[1][3] + z * matrix[2][3] + newmatrix[3][3];
if (newmatrix[3][3] != 1 && newmatrix[3][3] != 0)
{
newmatrix[3][0] = x / w;
newmatrix[3][1] = y / w;
newmatrix[3][2] = z / w;
}
return newmatrix;
}
My code is a bit verbose as I am just trying to learn how to work with the CSS matrix. But hopefully someone can help me get that one number into the right place.
Edit
I hate to bump a post but I am running out of places to ask, so I am hoping a few more people will see it with a chance of getting an answer. I have tried every possible search to figure this out (unique questions don't get ranked very high in Google). I have probably read over 20 articles on working with matrices and they are yielding nothing. If I need to add more information please let me know. Also if there is a better place to ask let me know that as well. I would assume by now several people have looked at the code and the code must be ok, maybe my assumption that CSS is the culprit is a possibility, if so how does one track that down?
Take a look at this page, it explains how css 3dmatrix work. Also here you have an implementation in JS of CSSMatrix object, very similar to WebKitCSSMatrix which is already included in your (webkit) browser for your use.
You have a bug in your implementation of function TransMultiply(matrix) { .. }
var newmatrix = matrix;
That isn't cloning your matrix, that's setting newmatrix to refer to your original matrix! Anything using this method is going to have the original matrix and new matrix messed up. You might want to use a method that creates new 4x4 matricies, like:
function new4x4matrix(){
return [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]];
}
and then wherever you need a new matrix, do:
var newmatrix = new4x4matrix();
Edit: err, but you may actually need a clone method: fine.
function cloneMatrix(matrixa)
{
var newmatrix = [];
for (var i = 0; i < 4; ++i)
{
newmatrix[i] = [];
for (var j = 0; j < 4; ++j)
{
newmatrix[i][j] = matrixa[i][j];
}
}
return newmatrix;
}
and instead, for TransMultiply do:
var newmatrix = cloneMatrix(matrix);

Categories