I have a javascript that allows a user to choose different images and then places them together using layers. They can see the design they did on the side. I am trying to figure out how to merge all the layers down to one image so they can download the image.
Here is the test I am working on.
http://www.theavatar...test/index.html
You see the image on the right. It is still in layers so if they try to right click and save as they only get the top layer.
How can I flatten or merge them down to one complete image?
1 reply to this topic
#1
Posted 06 May 2011 - 10:17 PM
|
|
|
#2
Posted 08 May 2011 - 02:48 AM
This won't be easy without a server side language like java, any .net language or php.
It IS possible tho.
result.jpg 39.96K
13 downloads
^image there
(note: the neck is a bit wrong there, In the following code I replaced alpha check by 125, I took this screenshot when it was 20)
Requirements:
First of all, here is the full code I wrote.
The first 4 lines of the javascript are simple. Just create 2 image objects, and set their source.
Then the canvasses kick in. I premade 3 canvas tags, 1 for chest, 1 for head, and 1 for both combined.
I just get their context and paint the images on the head and chest canvas. Then get their data.
The data are pixels.. but 1 pixel is represented by 4 entries.
By which I mean, that if you had an image of 2x2, 4 pixels total, the array will have a length of 16.
Because the array has these values:
[ {Red value pixel1}, {Green value pixel1}, {Blue value pixel1}, {Alpha value pixel1},
{Red value pixel2}, {Green value pixel2}, {Blue value pixel2}, {Alpha value pixel2},
{Red value pixel3}, {Green value pixel3}, {Blue value pixel3}, {Alpha value pixel3},
{Red value pixel4}, {Green value pixel4}, {Blue value pixel4}, {Alpha value pixel4}]
Note I've put enters here, it's no 2D array.
Next I get the resulting canvas, which will contain the 2 combined images. I don't get its pixels in 1 step
like I did with the previous canvasses, because I need the resultData variable later.
1 step to go from context to pixels:
And then I transfer the pixels from head and chest to the result:
If it's an alpha value, AND it has a value of less than 125, (meaning it's less than 50%visible) I don't paint the head, but take the chest instead.
When all is done. I pain the result on the canvas:
That's why I've put an image tag there, and use the canvas' data to fill the image:
Note that my if-statement of alpha less than 125 is actually pretty... simple and basic.
If you wanted both images to be merged smoothly you'll have to work with the alpha values more and don't take the color from A or B, but create a new color based on color A, color B, and A's alpha and B's alpha.
I suggest you google for "merge 2 colors with alpha values" or somehting like that :P
(You may also want to post in the Javascript instead of Java section next time)
It IS possible tho.
result.jpg 39.96K
13 downloads^image there
(note: the neck is a bit wrong there, In the following code I replaced alpha check by 125, I took this screenshot when it was 20)
Requirements:
- recent browser version so it supports the <canvas> element
- A brain to handle the pixel thinking ;)
First of all, here is the full code I wrote.
<html>
<head>
<script type="text/javascript">
function processImage(){
var chest = new Image();
chest.src = 'chest.png';
var head = new Image();
head.src = 'head.png';
var chestContext = document.getElementById('chestCanvas').getContext('2d');
chestContext.drawImage(chest, 0, 0);
chestPixels = chestContext.getImageData(0, 0, 120, 120).data;
var headContext = document.getElementById('headCanvas').getContext('2d');
headContext.drawImage(head, 0, 0);
headPixels = headContext.getImageData(0, 0, 120, 120).getImageData(0, 0, 120, 120).data;
var resultContext = document.getElementById('result').getContext('2d');
var resultData = resultContext.getImageData(0, 0, 120, 120);
var resultPixels = resultData.data;
for (var i=0 ; i < headPixels.length ; i++) {
if(!((i+1)%4==0 && headPixels[i]<20)){
resultPixels[i]=headPixels[i];
} else {
resultPixels[i-3]=chestPixels[i-3];
resultPixels[i-2]=chestPixels[i-2];
resultPixels[i-1]=chestPixels[i-1];
resultPixels[i]=chestPixels[i];
}
}
resultContext.putImageData(resultData, 0, 0);
var image = document.getElementById('final');
image.src = document.getElementById('result').toDataURL();
}
</script>
</head>
<body>
<canvas id="chestCanvas"></canvas>
<canvas id="headCanvas"></canvas>
<canvas id="result"></canvas>
<input type="button" onClick="javascript:processImage();" value="click"/>
<img id="final" />
</body>
</html>
The first 4 lines of the javascript are simple. Just create 2 image objects, and set their source.
Then the canvasses kick in. I premade 3 canvas tags, 1 for chest, 1 for head, and 1 for both combined.
I just get their context and paint the images on the head and chest canvas. Then get their data.
The data are pixels.. but 1 pixel is represented by 4 entries.
By which I mean, that if you had an image of 2x2, 4 pixels total, the array will have a length of 16.
Because the array has these values:
[ {Red value pixel1}, {Green value pixel1}, {Blue value pixel1}, {Alpha value pixel1},
{Red value pixel2}, {Green value pixel2}, {Blue value pixel2}, {Alpha value pixel2},
{Red value pixel3}, {Green value pixel3}, {Blue value pixel3}, {Alpha value pixel3},
{Red value pixel4}, {Green value pixel4}, {Blue value pixel4}, {Alpha value pixel4}]
Note I've put enters here, it's no 2D array.
Next I get the resulting canvas, which will contain the 2 combined images. I don't get its pixels in 1 step
like I did with the previous canvasses, because I need the resultData variable later.
1 step to go from context to pixels:
chestPixels = chestContext.getImageData(0, 0, 120, 120).data;2 steps:
var resultData = resultContext.getImageData(0, 0, 120, 120); var resultPixels = resultData.data;
And then I transfer the pixels from head and chest to the result:
for (var i=0 ; i < headPixels.length ; i++) {
if(!((i+1)%4==0 && headPixels[i]<125)){
resultPixels[i]=headPixels[i];
} else {
resultPixels[i-3]=chestPixels[i-3];
resultPixels[i-2]=chestPixels[i-2];
resultPixels[i-1]=chestPixels[i-1];
resultPixels[i]=chestPixels[i];
}
}
if(!((i+1)%4==0 && headPixels[i]<125)){
resultPixels[i]=headPixels[i];
}
Remember how the array was built up? Every 4th element is the alpha value, that's what I test here.If it's an alpha value, AND it has a value of less than 125, (meaning it's less than 50%visible) I don't paint the head, but take the chest instead.
else {
resultPixels[i-3]=chestPixels[i-3];
resultPixels[i-2]=chestPixels[i-2];
resultPixels[i-1]=chestPixels[i-1];
resultPixels[i]=chestPixels[i];
}
Since i'm now at position 4, the Red, green and blue values are at i-1, i-2, and i-3. I must copy those too.When all is done. I pain the result on the canvas:
resultContext.putImageData(resultData, 0, 0);Now the user can't right click on a canvas and choose save as.
That's why I've put an image tag there, and use the canvas' data to fill the image:
var image = document.getElementById('final');
image.src = document.getElementById('result').toDataURL();
Now the user can right click and save as.Note that my if-statement of alpha less than 125 is actually pretty... simple and basic.
If you wanted both images to be merged smoothly you'll have to work with the alpha values more and don't take the color from A or B, but create a new color based on color A, color B, and A's alpha and B's alpha.
I suggest you google for "merge 2 colors with alpha values" or somehting like that :P
(You may also want to post in the Javascript instead of Java section next time)
Edited by wim DC, 08 May 2011 - 04:49 AM.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users


Sign In
Create Account


Back to top









