Reputation: 2551
i am trying to merge two textures into one in unity
the first texture is from a webcamTexture
the second is from a sprite using : gameobject.getComponent<SpriteRenderer>().sprite.texture as Texture2D
I'm having problem in writing the function this is what i did so far :
public static Texture2D CombineTextures(GameObject obj, Texture2D background, Texture2D TodrawLogo)
{
Vector3 v = obj.transform.position;// obj is TodrawLogo gameobject
int width = TodrawLogo.width;
int height = TodrawLogo.height;
for (int x =(int)v.x; x < width; x++){
background.SetPixel(x,(int)v.y,TodrawLogo.GetPixel(x,(int)v.y));
}
background.Apply();
return background;
}
this what i am trying to do :
WebcamTexture
the result Texture should be like this
the webcamTexture is a 3dplane
and the logo is a single sprite
but sadly my function doesn't work
does anyone know how to fix this
I know that i should find the exact coordinate of the todraw image
and set the pixels but i can't figure out how
Much appreciation
EDIT:
i tried to use @nexx code :
public static Texture2D CombineTexture(Texture2D background, Texture2D TodrawLogo)
{
int width = TodrawLogo.width;
int height = TodrawLogo.height;
int backWidth = background.width;
int backHeight = background.height;
// bottom right corner
int startX = backWidth - width;
int startY = backHeight - height;
// loop through texture
int y = 0;
while (y < backHeight) {
int x = 0;
while (x < backWidth) {
// set normal pixels
background.SetPixel(x,y,background.GetPixel(x,y));
// if we are at bottom right apply logo
//TODO also check alpha, if there is no alpha apply it!
if(x >= startX && y < backHeight- startY)
background.SetPixel(x,y,TodrawLogo.GetPixel(x-startX,y-startY));
++x;
}
++y;
}
background.Apply();
return background;
}
but this is the resulting image i get :
i am stuck at this can someone please tell me what am i doing wrong ?
Upvotes: 4
Views: 28216
Reputation: 11
A slightly more optimized solution. Reading and writing only the area required for the watermark.
public static Texture2D AddWatermark(Texture2D background, Texture2D watermark, int startPositionX, int startPositionY)
{
//only read and rewrite the area of the watermark
for (int x = startPositionX; x < background.width; x++)
{
for (int y = startPositionY; y < background.height; y++)
{
if (x - startPositionX < watermark.width && y - startPositionY < watermark.height)
{
var bgColor = background.GetPixel(x, y);
var wmColor = watermark.GetPixel(x - startPositionX, y - startPositionY);
var finalColor = Color.Lerp(bgColor, wmColor, wmColor.a / 1.0f);
background.SetPixel(x, y, finalColor);
}
}
}
background.Apply();
return background;
}
Upvotes: 1
Reputation: 11
This code works perfectly with two images that are not the same size
public static Texture2D AddWatermark(Texture2D background, Texture2D watermark, int startX, int startY)
{
Texture2D newTex = new Texture2D(background.width, background.height, background.format, false);
for (int x = 0; x < background.width; x++)
{
for (int y = 0; y < background.height; y++)
{
if (x >= startX && y >= startY && x < watermark.width && y < watermark.height)
{
Color bgColor = background.GetPixel(x, y);
Color wmColor = watermark.GetPixel(x - startX, y - startY);
Color final_color = Color.Lerp(bgColor, wmColor, wmColor.a / 1.0f);
newTex.SetPixel(x, y, final_color);
}
else
newTex.SetPixel(x, y, background.GetPixel(x, y));
}
}
newTex.Apply();
return newTex;
}
Upvotes: 1
Reputation: 136
Here's a working example. I tested!
public Texture2D AddWatermark(Texture2D background, Texture2D watermark)
{
int startX = 0;
int startY = background.height - watermark.height;
for (int x = startX; x < background.width; x++)
{
for (int y = startY; y < background.height; y++)
{
Color bgColor = background.GetPixel(x, y);
Color wmColor = watermark.GetPixel(x - startX, y - startY);
Color final_color = Color.Lerp(bgColor, wmColor, wmColor.a / 1.0f);
background.SetPixel(x, y, final_color);
}
}
background.Apply();
return background;
}
Upvotes: 12
Reputation: 1035
Try this (its a modification of nexx's code.) It combines two textures into a new texture. The new texture is guarenteed to be writable (otherwise SetPixel/GetPixel won't work.)
Also, it assumes that the watermark texture is smaller than the background texture.
Please note: I've not tested this.
public static Texture2D AddWatermark(Texture2D background, Texture2D watermark)
{
// Create a new writable texture.
Texture2D result = new Texture2D(background.width, background.height);
// Draw watermark at bottom right corner.
int startX = background.width - watermark.width;
int startY = background.height - watermark.height;
for (int x = 0; x < background.width; x++) {
for (int y = 0; y < background.height; y++) {
Color bgColor = background.GetPixel(x, y);
Color wmColor = new Color(0, 0, 0, 0);
// Change this test if no longer drawing at the bottom right corner.
if (x >= startX && y >= startY) {
wmColor = watermark.GetPixel(x, y);
}
// Alpha-blend background and watermark color.
Color bended = bgColor * (1.0f - wmColor.a) + wmColor;
blended.a = 1.0f;
result.SetPixel(x, y, blended);
}
}
result.Apply();
return result;
}
Upvotes: 0
Reputation: 125
I don't know how you would like to do it but you can use unity's OnGUI method to draw the logo where needed.
http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnGUI.html
Its as simple as something like this:
var aTexture : Texture;
function OnGUI() {
if(!aTexture){
Debug.LogError("Assign a Texture in the inspector.");
return;
}
GUI.DrawTexture(Rect(10,10,60,60), aTexture, ScaleMode.ScaleToFit, true, 10.0f);
}
I hope i was helpful.
Upvotes: 0
Reputation: 579
I made some changes for your CombineTextures
method,
public static Texture2D CombineTexture(GameObject obj, Texture2D background, Texture2D TodrawLogo)
{
int width = TodrawLogo.width;
int height = TodrawLogo.height;
int backWidth = background.width;
int backHeight = background.height;
// bottom right corner
int startX = backWidth - width;
int startY = backHeight - height;
// loop through texture
int y = 0;
while (y < backHeight) {
int x = 0;
while (x < backWidth) {
// set normal pixels
background.SetPixel(x,y,background.GetPixel(x,y));
// if we are at bottom right apply logo
//TODO also check alpha, if there is no alpha apply it!
if(x >= startX && y < backHeight- startY)
background.SetPixel(x,y,TodrawLogo.GetPixel(x-startX,y-startY));
++x;
}
++y;
}
background.Apply();
return background;
}
You can change the values inside while loop to place your texture where you want.
Upvotes: 0