Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The following is how I solved this. The TL;DR: the rotation transform goes around 0, 0, so if your image coordinates set 0,0 to bottom left, you need to translate the image to be centered on 0,0 first. Also, sin and cos expect radians, not degrees, so remember to convert first</p> <p>The long way: I started by creating a simple program that has easily verified answers, to find out where things are going wrong.</p> <p>The first thing I noticed was that 90.0f wouldn't produce any output. That seemed weird, so I broke in at the "output image size" printf and realized that the output height was being calculated as -87. Clearly that's not right, so let's see why that might happen.</p> <p>Going up a bit, <code>outHeight=(int)ceil(fabs(maxy)-miny);</code> so let's figure out how we're ending up with a negative output height when subtracting maxy and miny. It appears maxy is -0.896... and miny is 88.503... However, the absolute value of maxy is taken before subtracting miny, meaning we're ending up with 0.896 - 88.503. Whoa, that's not good! Let's try doing the subtraction then taking the absolute value.</p> <p>Recompiling with both width and height as such: outWidth=(int)ceil(fabs(maxx-minx)); outHeight=(int)ceil(fabs(maxy-miny));</p> <p>Gets us much better values. Now outWidth and outHeight are 2 and 90, respectively. This is massively improved, but the height should be 100. We'll address that later.</p> <p>To figure out where the math is going wrong, I reorganize the terms to go together: x with x, y with y. Next I adjusted spacing and added parenthesis to make it more readable and ensure order of operations (sure beats trying to look at an OoO table ;) ). Since it's clear you're breaking out the rotation matrix multiplication, I'm going to name your variables something a bit more intuitive than x1, x2, etc. From now on, x1 is topLeftTransformedX, x2 is topRightTransformedX, x3 will exist as bottomLeftTransformedX (always 0), and x4 will be bottomRightTransformedX, same for Y. Longer, but much easier to know what you're dealing with.</p> <p>Using this, at this point, I see the same thing you do... then I remembered something, based on the numbers seen from this cleaner code (same math as yours, but still easier to debug).</p> <p>Suddenly, my math for X looks like this: // x = x cos - y sin float topLeftTransformedX = (-midX * cosine) - (midY * sine); float topRightTransformedX = (midX * cosine) - (midY * sine); float bottomLeftTransformedX = (-midX * cosine) - (-midY * sine); float bottomRightTransformedX = (midX * cosine) - (-midY * sine);</p> <p>The rotation matrix rotates around the center point. You have to translate the image to be centered around that for a proper rotation.</p> <p>Then, when trying to figure out why this would be giving the values it is, i recalled something else - angle needs to be in radians.</p> <p>Suddenly, it almost all works. There's still some more to do, but this should get you 95% of the way there or more. Hope it helps!</p> <pre><code>// bmprotate.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include &lt;math.h&gt; #define min(x,y) x &lt; y ? x : y #define max(x,y) x &gt; y ? x : y #define PI 3.14159 void rotate(int width, int height, float angleInDeg) { float angle = angleInDeg * (PI/180.0f); float midX = ((float)width) / 2.0f; float midY = ((float)height) / 2.0f; float sine = sin(angle); float cosine = cos(angle); // x = x cos - y sin float topLeftTransformedX = (-midX * cosine) - (midY * sine); float topRightTransformedX = (midX * cosine) - (midY * sine); float bottomLeftTransformedX = (-midX * cosine) - (-midY * sine); float bottomRightTransformedX = (midX * cosine) - (-midY * sine); float minx = min( topLeftTransformedX, min(topRightTransformedX, min(bottomLeftTransformedX, bottomRightTransformedX)) ); float maxx = max( topLeftTransformedX, max(topRightTransformedX, max(bottomLeftTransformedX, bottomRightTransformedX)) ); // y = x sin + y cos float topLeftTransformedY = (-midX * sine) + (midY * cosine); float topRightTransformedY = (midX * sine) + (midY * cosine); float bottomLeftTransformedY = (-midX * sine) + (-midY * cosine); float bottomRightTransformedY = (midX * sine) + (-midY * cosine); float miny = min( topLeftTransformedY, min(topRightTransformedY, min(bottomLeftTransformedY, bottomRightTransformedY)) ); float maxy = max( topLeftTransformedY, max(topRightTransformedY, max(bottomLeftTransformedY, bottomRightTransformedY)) ); int outWidth; int outHeight; printf("(%f,%f) , (%f,%f) , (%f,%f) , (%f,%f)\n", topLeftTransformedX, topLeftTransformedY, topRightTransformedX, topRightTransformedY, bottomLeftTransformedX, bottomLeftTransformedY, bottomRightTransformedX, bottomRightTransformedY); outWidth = (int) ceil( fabs(maxx) + fabs(minx)); outHeight = (int) ceil( fabs(maxy) + fabs(miny) ); printf("output image size: (%d,%d)\n",outWidth,outHeight); for(int x=0; x&lt;outWidth; x++) { for(int y=0; y&lt;outHeight; y++) { int srcX=(int)((x+minx)*cosine+(y+miny)*sine); int srcY=(int)((y+miny)*cosine-(x+minx)*sine); if(srcX &gt;=0 &amp;&amp; srcX &lt; width &amp;&amp; srcY &gt;= 0 &amp;&amp; srcY &lt; height) { printf("(x,y) = (%d,%d)\n",srcX, srcY); } } } } int _tmain(int argc, _TCHAR* argv[]) { rotate(100,2,90.0f); for (int i = 0; i &lt; 360; i++) { } return 0; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload