How to convert texture2D to image in C#

Hello, I am trying to use Aforge for Computer Vision with the unity webcam. I need to turn a texture2D into a C# image file, and I don’t know how to do it. Based on some looking aroudn the net, I wrote the following functions. However, I am apparently missing a dll: gdiplus.dll , which I am starting to think doesn’t exist on the OSX operating system. How else can I convert texture2D into an Image?

And I am surprised there isn’t some code already available to do this.

# region texture2image 
public static System.Drawing.Image Texture2Image(Texture2D texture)
{
  if (texture == null)
  {
      return null;
  }
  //Save the texture to the stream.
  byte[] bytes = texture.EncodeToPNG();

   //Memory stream to store the bitmap data.
  MemoryStream ms = new MemoryStream(bytes);

  //Seek the beginning of the stream.
  ms.Seek(0, SeekOrigin.Begin);

  //Create an image from a stream.
  System.Drawing.Image bmp2 = System.Drawing.Bitmap.FromStream(ms);

  //Close the stream, we nolonger need it.
  ms.Close();
  ms = null;
  
  return bmp2;
}
#endregion

# region image2texture 
public static Texture2D Image2Texture(System.Drawing.Image im)
{
	if (im == null)
	  {
	      return new Texture2D(4,4);
	  }


	  //Memory stream to store the bitmap data.
	  MemoryStream ms = new MemoryStream();

	
	  //Save to that memory stream.
	  im.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
	
	   //Go to the beginning of the memory stream.
	  ms.Seek(0, SeekOrigin.Begin);

	  //make a new Texture2D
	  Texture2D tex = new Texture2D(im.Width, im.Height);
	 
	  tex.LoadImage(ms.ToArray());
	  		
	  //Close the stream.
	  ms.Close(); 
	  ms = null;

	  //
	  return tex;
}
#endregion

Hi, I will answer to this question:

“How to convert texture2D to image in Unity using C#”

Image pictureInScene;
byte[] temp= File.ReadAllBytes ("pathTo/image.png");
Texture2D tempPic= new Texture2D (2, 2);
fotillo.LoadImage (temp);
pictureInScene.sprite = Sprite.Create (tempPic, new Rect (0, 0, 128, 128), new Vector2 ());//set the Rect with position and dimensions as you need

It’s not a matter of OS X…you can’t use System.Drawing, that’s not in Mono. You don’t need that anyway, just use File.WriteAllBytes for the PNG data. Look at the code example in the docs for EncodeToPNG.

A quick search on google and the AForge forums gives me this:

Is AForge supported on Mono

Support for Mac OS

From the first link it seems it’s possible to use “some” parts of the framework, but you have to compile them yourself for mono.

Since this was high up in search results and took me a while to find the correct answer:

private static Texture2D RenderTextureToTexture2D(RenderTexture texture)
{
    var oldRen = RenderTexture.active;
    RenderTexture.active = texture;
    var texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA64, false, false);
    texture2D.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
    texture2D.Apply();
    RenderTexture.active = oldRen;
    return texture2D;
}
    private static void CreateImageFiles(Texture2D tex, int index)
    {
        var pngData = tex.EncodeToJPG();
        if (pngData.Length < 1)
        {
            return;
        }
        var path = @"TypePathHere" + index + ".jpg";
        File.WriteAllBytes(path, pngData);
        AssetDatabase.Refresh();
    }

Those are the main things you need

If you were like me trying to render it from a texture from PreviewRenderUtility’s EndPreview method, please note that the texture that PreviewRenderUtility returns is of type RenderTexture. So just cast it from Texture to RenderTexture.

This one should work for .texture2D embedded into .glb or .fbx files.
Once you put the script inside Assets/, select the file with textures in it, then from the menu pick Extract/Textures.

using System;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Object = UnityEngine.Object;

/* Source: https://github.com/Ecilos/ecilos-unity-assets-scripts */

namespace WARP.Core.API {
public class ImageExtractor {
  [MenuItem("Extract/Textures")]
  public static void Extract() {
    foreach (string guid in Selection.assetGUIDs) {
      ExtractAsset(guid);
    }
  }

  public static void ExtractAsset(string guid, string extension = "jpg",
                                  int quality = 100) {
    string assetPath = AssetDatabase.GUIDToAssetPath(guid);

    AssetImporter assetImporter = AssetImporter.GetAtPath(assetPath);

    IEnumerable<Object> materials =
        AssetDatabase.LoadAllAssetsAtPath(assetImporter.assetPath)
            .ToList()
            .Where(x => x is Material || x is Texture2D);

    foreach (Object obj in materials) {
      if (obj is Material material) {
        string[] texturePropertyNames = material.GetTexturePropertyNames();

        foreach (string texturePropertyName in texturePropertyNames) {
          Texture texture = material.GetTexture(texturePropertyName);

          if (texture == null)
            // Empty slot.
            continue;

          if (texture is Texture2D texture2D)
            WriteTexture(assetPath, texture2D, extension, quality);
          else
            Debug.LogWarning(
                $"Extraction of object's \"{assetImporter.assetPath}\"'s texture type {texture.GetType().Name} is unsupported for texture property \"{texturePropertyName}\"! Only Texture2D is yet supported.");
        }
      } else if (obj is Texture2D texture2D)
        WriteTexture(assetPath, texture2D, extension, quality);
    }
  }

  private static void WriteTexture(string assetPath, Texture2D texture,
                                   string extension, int quality = 100) {
    byte[] bytes;

    if (extension == "jpg")
      bytes = texture.EncodeToJPG(quality);
    else
      throw new ArgumentException(
          "Only \"jpg\" extension currently supported!");

    File.WriteAllBytes(BuildTexturePath(assetPath, texture.name, extension),
                       bytes);
  }

  public static string BuildTexturePath(string assetPath, string textureName,
                                        string extension) {
    string assetFolder = assetPath.Substring(0, assetPath.LastIndexOf('/'));
    string assetPathWithoutExtension =
        assetPath.Substring(0, assetPath.LastIndexOf('.'));
    // string assetName = assetPath.Substring(assetFolder.Length + 1);

    Directory.CreateDirectory(assetPathWithoutExtension);

    return $"{assetPathWithoutExtension}/{textureName}.{extension}";
  }
}
}

For up-to-date version, visit: GitHub - Ecilos/ecilos-unity-assets-scripts: Unity C# scripts for Ecilos metaverse project.