Advertisement
JontePonte

Rearrange a picture into another (Unity C#)(Random visual)

Jul 20th, 2024
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.31 KB | None | 0 0
  1. using System.ComponentModel;
  2. using UnityEngine;
  3. using System.Collections;
  4. using UnityEngine.XR;
  5.  
  6. public class Main : MonoBehaviour
  7. {
  8.     //Based on this article: https://estebanhufstedler.com/2020/06/08/rearrange-a-picture-into-another/
  9.     public Texture2D sourceImage;
  10.     public Texture2D targetImage;
  11.  
  12.     public int segmentSize;
  13.  
  14.     public float imageScale;
  15.  
  16.     public bool rotateTiles;
  17.  
  18.     public string executionTime;
  19.  
  20.     Texture2D[,,] sourceTiles;
  21.     Texture2D[,] targetTiles;
  22.     Texture2D[,] modifiedTiles;
  23.  
  24.     Color[,,][] sourceTilePixels;
  25.     Color[,][] targetTilePixels;
  26.  
  27.     int ySegments;
  28.     int xSegments;
  29.  
  30.     public void GenerateImage()
  31.     {
  32.         float startTime = Time.realtimeSinceStartup;
  33.  
  34.         if (sourceImage.width != targetImage.width || sourceImage.height != targetImage.height)
  35.         {
  36.             Debug.LogError("Images must have the same dimensions!");
  37.             return;
  38.         }
  39.         ySegments = sourceImage.height / segmentSize;
  40.         xSegments = sourceImage.width / segmentSize;
  41.  
  42.         sourceTiles = new Texture2D[xSegments, ySegments, 4];
  43.         targetTiles = new Texture2D[xSegments, ySegments];
  44.         modifiedTiles = new Texture2D[xSegments, ySegments];
  45.  
  46.         sourceTilePixels = new Color[xSegments, ySegments, 4][];
  47.         targetTilePixels = new Color[xSegments, ySegments][];
  48.  
  49.         for (int y = 0; y < ySegments; y++)
  50.         {
  51.             for (int x = 0; x < xSegments; x++)
  52.             {
  53.                 CreateTile(x, y);
  54.             }
  55.         }
  56.  
  57.         for (int y = 0; y < ySegments; y++)
  58.         {
  59.             for (int x = 0; x < xSegments; x++)
  60.             {
  61.                 MatchTileToTarget(x, y);
  62.             }
  63.         }
  64.  
  65.         GameObject parent = new GameObject();
  66.         parent.name = "Image";
  67.  
  68.         for (int y = 0; y < ySegments; y++)
  69.         {
  70.             for (int x = 0; x < xSegments; x++)
  71.             {
  72.                 GameObject tile = GameObject.CreatePrimitive(PrimitiveType.Quad);
  73.  
  74.                 tile.name = "Tile";
  75.                 tile.transform.position = new Vector3(x * xSegments * 1.05f, y * xSegments * 1.05f, 0);
  76.                 tile.transform.localScale = new Vector3(xSegments, xSegments);
  77.                 tile.transform.parent = parent.transform;
  78.  
  79.                 tile.GetComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Unlit/Texture"));
  80.                 tile.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = modifiedTiles[x, y];
  81.                 tile.GetComponent<MeshRenderer>().sharedMaterial.mainTexture.filterMode = FilterMode.Point;
  82.             }
  83.         }
  84.  
  85.         executionTime = ((Time.realtimeSinceStartup - startTime) * 1000f) + "ms";
  86.     }
  87.  
  88.     void CreateTile(int x, int y)
  89.     {
  90.         Color[] sourceColors = sourceImage.GetPixels(x * segmentSize, y * segmentSize, segmentSize, segmentSize);
  91.         sourceTiles[x, y, 0] = new Texture2D(segmentSize, segmentSize);
  92.         sourceTiles[x, y, 0].SetPixels(sourceColors);
  93.         sourceTiles[x, y, 0].Apply();
  94.  
  95.         sourceTilePixels[x, y, 0] = sourceTiles[x, y, 0].GetPixels();
  96.  
  97.         //Create rotated version of tiles
  98.         for (int i = 1; i < 4; i++)
  99.         {
  100.             sourceTiles[x, y, i] = RotateTexture(sourceTiles[x, y, i - 1], true);
  101.             sourceTiles[x, y, i].Apply();
  102.             sourceTilePixels[x, y, i] = sourceTiles[x, y, i].GetPixels();
  103.         }
  104.  
  105.         targetTiles[x, y] = new Texture2D(segmentSize, segmentSize);
  106.  
  107.         Color[] targetColors = targetImage.GetPixels(x * segmentSize, y * segmentSize, segmentSize, segmentSize);
  108.  
  109.         targetTiles[x, y].SetPixels(targetColors);
  110.         targetTiles[x, y].Apply();
  111.         targetTilePixels[x, y] = targetTiles[x, y].GetPixels();
  112.     }
  113.  
  114.     void MatchTileToTarget(int xCoord, int yCoord)
  115.     {
  116.         int xOptimalCoord = 0;
  117.         int yOptimalCoord = 0;
  118.         int optimalRotation = 0;
  119.  
  120.         float minCost = float.MaxValue;
  121.  
  122.         for (int y = 0; y < ySegments; y++)
  123.         {
  124.             for (int x = 0; x < xSegments; x++)
  125.             {
  126.                 if (modifiedTiles[x, y] == null)
  127.                 {
  128.                     for (int i = 0; i < 4; i++)
  129.                     {
  130.                         float cost = CalculateCost(xCoord, yCoord, i, x, y);
  131.                         if (cost < minCost)
  132.                         {
  133.                             minCost = cost;
  134.                             xOptimalCoord = x;
  135.                             yOptimalCoord = y;
  136.                             optimalRotation = i;
  137.                         }
  138.                     }
  139.  
  140.                 }
  141.             }
  142.         }
  143.  
  144.         modifiedTiles[xOptimalCoord, yOptimalCoord] = sourceTiles[xCoord, yCoord, rotateTiles ? optimalRotation : 0];
  145.     }
  146.  
  147.     float CalculateCost(int x1, int y1, int rot, int x2, int y2)
  148.     {
  149.         Color[] pixels1 = sourceTilePixels[x1, y1, rot];
  150.         Color[] pixels2 = targetTilePixels[x2, y2];
  151.  
  152.         float totalDiff = 0;
  153.  
  154.         for (int i = 0; i < pixels1.Length; i++)
  155.         {
  156.             float r1 = pixels1[i].r;
  157.             float g1 = pixels1[i].g;
  158.             float b1 = pixels1[i].b;
  159.  
  160.             float r2 = pixels2[i].r;
  161.             float g2 = pixels2[i].g;
  162.             float b2 = pixels2[i].b;
  163.  
  164.             float redDiff = (r1 - r2) * (r1 - r2);
  165.             float greenDiff = (g1 - g2) * (g1 - g2);
  166.             float blueDiff = (b1 - b2) * (b1 - b2);
  167.  
  168.             totalDiff += redDiff + greenDiff + blueDiff;
  169.         }
  170.         return totalDiff;
  171.     }
  172.  
  173.  
  174.  
  175.     Texture2D RotateTexture(Texture2D originalTexture, bool clockwise)
  176.     {
  177.         Color32[] original = originalTexture.GetPixels32();
  178.         Color32[] rotated = new Color32[original.Length];
  179.         int w = originalTexture.width;
  180.         int h = originalTexture.height;
  181.  
  182.         int iRotated, iOriginal;
  183.  
  184.         for (int j = 0; j < h; ++j)
  185.         {
  186.             for (int i = 0; i < w; ++i)
  187.             {
  188.                 iRotated = (i + 1) * h - j - 1;
  189.                 iOriginal = clockwise ? original.Length - 1 - (j * w + i) : j * w + i;
  190.                 rotated[iRotated] = original[iOriginal];
  191.             }
  192.         }
  193.  
  194.         Texture2D rotatedTexture = new Texture2D(h, w);
  195.         rotatedTexture.SetPixels32(rotated);
  196.         rotatedTexture.Apply();
  197.         return rotatedTexture;
  198.     }
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement