/** For each pixel location in the new buffer P' (NewX, NewY), do: Find corresponding old location, P = W-1.P' Validate that this old location lie inside the original image boundary (i.e. 0 ≤ OldX < W, 0 ≤ Old Y < H). Otherwise, set the new empty pixel to 0 and continue to next location. If Validated, apply Bilinear Interpolation Algorithm to get the new pixel value, as follows:(Refer to above figure) */ public BufferedImage apply_transformation_matrix_to_bitmap_or_buffer(Matrix _transformations_matrix, BufferedImage _src_img, int _new_width, int _new_height, TextBox _console) { BufferedImage ret = new BufferedImage(_new_width, _new_height); BilinearInterpolation obj_bi_lin_interpol = new BilinearInterpolation(); for (int i = 0; i < _new_width; i++) { for (int j = 0; j < _new_height; j++) { PointF[] points = { new PointF(i, j) }; _transformations_matrix.TransformPoints(points); _console.Text += "P = (" + points[0].X + ", " + points[0].Y + ")"; _console.Text += Environment.NewLine; _console.Text += "P' = (" + i + ", " + j + ")"; _console.Text += Environment.NewLine; Color _color = Color.FromArgb(0); if(points[0].X >= 0 && points[0].X < _src_img.width && points[0].Y >= 0 && points[0].Y < _src_img.height) _color = obj_bi_lin_interpol.calculate(_src_img, points[0].X, points[0].Y); ret.buffer[i, j] = _color; } } return ret; }
public void run_test(TextBox _console) { Bitmap bmp = new Bitmap(Image.FromFile("C:/lenna.png")); BufferedImage obj_buff_img = new BufferedImage(bmp, _console); ImageMatrixTransformations obj_trans = new ImageMatrixTransformations(); BufferedImage ret = obj_trans.perform_concat_matrices_operations(obj_buff_img, _console); Bitmap new_bmp = ret.get_bitmap_object(); new_bmp.Save("new_lenna.png"); }
/** * find 4 adjacent pixels X1 = floor (OldX) ; X2 = X1 + 1 Y1 = floor (OldY) ; Y2 = Y1 + 1 P1 = OrigBuf[X1,Y1] ; P2 = OrigBuf[X2,Y1] P3 = OrigBuf[X1,Y2] ; P4 = OrigBuf[X2,Y2] Calculate X, Y fractions Xfraction = OldX – X1 Yfraction = OldY – Y1 Interpolate in X-Direction Z1 = P1 × (1 – Xfraction) + P2 × Xfraction Z2 = P3 × (1 – Xfraction) + P4 × Xfraction Interpolate in Y-Direction NewPixel = Z1 × (1 – Yfraction) + Z2 × Yfraction */ public Color calculate(BufferedImage _original_buffer, float _old_x, float _old_y) { int new_red, new_green, new_blue; Color ret; int x_1 = (int)Math.Floor(_old_x); int x_2 = x_1 + 1; int y_1 = (int)Math.Floor(_old_y); int y_2 = y_1 + 1; Color p_1 = _original_buffer.buffer[x_1, y_1]; Color p_2 = _original_buffer.buffer[x_2, y_2]; Color p_3 = _original_buffer.buffer[x_1, y_2]; Color p_4 = _original_buffer.buffer[x_2, y_2]; float x_fraction = _old_x - x_1; float y_fraction = _old_y - y_1; // Interpolate in X-Direction // Red int r_1 = (int)Math.Floor(p_1.R * (1 - x_fraction) + p_2.R * x_fraction); int r_2 = (int)Math.Floor(p_3.R * (1 - x_fraction) + p_4.R * x_fraction); // Green int g_1 = (int)Math.Floor(p_1.G * (1 - x_fraction) + p_2.G * x_fraction); int g_2 = (int)Math.Floor(p_3.G * (1 - x_fraction) + p_4.G * x_fraction); // Blue int b_1 = (int)Math.Floor(p_1.B * (1 - x_fraction) + p_2.B * x_fraction); int b_2 = (int)Math.Floor(p_3.B * (1 - x_fraction) + p_4.B * x_fraction); // Interpolate in Y-Direction new_red = (int)Math.Floor(r_1 * (1 - y_fraction) + r_2 * y_fraction); new_green = (int)Math.Floor(g_1 * (1 - y_fraction) + g_2 * y_fraction); new_blue = (int)Math.Floor(b_1 * (1 - y_fraction) + b_2 * y_fraction); ret = Color.FromArgb(new_red, new_green, new_blue); return ret; }
/** You can use this matrix as follows: 1 - Create new object with identity matrix (empty constructor) 2 - Apply a set of transformations that you want to this matrix 3 - Transform the four corners of the original image to calculate 4 - The min X and min Y of the transformed image 5 - The width & height of the new image buffer 6 - Translate this matrix by (- min X, - min Y) 7 - Invert the matrix 8 - Use the inverted version to reverse transform all new locations in the new image buffer **/ public BufferedImage perform_concat_matrices_operations(BufferedImage _src_img, TextBox _console, float _shear_x = (float)0, float _shear_y = (float)0, float _scale_x = (float)1, float _scale_y = (float)1, float _rotate_theta = (float)0) { BufferedImage ret; // 1 - Create new object with identity matrix (empty constructor) Matrix transformations_matrix = new Matrix(); // 2 - Apply a set of transformations that you want to this matrix transformations_matrix.Rotate(_rotate_theta); transformations_matrix.Scale(_scale_x, _scale_y); transformations_matrix.Shear(_shear_x, _shear_y); // 3 - Transform the four corners of the original image to calculate /** * To get the size of the new (destination) image, * apply the forward mapping to the four corners of the original image * ([0,0], [W-1,0], [0,H-1], [W-1,H-1]) * to get their new locations. * Then use these new four locations to get the width and height of the destination image * (e.g. to get new width: * find min X & max X of the four new points and subtract them, * do the same for Y to get the new height) */ Point[] corner_points = { new Point(0, 0), new Point(_src_img.width - 1, 0), new Point(0, _src_img.height - 1), new Point(_src_img.width - 1, _src_img.height - 1) }; transformations_matrix.TransformPoints(corner_points); int min_x = find_min_x(corner_points); int min_y = find_min_y(corner_points); int max_x = find_max_x(corner_points); int max_y = find_max_y(corner_points); int new_width = max_x - min_x; int new_height = max_y - min_y; _console.Text += "Min X = "; _console.Text += min_x; _console.Text += Environment.NewLine; _console.Text += "Min Y = "; _console.Text += min_y; _console.Text += Environment.NewLine; _console.Text += "Max X = "; _console.Text += max_x; _console.Text += Environment.NewLine; _console.Text += "Max Y = "; _console.Text += max_y; _console.Text += Environment.NewLine; _console.Text += "New Width = "; _console.Text += new_width; _console.Text += Environment.NewLine; _console.Text += "New Height = "; _console.Text += new_height; _console.Text += Environment.NewLine; // 4 - The min X and min Y of the transformed image /** * To make the transformed image totally fit inside the buffer, a translation with (- min X, - min Y) should be appended to the original transformation matrix (W) before inverting it. */ // 6 - Translate this matrix by (- min X, - min Y) transformations_matrix.Translate(-min_x, -min_y); // 7 - Invert the matrix transformations_matrix.Invert(); // 8 - Use the inverted version to reverse transform all new locations in the new image buffer ret = apply_transformation_matrix_to_bitmap_or_buffer(transformations_matrix, _src_img, new_width, new_height, _console); return ret; }