Is there build in function or any code sample that allows to transform **Texture2D.GetPixels32()** array in such way that output array would correspond to the same image which was rotated around its center by a specific angle?

finally I’ve end up with this:

```
#pragma strict
var texToDraw : Texture2D;
var x: int;
var y: int;
private var pix1:Color32[];
private var pix2:Color32[];
private var pix3:Color32[];
var angle: int;
function Start (){
var background : Texture2D = Instantiate(renderer.material.mainTexture);
pix1 = background.GetPixels32();
pix2 = texToDraw.GetPixels32();
var W = texToDraw.width;
var H = texToDraw.height;
pix3 = rotateSquare(pix2, Mathf.Deg2Rad*angle);
for (var j = 0; j < H; j++){
for (var i = 0; i < W; i++) {
//pix1[background.width/2 - texToDraw.width/2 + x + i + background.width*(background.height/2-texToDraw.height/2+j+y)] = pix2[i + j*texToDraw.width];
pix1[background.width/2 - W/2 + x + i + background.width*(background.height/2-H/2+j+y)] = pix3[i + j*W];
}
}
background.SetPixels32(pix1);
background.Apply();
renderer.material.mainTexture = background;
}
function rotateSquare(arr:Color32[], phi:float){
var x:int;
var y:int;
var i:int;
var j:int;
var sn:float = Mathf.Sin(phi);
var cs:float = Mathf.Cos(phi);
var texture: Texture2D = Instantiate(texToDraw);
var arr2:Color32[] = texture.GetPixels32();
var W:int = texture.width;
var H:int = texture.height;
var xc: int = W/2;
var yc: int = H/2;
for (j=0; j<H; j++){
for (i=0; i<W; i++){
arr2[j*W+i] = new Color32(0,0,0,0);
x = cs*(i-xc)+sn*(j-yc)+xc;
y = -sn*(i-xc)+cs*(j-yc)+yc;
if ((x>-1) && (x<W) &&(y>-1) && (y<H)){
arr2[j*W+i]=arr[y*W+x];
}
}
}
return arr2;
}
```

An excellent answer to your own question! Thank you very much qvarta, you ended a long search for me ! I’m posting this as an answer juste to include a C# version for fellow c# devs! (also I’ve replaced the floats with doubles and Mathf with System.Math, it improves the accuracy)

using System;

public class ImageRotator {

```
public static Texture2D RotateImage(Texture2D originTexture, int angle){
Texture2D result;
result = new Texture2D(originTexture.width, originTexture.height);
Color32[] pix1 = result.GetPixels32();
Color32[] pix2 = originTexture.GetPixels32();
int W = originTexture.width;
int H = originTexture.height;
int x = 0;
int y = 0;
Color32[] pix3 = rotateSquare(pix2, (Math.PI/180*(double)angle), originTexture);
for (int j = 0; j < H; j++){
for (var i = 0; i < W; i++) {
//pix1[result.width/2 - originTexture.width/2 + x + i + result.width*(result.height/2-originTexture.height/2+j+y)] = pix2[i + j*originTexture.width];
pix1[result.width/2 - W/2 + x + i + result.width*(result.height/2-H/2+j+y)] = pix3[i + j*W];
}
}
result.SetPixels32(pix1);
result.Apply();
return result;
}
static Color32[] rotateSquare(Color32[] arr, double phi, Texture2D originTexture){
int x;
int y;
int i;
int j;
double sn = Math.Sin(phi);
double cs = Math.Cos(phi);
Color32[] arr2 = originTexture.GetPixels32();
int W = originTexture.width;
int H = originTexture.height;
int xc = W/2;
int yc = H/2;
for (j=0; j<H; j++){
for (i=0; i<W; i++){
arr2[j*W+i] = new Color32(0,0,0,0);
x = (int)(cs*(i-xc)+sn*(j-yc)+xc);
y = (int)(-sn*(i-xc)+cs*(j-yc)+yc);
if ((x>-1) && (x<W) &&(y>-1) && (y<H)){
arr2[j*W+i]=arr[y*W+x];
}
}
}
return arr2;
}
}
```

Hope this can help someone, thanks again qvatra !

## IMPORTANT PLEASE READ!!!

*You don’t understand the code? No surprise!*

Maybe the author wants to have his fingerprint in your programs or just likes to be the only one who understands this code. I got the impression the answer is simply to confuse you. You need examples?

Besides using **nonsense variable names**, here some obvious trolls:

- result.width == originTexture.width == W
- x = y = 0
- Thus the line:
**pix1[result.width/2 - W/2 + x + i + result.width*(result.height/2-H/2+j+y)] = pix3[i + j*W]

is the same as**pix1[i + j*W] = pix3[i + j*W]**. - Why this random calculation then? And why would you bring in two variables (x and y) that are simply 0 and do add nothing to the calculation?
**Yep, he definitely tries to help you**.

But this is not even the worst.**The whole method Start/RotateImage is redundant**.

You do not need to iterate over the pix[3] array.

All you need is the function rotateSquare and perform**result.SetPixels32(arr2)**and you are done.

Yes this is btw the same method the author used at some other point, strange he didn’t just use it, huh?

## How it works

Basically the well established rotation matrix (see rotateSquare-method) is applied and this is no magic and it is nothing he came up with on his own.

- x’ = x
*cos(a) - y*sin(a) - y’ = x
*sin(a) + y*cos(a)

However, instead of using the rotation matrix A itsself we use the inverted rotation matrix A^-1:

- x = x’ *cos(a) + y’ *sin(a)
- y = x’ * - sin(a) + y’ *cos(a)

This is an established approach to avoid holes in the output image. Rather than calculating the new, transformed pixel position for a pixel, we calculate for a given destination pixel [x’, y’] where its source [x, y] was. For further information I recommend the answer by Ralf Kleberhoff: java - How to get positions of rotated coordinate before rotation? - Stack Overflow

The rest besides this formulae is not relevant.

So here is the readable and performant solution to the problem, hope this helps some people…

```
public Texture2D RotateImage(Texture2D originTexture, float angle)
{
int oldX;
int oldY;
int width = originTexture.width;
int height = originTexture.height;
Color32[] originPixels = originTexture.GetPixels32();
Color32[] transformedPixels = originTexture.GetPixels32();
float phi = Mathf.Deg2Rad * angle;
for (int newY = 0; newY < height; newY++)
{
for (int newX = 0; newX < width; newX++)
{
transformedPixels[newY * width + newX] = new Color32(0, 0, 0, 0);
int newXNormToCenter = newX - width / 2;
int newYNormToCenter = newY - height / 2;
oldX = (int)(Mathf.Cos(phi) * newXNormToCenter + Mathf.Sin(phi) * newYNormToCenter + width / 2);
oldY = (int)(-Mathf.Sin(phi) * newXNormToCenter + Mathf.Cos(phi) * newYNormToCenter + height / 2);
bool InsideImageBounds = (oldX > -1) && (oldX < width) && (oldY > -1) && (oldY < height);
if (InsideImageBounds)
{
transformedPixels[newY * width + newX] = originPixels[oldY * width + oldX];
}
}
}
Texture2D result = new Texture2D(width, height);
result.SetPixels32(rotatedPixels);
result.Apply();
return result;
}
```