I found that, to rotate a piece of any size that exists in a grid only two graphical operations are needs.
If you want to rotate the piece clock-wise, first inverse the coordinates of each block that makes up the piece. This means swap the x and y coordinates of each block.
In code, it could look something like this
for (int i = 0; i < sizeOfPiece; i++)
{
int temp = piece[i].X;
piece[i].X = piece[i].Y;
piece[i].Y = temp;
}
Then, mirror your newly manipulated piece over the Y-axis. This can be done by taking the x-coordinate of each block and setting it equal to the width of the entire piece - the x-coordinate.
The code could look something like this:
for (int i = 0; i < sizeOfPiece; i++)
{
piece[i].X = pieceWidth - piece[i].X;
}
where int pieceWidth = piece[RightEdge].X - piece[leftEdge].X;
If you have trouble find the right and left edges of the piece, this should work fine
int edges[4] = {0, 0, 0, 0};
for (int i = 1; i < sizeOfPiece; i++)
{
if (piece[i].X < piece[edges[LEFT]].X) edges[LEFT] = i; //Check for a block on the left edge
if (piece[i].X > piece[edges[RIGHT]].X) edges[RIGHT] = i; //Check for a block on the right edge
if (piece[i].Y < piece[edges[UP]].Y) edges[UP] = i; //Check for a block on the upper edge
if (piece[i].Y > piece[edges[DOWN]].Y) edges[DOWN] = i; //Check for a block on the bottom edge
}
where LEFT = 0, RIGHT = 1, UP = 2, and DOWN = 3
In this case, the edges array stores the ID's of a single block that is on each of the 4 edges of the piece. Only the right and left edges are needed to find the width, but the other edges could be useful to know at some other point.
In this case, the previously mentioned pieceWidth formula would actually look like this:
int pieceWidth = piece[edges[RIGHT]].X - piece[edges[LEFT]].X;
If you want to rotate counter-clockwise, just do the opposite. This means that you first mirror the piece over the y-axis and then inverse it's coordinates.
I've drawn up a little visual representation of these graphical translations put into action:
Picture
In the above picture, the red section represents the original piece, a blue transition shows the piece after it has been inversed, and the green section shows the previous piece after is has been mirrored over the y-axis.
The upper example is rotating clock-wise while the bottom example is rotating counter-clockwise.