Advertisement
JontePonte

Rearrange a picture into another (Unity C#) (Two different images)

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