Reputation: 18198
I am trying to break a spritesheet and well, it's not putting it into a 2D array like it should. At the end of my code, near the console.log, it spits out ImageData...but when it tries to putImageData... I get Uncaught TypeError: Type error
Help?
and here's my code:
$(document).ready(function () {
console.log("Client setup...");
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.tabIndex = 0;
canvas.focus();
console.log("Client focused.");
var imageObj = new Image();
imageObj.src = "./images/all_tiles.png";
imageObj.onload = function() {
context.drawImage(imageObj, imageWidth, imageHeight);
};
var allLoaded = 0;
var tilesX = ImageWidth / tileWidth;
var tilesY = ImageHeight / tileHeight;
var totalTiles = tilesX * tilesY;
var tileData = [totalTiles]; // Array with reserved size
for(var i=0; i<tilesY; i++)
{
for(var j=0; j<tilesX; j++)
{
// Store the image data of each tile in the array.
tileData.push(context.getImageData(j*tileWidth, i*tileHeight, tileWidth, tileHeight));
allLoaded++;
}
}
if (allLoaded == totalTiles) {
console.log("All done: " + allLoaded);
console.log(tileData[1]);
context.putImageData(tileData[0], 0 ,0); // Sample paint
}
});
error happens at context.putImageData(tileData[0], 0 ,0); // Sample paint
Here is example fiddle of code above http://jsfiddle.net/47XUA/
Upvotes: 2
Views: 12188
Reputation: 89
I'm using Chrome.
context.drawImage(spritesheet.image, 0, 0, 4608, 768);// Works
context.drawImage(spritesheet.image, 768, 0, 768, 768, 4608, 768); // Doesn't work: Uncaught TypeError: Type error
Thank you!
Upvotes: 0
Reputation: 116030
Your problem is that the first element of tileData
is not an ImageData
object, it's a plain number! When you initialized your array you used:
var tileData = [totalTiles];
This means that tileData[0]
is equal to the value of totalTiles
, which is the number 483
. You are providing a number instead of an ImageData
object to putImageData
, and the browser is throwing an error in confusion. If you look at any other element in the rest of your array, you'll see it is successfully being populated with ImageData
objects as you expect; only the first element in the array is a number.
You probably meant to do:
var tileData = new Array(totalTiles);
which would create an array with the specified length
property, instead of setting the first value in the array to a number. Personally, I would run some performance tests to see if that is even useful; you may be just as well using var tileData = [];
Upvotes: 4
Reputation: 31
A type error is caused when a variable or object passed into a statement is not of a type that is expected for that command and can’t be converted into something that is valid.
See here for a full definition of the error.
So most likely that context or tileData is in an incorrect format or is null or undefined
Upvotes: 3
Reputation: 18858
The problem here is that the imageObj.onload()
function is being called AFTER the rest of the script is executed.
This means that queries to getImageData()
are returning undefined, as there is no image data in the canvas when called.
A simple way to fix this is to encapuslate the remaining script in the imageObj.onload
function, like so:
$(document).ready(function () {
console.log("Client setup...");
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.tabIndex = 0;
canvas.focus();
console.log("Client focused.");
var imageObj = new Image();
imageObj.src = "./images/all_tiles.png";
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
var allLoaded = 0;
var tilesX = imageWidth / tileWidth;
var tilesY = imageHeight / tileHeight;
var totalTiles = tilesX * tilesY;
var tileData = new Array(); // Array with NO reserved size
for(var i=0; i<tilesY; i++)
{
for(var j=0; j<tilesX; j++)
{
// Store the image data of each tile in the array.
tileData.push(context.getImageData(j*tileWidth, i*tileHeight, tileWidth, tileHeight));
allLoaded++;
}
}
context.putImageData(tileData[0], 0 ,0); // Sample paint
}; // End 'imageObj.onload()' scope.
}); // End document ready function scope.
This ensures that any calls to getImageData()
are made after context.drawImage()
You may also have a problem here that you are not drawing the image to cover the canvas. Change the line:
context.drawImage(imageObj, imageWidth, imageHeight);
to
context.drawImage(imageObj, 0, 0);
EDIT: You also had ImageWidth
and imageWidth
(same for height). Rename these.
EDIT: Reserving the Array size here with new Array(totalTiles)
was causing an issue. When we pushed new tile images to the array, it pushed to the end of the pre-allocated array (starting at tileData[totalTiles]
). This is easily fixed by removing the size argument. Otherwise instead of using push()
we could copy the image data into the array in a loop, eg: tileData[n] = getImageData(...)
, starting at tileData[0]
.
Upvotes: 0
Reputation: 16584
It might be a racing condition. You are using drawImage only when the image ./images/all_tiles.png
has been loaded. But you are using the image data on the context before the onload fired. Try to move everything which is after the onload handler into the onload handler.
Upvotes: 0