Advertisement
Guest User

bitmap transformations

a guest
Sep 4th, 2011
301
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.00 KB | None | 0 0
  1. #define _WIN32_WINNT 0x0500
  2.  
  3. #include <windows.h>
  4.  
  5. #include <iostream>
  6. #include <vector>
  7.  
  8. #include <cstdlib>
  9. #include <ctime>
  10. #include <cmath>
  11.  
  12. typedef void (*Callback)(double[2][2], double[2], int, int, int, int, int, int);
  13.  
  14. struct Color
  15. {
  16.     static const int Default = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  17.     static const int White   = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  18.     static const int Red     = FOREGROUND_RED |                                      FOREGROUND_INTENSITY;
  19.     static const int Green   =                  FOREGROUND_GREEN |                   FOREGROUND_INTENSITY;
  20.     static const int Blue    =                                     FOREGROUND_BLUE | FOREGROUND_INTENSITY;
  21. };
  22.  
  23. struct Bitmap
  24. {
  25.     int width;
  26.     int height;
  27.  
  28.     std::vector<int> data;
  29.  
  30.     Bitmap(int width_ = 1, int height_ = 1, int color_ = Color::White) :
  31.         width(width_), height(height_), data(width_ * height_, color_) {}
  32.  
  33.     int & operator()(int x, int y)       { return data[x * height + y]; }
  34.     int   operator()(int x, int y) const { return data[x * height + y]; }
  35. };
  36.  
  37. Bitmap RandomBitmap(int width, int height)
  38. {
  39.     Bitmap bmp(width, height);
  40.  
  41.     struct Local
  42.     {
  43.         static void RandomColorDrops(Bitmap & bmp, int color)
  44.         {
  45.             int x, y;
  46.  
  47.             const int max_drops = 1 + (bmp.width + bmp.height) / 2;
  48.  
  49.             for (int count = 0; count < max_drops; ++count)
  50.             {
  51.                 x = rand() % (bmp.width  - 6) + 3;
  52.                 y = rand() % (bmp.height - 6) + 3;
  53.  
  54.                 for (int i = -1; i <= 1; ++i)
  55.                     for (int j = -1; j <= 1; ++j)
  56.                         bmp(x + i, y + j) = color;
  57.             }
  58.         }
  59.     };
  60.  
  61.     Local::RandomColorDrops(bmp, Color::Red);
  62.     Local::RandomColorDrops(bmp, Color::Green);
  63.     Local::RandomColorDrops(bmp, Color::Blue);
  64.  
  65.     return bmp;
  66. }
  67.  
  68. struct Console
  69. {
  70.     static HANDLE console;
  71.     static CHAR_INFO * buffer;
  72.     static int width;
  73.     static int height;
  74.  
  75.     static void ClearBuffer()
  76.     {
  77.         for (int i = 0; i < width; ++i)
  78.             for (int j = 0; j < height; ++j)
  79.                 buffer[i * height + j].Char.AsciiChar = ' ';
  80.     }
  81.  
  82.     static void Init()
  83.     {
  84.         console = GetStdHandle(STD_OUTPUT_HANDLE);
  85.  
  86.         width = 80;
  87.         height = 25;
  88.  
  89.         buffer = new CHAR_INFO[80 * 25];
  90.     }
  91.  
  92.     static void Destroy()
  93.     {
  94.         delete[] buffer;
  95.     }
  96.  
  97.     static void Resize(int x, int y)
  98.     {
  99.         delete[] buffer;
  100.  
  101.         width = x;
  102.         height = y;
  103.  
  104.         buffer = new CHAR_INFO[x * y];
  105.  
  106.         COORD size = { x, y };
  107.  
  108.         SetConsoleScreenBufferSize(console, size);
  109.     }
  110.  
  111.     static void DrawOnBuffer(const Bitmap & bmp)
  112.     {
  113.         for (int y = 0; y < bmp.height; ++y)
  114.         {
  115.             for (int x = 0; x < bmp.width; ++x)
  116.             {
  117.                 buffer[y * width + x].Char.AsciiChar = '#';
  118.                 buffer[y * width + x].Attributes = bmp(x, y);
  119.             }
  120.         }
  121.     }
  122.  
  123.     static void DisplayBuffer()
  124.     {
  125.         COORD buffer_size = { width, height };
  126.         COORD buffer_coord = { 0, 0 };
  127.  
  128.         SMALL_RECT rect;
  129.  
  130.         rect.Top = 0;
  131.         rect.Left = 0;
  132.         rect.Right = width;
  133.         rect.Bottom = height;
  134.  
  135.         WriteConsoleOutput(console, buffer, buffer_size, buffer_coord, &rect);
  136.     }
  137. };
  138.  
  139. HANDLE Console::console;
  140. CHAR_INFO * Console::buffer;
  141. int Console::width;
  142. int Console::height;
  143.  
  144. void Invert(double a[2][2], double b[2])
  145. {
  146.     double det = a[0][0] * a[1][1] - a[0][1] * a[1][0];
  147.  
  148.     double temp = a[0][0];
  149.  
  150.     a[0][0] = a[1][1];
  151.     a[1][1] = temp;
  152.  
  153.     a[0][1] = - a[0][1];
  154.     a[1][0] = - a[1][0];
  155.  
  156.     a[0][0] /= det;
  157.     a[0][1] /= det;
  158.     a[1][0] /= det;
  159.     a[1][1] /= det;
  160.  
  161.     temp = b[0];
  162.  
  163.     b[0] = - (a[0][0] * b[0] + a[0][1] * b[1]);
  164.     b[1] = - (a[1][0] * temp + a[1][1] * b[1]);
  165. }
  166.  
  167. Bitmap Transform(const Bitmap & input, Callback matrix_setup, int frame, int max_frame)
  168. {
  169.     double matrix_a[2][2] = { 1, 0, 0, 1 };
  170.     double matrix_b[2]    = { 0, 0 };
  171.  
  172.     const int old_width  = input.width;
  173.     const int old_height = input.height;
  174.  
  175.     int max_new_x = matrix_b[0];
  176.     int min_new_x = matrix_b[0];
  177.     int max_new_y = matrix_b[1];
  178.     int min_new_y = matrix_b[1];
  179.  
  180.     int new_x, new_y;
  181.     int old_x, old_y;
  182.  
  183.     for (int old_x = 0; old_x < old_width; ++old_x)
  184.     {
  185.         for (int old_y = 0; old_y < old_height; ++old_y)
  186.         {
  187.             matrix_setup(matrix_a, matrix_b, old_x, old_y, old_width, old_height, frame, max_frame);
  188.  
  189.             new_x = matrix_a[0][0] * old_x + matrix_a[0][1] * old_y + matrix_b[0];
  190.             new_y = matrix_a[1][0] * old_x + matrix_a[1][1] * old_y + matrix_b[1];
  191.  
  192.             if (new_x < min_new_x) min_new_x = new_x;
  193.             if (new_x > max_new_x) max_new_x = new_x;
  194.  
  195.             if (new_y < min_new_y) min_new_y = new_y;
  196.             if (new_y > max_new_y) max_new_y = new_y;
  197.         }
  198.     }
  199.  
  200.     const int new_width  = max_new_x - min_new_x + 1;
  201.     const int new_height = max_new_y - min_new_y + 1;
  202.  
  203.     Bitmap output(new_width, new_height);
  204.  
  205.     for (int new_x = 0; new_x < new_width; ++new_x)
  206.     {
  207.         for (int new_y = 0; new_y < new_height; ++new_y)
  208.         {
  209.             matrix_setup(matrix_a, matrix_b, new_x, new_y, new_width, new_height, frame, max_frame);
  210.  
  211.             Invert(matrix_a, matrix_b);
  212.  
  213.             old_x = matrix_a[0][0] * new_x + matrix_a[0][1] * new_y + matrix_b[0];
  214.             old_y = matrix_a[1][0] * new_x + matrix_a[1][1] * new_y + matrix_b[1];
  215.  
  216.             if (old_x >= 0 && old_x < old_width && old_y >=0 && old_y < old_height)
  217.                 output(new_x, new_y) = input(old_x, old_y);
  218.         }
  219.     }
  220.  
  221.     return output;
  222. }
  223.  
  224. void shear(double a[2][2], double b[2], int x, int y, int max_x, int max_y, int frame, int max_frame)
  225. {
  226.     a[0][1] = frame * 2.0 / max_frame;
  227. }
  228.  
  229. void grow_top(double a[2][2], double b[2], int x, int y, int max_x, int max_y, int frame, int max_frame)
  230. {
  231.     a[0][0] = 1 + (1 - y * 1.0 / max_y) * frame * 3.0 / max_frame;
  232. }
  233.  
  234. void shrink_left(double a[2][2], double b[2], int x, int y, int max_x, int max_y, int frame, int max_frame)
  235. {
  236.     a[1][1] = 1 - (1 - x * 1.0 / max_x) * frame * 0.67 / max_frame;
  237. }
  238.  
  239. void magnifying_glass(double a[2][2], double b[2], int x, int y, int max_x, int max_y, int frame, int max_frame)
  240. {
  241.     a[0][0] = 1;
  242.     a[1][1] = 1;
  243.  
  244.     b[0] = 0;
  245.     b[1] = 0;
  246.  
  247.     if ( (x - (15 + frame * 15.0 / max_frame )) * (x - (15 + frame * 15.0 / max_frame ))
  248.          + (y - (20 + frame * 15.0 / max_frame )) * (y - (20 + frame * 15.0 / max_frame )) < 225)
  249.     {
  250.         a[0][0] = 2;
  251.         a[1][1] = 2;
  252.  
  253.         b[0] =  (- 10 - frame * 35.0 / max_frame);
  254.         b[1] =  (- 10 - frame * 35.0 / max_frame);
  255.     }
  256. }
  257.  
  258. void Animate(const Bitmap & bmp, Callback transformation)
  259. {
  260.     const int max_frame = 60;
  261.     const int delay = 25;
  262.  
  263.     Bitmap animation[max_frame + 1];
  264.  
  265.     for (int i = 0; i <= max_frame; ++i)
  266.         animation[i] = Transform(bmp, transformation, i, max_frame);
  267.  
  268.     for (int i = 0; i <= max_frame; ++i)
  269.     {
  270.         Console::ClearBuffer();
  271.         Console::DrawOnBuffer(animation[i]);
  272.         Console::DisplayBuffer();
  273.  
  274.         Sleep(delay);
  275.     }
  276.  
  277.     for (int i = max_frame; i >=0; --i)
  278.     {
  279.         Console::ClearBuffer();
  280.         Console::DrawOnBuffer(animation[i]);
  281.         Console::DisplayBuffer();
  282.  
  283.         Sleep(delay);
  284.     }
  285. }
  286.  
  287. int main()
  288. {
  289.     srand(time(0));
  290.  
  291.     Console::Init();
  292.     Console::Resize(100, 100);
  293.  
  294.     ShowWindow(GetConsoleWindow(), SW_SHOWMAXIMIZED);
  295.  
  296.     Bitmap small_bmp = RandomBitmap(25, 25);
  297.     Bitmap   big_bmp = RandomBitmap(50, 50);
  298.  
  299.     Animate(small_bmp, shear);
  300.     Animate(small_bmp, grow_top);
  301.  
  302.     Animate(big_bmp, shrink_left);
  303.     Animate(big_bmp, magnifying_glass);
  304.  
  305.     Console::ClearBuffer();
  306.     Console::DrawOnBuffer(big_bmp);
  307.     Console::DisplayBuffer();
  308.  
  309.     Console::Destroy();
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement