[Unity (C #)] Convert textures to image data, save and load on the terminal
Introduction
I took a lot of time to save the image, so I will leave a note.
This time, the following processing is performed.
**-Convert Sprite (Texture) attached to Image component to Png and save
-Load Png and attach it to the Image component as Sprite (Texture) **
demo
Here is a demo that was actually verified on an Android device.
After erasing the written image, the restoration was successful.
Since the image data is saved in the terminal, it can be restored even if the application is closed.
The image below is a screenshot when referring to the save destination directory inside the PC.
It was properly saved in Png format.
Code for the drawing part
I will use the implementation of the drawing part completely as it is.
Only the smartphone compatible part and the texture reset are added as follows.
Added to Painter class
/// <summary>
///Reset texture
/// </summary>
public void ResetTexture()
{
var img = GetComponent<Image>();
var rt = GetComponent<RectTransform>();
var width = (int)rt.rect.width;
var height = (int)rt.rect.height;
texture = new Texture2D(width, height, TextureFormat.ARGB32, false);
img.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
Color32[] texColors = Enumerable.Repeat<Color32>(bgColor, width * height).ToArray();
texture.SetPixels32(texColors);
texture.Apply();
}
void Update()
{
#if UNITY_EDITOR
if (Input.GetMouseButtonDown(0))
{
beforeMousePos = GetPosition();
}
else if (Input.GetMouseButton(0))
{
Vector3 v = GetPosition();
LineTo(beforeMousePos, v, lineColor);
beforeMousePos = v;
texture.Apply();
}
#elif UNITY_ANDROID && !UNITY_EDITOR
if (0 < Input.touchCount)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
beforeMousePos = GetPosition();
}
else if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
{
Vector3 v = GetPosition();
LineTo(beforeMousePos, v, lineColor);
beforeMousePos = v;
texture.Apply();
}
}
#endif
}
Save and load images
Button press processing is implemented in UniRx. There is no particular meaning.
using System.IO;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
///Texture ⇔ Png Image conversion, saving and loading
/// </summary>
public class TexturePngConverter : MonoBehaviour
{
[SerializeField] private Button _saveButton;
[SerializeField] private Button _loadButton;
[SerializeField] private Button _resetButton;
[SerializeField] private Image _paintImage;
[SerializeField] private Painter _painter;
private const string IMAGE_SAVE_FOLDER = "Image";
private void Start()
{
//Save button
_saveButton.OnPointerClickAsObservable().Subscribe(_ => ConvertToPngAndSave(GetSavePath(IMAGE_SAVE_FOLDER))).AddTo(this);
//Load button
_loadButton.OnPointerClickAsObservable().Subscribe(_ => ConvertToTextureAndLoad(GetSavePath(IMAGE_SAVE_FOLDER))).AddTo(this);
//Reset button
_resetButton.OnPointerClickAsObservable().Subscribe(_ => _painter.ResetTexture());
}
/// /// <summary>
///Get the save destination path
/// </summary>
/// <param name="folderName">Delimited folder name</param>
/// <returns>Destination path</returns>
private string GetSavePath(string folderName)
{
string directoryPath = Application.persistentDataPath + "/" + folderName + "/";
if (!Directory.Exists(directoryPath))
{
//Create if it doesn't exist yet
Directory.CreateDirectory(directoryPath);
return directoryPath + "paint.png ";
}
return directoryPath + "paint.png ";
}
/// <summary>
///Convert & save to image
/// </summary>
private void ConvertToPngAndSave(string path)
{
//Convert to png
byte[] bytes = _paintImage.sprite.texture.EncodeToPNG();
//Save
File.WriteAllBytes(path, bytes);
}
/// <summary>
///Convert & load to texture
/// </summary>
private void ConvertToTextureAndLoad(string path)
{
//Read
byte[] bytes = File.ReadAllBytes(path);
//Convert image to texture
Texture2D loadTexture = new Texture2D(2, 2);
loadTexture.LoadImage(bytes);
//Convert textures to sprites
_paintImage.sprite = Sprite.Create(loadTexture, new Rect(0, 0, loadTexture.width, loadTexture.height), Vector2.zero);
}
}
Application.persistentDataPath
ʻWhen you call Application.persistentDataPath`
You can access the persistent path that literally exists within the app.
I make a folder here to save the images.
EncodeToPNG
If you call ʻEncodeToPNG from the ʻImageConversion
class, it will be converted to png data as a byte array.
](https://docs.unity3d.com/ScriptReference/ImageConversion.EncodeToPNG.html)
WriteAllBytes,ReadAllBytes
WriteAllBytes
and ReadAllBytes
are responsible for writing and reading data, respectively.
I’m grateful that you can do it just by writing this.
in conclusion
I wasn’t sure about ** resource release ** when writing and reading.
It worked even if I didn’t write it, so it says “OK”.
Please let me know if you write dangerous code because you are a good and honest child.
Reference link
](Https://stackoverflow.com/questions/60484595/encodetopng-hangs-the-script) Reference link: Hanachiru’s My Note / 09/13/214940)