But as soon as i leave out the drawImage part and substitute it with putImageData i previously created (remember, i have a dynamically generated thing, it's only on canvas, not in an Image object that i could use for drawImage), it stops scaling! I'm back to the big, 100% scaled image.
PLEASE help me out with this, these canvas and their logic are driving me nuts!!!!
P.S. Also, why do we save the state before making any changes, then restore the state after the changes, and somehow still see the changes made??? Shouldn't the restore() method revert to the state before any changes were made??
I'm eagerly awaiting for anyone to shed some light on this
I don't claim to be an expert on Canvas, but I think we can figure it out. ;-)
Regarding putImageData, it would be easier for me to understand what the problem is if you had a link so I could see how you're using it. It's a little hard to answer that otherwise.
Your question about save state / restore state has to do with the behavior of Canvas. When you transform the canvas without clearing it and redrawing it, the canvas remains the same and new changes are placed on top of it. In other words, if you took out the save/clear/restore lines, and made the code look like the following, you would see duplicate copies of the image on top of one another:
In that case, changing the parameters of the setTransform method would duplicate the canvas view in addition to modifying it.
The way to work around this is, of course, to save the canvas context in its current state (which is why we start with the save() method), clear what is currently visible on the canvas (clearRect()), perform our transformation operation, and then when we're done, restore the canvas state (restore()). The save/restore methods don't actually clear/restore the output of the canvas itself (that's what drawImage does); however, they do provide state-change information (the "context" as it were), which is important for a program that will be interacting with the canvas (particularly for optimizing redraws and the creation of new paths after they have been filled or stroked). Essentially, the transformations performed on the canvas are cumulative, and therefore each call saves and restores the canvas state. Does that help any?
Visit Slightly Remarkable to see my portfolio, resumé, and consulting rates.
thank you so much for explaining canvas to me! my biggest mistake was that i thought that the save() and restore() methods saved/restored the pixel data of canvas. now i understand that, apparently, they save/restore the, er, attributes of canvas, such as the transform arguments.
however, now it seems clearer to me that the resize trick may be impossible to implement at all.
i have put together a small example: http://gda.0fees.net/tests/test01.php
function resize1() works just great, but it redraws the image from a static source. this is not what i need
function resize2() calls putImageData(), and apparently this method disregards the transformed state of canvas...
P. S. sorry i'm so slow. i received the notification about your answer immediately, but things have been keeping me really busy lately...
Update:
i have found a workaround that uses the drawImage function. it's kinda dodgy though.
Code:
var tempImage = new Image;
/* draw something on the canvas here */
tempImage.src = $("tc").toDataURL("image/png");
$("tc").getContext("2d").clearRect(0, 0, 604, 339);
$("tc").getContext("2d").drawImage(tempImage, 0, 0, 302, 170)
This does scale the image inside the canvas to 50%, but it's not exactly lightning fast. in fact, it appears to be several times slower than using putImageData() (which doesn't work, however).
I only wonder whether i will have any speed boost if i say screw it and implement bicubic interpolation of the imageData array
Then it will always draw the original image, as contained in the file.
Sorry that my example page doesn't reflect it, but instead of drawing a PNG file there actually should be drawing some graphs and stuff rendered in real time. I can't fetch it from a file, it's content created on the fly.
And also i apologize that i can't post what exactly i'm working with and need to show this by way of example pages - my work is slightly confidential as of now
The image being drawn to the canvas is pixel data, so you're going to want to operate on that before drawing it to the canvas, rather than drawing it to the canvas and then performing your operations.
In the following example code, you can reference imgD.data to modify the pixel data directly.
Here's a very simplified example that increases the exposure (contrast) of the image.
Code:
var ctx = $('tc').getContext('2d');
ctx.save();
ctx.clearRect(0, 0, 604, 339);
ctx.drawImage($('ti'), 0, 0, 604, 339);
var imgD = ctx.getImageData(0, 0, 604, 339);
// this loop should be extracted to a separate function
for (var x = 0; x < imgD.data.length; x++){
imgD.data[x] = imgD.data[x] << 2;
}
ctx.putImageData(imgD, 0, 0);
ctx.restore();
Visit Slightly Remarkable to see my portfolio, resumé, and consulting rates.
Bookmarks