I have a gallery scene and I want to load PNG's from Persistence path .
The thing is that I want them as thumbnails, theirs no need for me to load the full size file .
How can I defined the scale of the sprite?
that the relevant line for the creating of the sprite:
Sprite sp1 = Sprite.Create(texture1, new Rect(0, 0, texture1.width, texture1.height), new Vector2(0.5f, 0.5f), 100, 0, SpriteMeshType.FullRect);
and that the texture creating code:
Texture2D takeScreenShotImage(string filePath)
{
Texture2D texture = null;
byte[] fileBytes;
if (File.Exists(filePath))
{
fileBytes = File.ReadAllBytes(filePath);
texture = new Texture2D(1, 1, TextureFormat.ETC2_RGB, false);
texture.LoadImage(fileBytes);
}
return texture;
}
The proper place to make that change is on the Texture2D after loading the Texture. If you really want to load them as thumbnails and want the size to be smaller to save memory then resize it with the Texture2D.Resize function after loading the Texture. The height and width of 60 should be fine. You can then create Sprite from it with Sprite.Create.
Texture2D takeScreenShotImage(string filePath)
{
Texture2D texture = null;
byte[] fileBytes;
if (File.Exists(filePath))
{
fileBytes = File.ReadAllBytes(filePath);
texture = new Texture2D(1, 1, TextureFormat.ETC2_RGB, false);
texture.LoadImage(fileBytes);
}
//RE-SIZE THE Texture2D
texture.Resize(60, 60);
texture.Apply();
return texture;
}
Note that TextureFormat.ETC2_RGB is compressed. To resize it you may have to create a copy of it. See #1 solution from my other post on how to do this.
Related
I am fairly new to Unity but am trying to take a photo from the camera and save it. Taking a screen capture is not an option. When I take the photo it appears clear in the center of the photo but gets further distorted towards the edges and I am not sure why. The main camera is linked to the realCamera object in Unity.
The screenshot code, which calls on update is:
DirectoryInfo screenshotDirectory = Directory.CreateDirectory(directoryName);
fileO = original + fileNameEnd + count.ToString() + fileType;
string fullPathO = Path.Combine(screenshotDirectory.FullName, fileO);
RenderTexture rt = new RenderTexture(resWidth, resHeight, 24);
Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false);
byte[] bytes;
realCamera.targetTexture = rt;
realCamera.Render();
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
realCamera.targetTexture = null;
RenderTexture.active = null;
Destroy(rt);
bytes = screenShot.EncodeToPNG();
System.IO.File.WriteAllBytes(fullPathO, bytes);
I have a set of sprites with different resolutions and aspect ratios. I want to create new sprites based on the original sprites but with a fixed 20 x 20 resolution.
When working with bitmaps, what I did was this: Bitmap newImage = new Bitmap(oldImage, new Size(20, 20));
But Unity's Sprites don't have any constructors. How can I do this?
There are 2 ways to create Sprites from image or original sprite.
from image code below..
string url = "";//image url;
WWW image = new WWW(url);
yield return image;
Texture2D texture = new Texture2D(1, 1);
image.LoadImageIntoTexture(texture);
Sprite newSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0), 1);
RectTransform rt = newSprite.GetComponent<RectTransform>();
rt.sizeDelta = new Vector2(20, 20);//make 20px * 20px sprite
clone sprite code below..
Sprite cloneSprite = Instantiate(originalSprite);
RectTransform rt = cloneSprite.GetComponent<RectTransform>();
rt.sizeDelta = new Vector2(20, 20);//make 20px * 20px sprite
I hope it will work on your project.
Not sure how exactly you want to resize an image (make it smaller, or cut the part of it), but you can play around with Sprite.Create method
I have got a quad that has got a target texture set through Unity Editor. I would like to save the output visualization on the quad as an image. Are there any ways to save it as a quad? I have tried through texture2d but its just a black image that is being saved.
Try this
private void SaveImage(Texture t, string path)
{
RenderTexture rt = new RenderTexture(t.width, t.height, 0);
Graphics.Blit(t, rt);
Texture2D t2d = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
t2d.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
File.WriteAllBytes(path, t2d.EncodeToPNG());
}
Usage
SaveImage(yourQuad.GetComponent<MeshRenderer>().material.mainTexture, "yourSavePath.png");
The reason I wish to do so is that Unity has a nice DTX5 format that reduces the file size by a lot. But to get that, I need a sprite that's size is - both for height and width - a multiple of 4.
So I thought I create a new texture with the desired size, load its pixels with the original's pixels and make a sprite out of it that I save as an asset.
The issue is that while saving the texture works, I get the same texture with the proper sizes, saving the sprite doesn't work. It spits out something, but that isn't even close to what I need.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResizeSprites
{
public void Resize(Sprite sprite)
{
int _hei, _wid;
//getting the closest higher values that are a multiple of 4.
for (_hei = sprite.texture.height; _hei % 4 != 0; _hei++) ;
for (_wid = sprite.texture.width; _wid % 4 != 0; _wid++) ;
//creating the new texture.
Texture2D tex = new Texture2D(_wid, _hei,TextureFormat.RGBA32,false);
//tex.alphaIsTransparency = true;
//tex.EncodeToPNG();
//giving the new texture the "improper" ratio sprite texture's pixel info
//pixel by pixel.
for (int wid = 0; wid < sprite.texture.width; wid++)
{
for (int hei = 0; hei < sprite.texture.height; hei++)
{
tex.SetPixel(wid, hei, sprite.texture.GetPixel(wid, hei));
}
}
//saving the asset. the save works, was used for both meshes as well as textures.
Sprite n_spr = Sprite.Create(tex,
new Rect(0, 0, tex.width, tex.height),
new Vector2(0.5f, 0.5f), 100.0f);
AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
}
}
And here are my results:
The first one is the original sprite, and the second is what I was given.
Edit: Even if I don't save my creation, just instantiate it as a GameObject, the result is still the same ugly one.
You really don't need all these code.Texture2D has a resize function so just pull the Texture2D from the Sprite then call the re-szie function to re-size it. That's it.
Something like this:
public void Resize(Sprite sprite)
{
Texture2D tex = sprite.texture;
tex.Resize(100, 100, TextureFormat.RGBA32, false);
Sprite n_spr = Sprite.Create(tex,
new Rect(0, 0, tex.width, tex.height),
new Vector2(0.5f, 0.5f), 100.0f);
AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
}
As for you original problem, that's because you did not call the Apply function. Each time you modify the pixels, you are supposed to call the Apply function. Finally, always use GetPixels32 not GetPixel or GetPixels. The reason is because GetPixels32 is extremely faster than the rest of the function.
public void Resize(Sprite sprite)
{
int _hei, _wid;
//getting the closest higher values that are a multiple of 4.
for (_hei = sprite.texture.height; _hei % 4 != 0; _hei++) ;
for (_wid = sprite.texture.width; _wid % 4 != 0; _wid++) ;
//creating the new texture.
Texture2D tex = new Texture2D(_wid, _hei, TextureFormat.RGBA32, false);
//tex.alphaIsTransparency = true;
//tex.EncodeToPNG();
//giving the new texture the "improper" ratio sprite texture's pixel info
//pixel by pixel.
Color32[] color = sprite.texture.GetPixels32();
tex.SetPixels32(color);
tex.Apply();
//saving the asset. the save works, was used for both meshes as well as textures.
Sprite n_spr = Sprite.Create(tex,
new Rect(0, 0, tex.width, tex.height),
new Vector2(0.5f, 0.5f), 100.0f);
AssetSaver.CreateAsset(n_spr, sprite.name + "_dtx5");
}
Is it possible to crop the captured image based on the shape that I want? I'm using raw image + web cam texture to activate the camera and save the image. And I'm using UI Image overlay method as a mask to cover the unwanted parts. I will be attaching the picture to the char model in the latter part. Sorry, I am new to unity. Grateful for your help!
Below is what I have in my code:
// start cam
void Start () {
devices = WebCamTexture.devices;
background = GetComponent<RawImage> ();
devCam = new WebCamTexture ();
background.texture = devCam;
devCam.deviceName = devices [0].name;
devCam.Play ();
}
void OnGUI()
{
GUI.skin = skin;
//swap front and back camera
if (GUI.Button (new Rect ((Screen.width / 2) - 1200, Screen.height - 650, 250, 250),"", GUI.skin.GetStyle("btn1"))) {
devCam.Stop();
devCam.deviceName = (devCam.deviceName == devices[0].name) ? devices[1].name : devices[0].name;
devCam.Play();
}
//snap picture
if (GUI.Button (new Rect ((Screen.width / 2) - 1200, Screen.height - 350, 250, 250), "", GUI.skin.GetStyle ("btn2"))) {
OnSelectCapture ();
//freeze cam here?
}
}
public void OnSelectCapture()
{
imgID++;
string fileName = imgID.ToString () + ".png";
Texture2D snap = new Texture2D (devCam.width, devCam.height);
Color[] c;
c = devCam.GetPixels ();
snap.SetPixels (c);
snap.Apply ();
// Save created Texture2D (snap) into disk as .png
System.IO.File.WriteAllBytes (Application.persistentDataPath +"/"+ fileName, snap.EncodeToPNG ());
}
}
Unless I am not understanding your question correctly, you can just call `devCam.pause!
Update
What you're looking for is basically to copy the pixels from the screen onto a separate image under some condition. So you could use something like this: https://docs.unity3d.com/ScriptReference/Texture2D.EncodeToPNG.html
I'm not 100% sure what you want to do with it exactly but if you want to have an image that you can use as a sprite, for instance, you can scan each pixel and if the pixel colour value is the same as the blue background, swap it for a 100% transparent pixel (0 in the alpha channel). That will give you just the face with the black hair and the ears.
Update 2
The link that I referred you to copies all pixels from the camera view so you don't have to worry about your source image. Here is the untested method, it should work plug and play so long as there is only one background colour else you will need to modify slightly to test for different colours.
IEnumerator GetPNG()
{
// Create a texture the size of the screen, RGB24 format
yield return new WaitForEndOfFrame();
int width = Screen.width;
int height = Screen.height;
Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
// Read screen contents into the texture
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
tex.Apply();
//Create second texture to copy the first texture into minus the background colour. RGBA32 needed for Alpha channel
Texture2D CroppedTexture = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false);
Color BackGroundCol = Color.white;//This is your background colour/s
//Height of image in pixels
for(int y=0; y<tex.height; y++){
//Width of image in pixels
for(int x=0; x<tex.width; x++){
Color cPixelColour = tex.GetPixel(x,y);
if(cPixelColour != BackGroundCol){
CroppedTexture.SetPixel(x,y, cPixelColour);
}else{
CroppedTexture.SetPixel(x,y, Color.clear);
}
}
}
// Encode your cropped texture into PNG
byte[] bytes = CroppedTexture.EncodeToPNG();
Object.Destroy(CroppedTexture);
Object.Destroy(tex);
// For testing purposes, also write to a file in the project folder
File.WriteAllBytes(Application.dataPath + "/../CroppedImage.png", bytes);
}