/// <summary> /// Изменение позиции, размера и поворот изображения, с биллинейной интерполяцией /// </summary> public void BilinearInterpolationTransform(int Width, int Height, int offsetX, int offsetY, int angle) { Scale(Width, Height, angle); byte[] TransformBuffer = new byte[w * h * Channels]; int X, Y, X2, Y2; RGB A = new RGB(); RGB B = new RGB(); RGB C = new RGB(); RGB D = new RGB(); byte r, g, b; double W, H; int pointX = Width / 2; int pointY = Height / 2; int currentOffsetX = offsetY + (previousWidth - Width) / 2 - (previousWidth - w) / 2; int currentOffsetY = offsetX - (previousHeight - Height) / 2 + (previousHeight - h) / 2; double x_ratio = (double)(previousWidth - 1) / Width; double y_ratio = (double)(previousHeight - 1) / Height; someDoubleValue = Math.PI / 180 * angle; cos = Math.Cos(someDoubleValue); sin = Math.Sin(someDoubleValue); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { X = (int)(cos * (j - currentOffsetX - pointX) - sin * (i + currentOffsetY - pointY) + pointX); Y = (int)(sin * (j - currentOffsetX - pointX) + cos * (i + currentOffsetY - pointY) + pointY); X2 = (int)(X * x_ratio); Y2 = (int)(Y * y_ratio); W = x_ratio * X - X2; H = y_ratio * Y - Y2; someIntValue = i * (w * Channels) + j * 4; someIntValue2 = Y2 * Stride + X2 * 4; if (someIntValue2 >= 0 && someIntValue2 < PixelsCountWithChannels) { A.B = PixelsBuffer[someIntValue2]; A.G = PixelsBuffer[someIntValue2 + 1]; A.R = PixelsBuffer[someIntValue2 + 2]; } someIntValue3 = Y2 * Stride + (X2 + 1) * 4; if (someIntValue3 >= 0 && someIntValue3 < PixelsCountWithChannels) { B.B = PixelsBuffer[someIntValue3]; B.G = PixelsBuffer[someIntValue3 + 1]; B.R = PixelsBuffer[someIntValue3 + 2]; } someIntValue3 = (Y2 + 1) * Stride + X2 * 4; if (someIntValue3 >= 0 && someIntValue3 < PixelsCountWithChannels) { C.B = PixelsBuffer[someIntValue3]; C.G = PixelsBuffer[someIntValue3 + 1]; C.R = PixelsBuffer[someIntValue3 + 2]; } someIntValue3 = (Y2 + 1) * Stride + (X2 + 1) * 4; if (someIntValue3 >= 0 && someIntValue3 < PixelsCountWithChannels) { D.B = PixelsBuffer[someIntValue3]; D.G = PixelsBuffer[someIntValue3 + 1]; D.R = PixelsBuffer[someIntValue3 + 2]; } r = (byte)(A.R * (1 - W) * (1 - H) + B.R * (W) * (1 - H) + C.R * (H) * (1 - W) + D.R * (W * H)); g = (byte)(A.G * (1 - W) * (1 - H) + B.G * (W) * (1 - H) + C.G * (H) * (1 - W) + D.G * (W * H)); b = (byte)(A.B * (1 - W) * (1 - H) + B.B * (W) * (1 - H) + C.B * (H) * (1 - W) + D.B * (W * H)); if (someIntValue >= 0 && someIntValue < TransformBuffer.Length && someIntValue2 >= 0 && someIntValue2 < PixelsCountWithChannels) { if (X2 >= 0 && X2 < previousWidth) { TransformBuffer[someIntValue] = b; TransformBuffer[someIntValue + 1] = g; TransformBuffer[someIntValue + 2] = r; TransformBuffer[someIntValue + 3] = 255; } else { TransformBuffer[someIntValue + 3] = 0; } } } } picture.TransformBuffer = TransformBuffer; picture.Width = Math.Abs(w); picture.Height = Math.Abs(h); }
/// <summary> /// Изменение позиции, размера и поворот изображения, с линейной интерполяцией /// </summary> public void LinearInterpolationTransform(int Width, int Height, int offsetX, int offsetY, int angle) { Scale(Width, Height, angle); byte[] TransformBuffer = new byte[w * h * Channels]; int X, Y, X2, Y2; RGB A = new RGB(); RGB B = new RGB(); byte r, g, b; int pointX = Width / 2; int pointY = Height / 2; int currentOffsetX = offsetY + (previousWidth - Width) / 2 - (previousWidth - w) / 2; int currentOffsetY = offsetX - (previousHeight - Height) / 2 + (previousHeight - h) / 2; int x_ratio = (previousWidth << 16) / Width + 1; int y_ratio = (previousHeight << 16) / Height + 1; someDoubleValue = Math.PI / 180 * angle; cos = Math.Cos(someDoubleValue); sin = Math.Sin(someDoubleValue); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { X = (int)(cos * (j - currentOffsetX - pointX) - sin * (i + currentOffsetY - pointY) + pointX); Y = (int)(sin * (j - currentOffsetX - pointX) + cos * (i + currentOffsetY - pointY) + pointY); X2 = (X * x_ratio) >> 16; Y2 = (Y * y_ratio) >> 16; someIntValue = i * (w * Channels) + j * 4; someIntValue2 = Y2 * Stride + X2 * 4; if (someIntValue2 >= 0 && someIntValue2 < PixelsCountWithChannels) { A.B = PixelsBuffer[someIntValue2]; A.G = PixelsBuffer[someIntValue2 + 1]; A.R = PixelsBuffer[someIntValue2 + 2]; } someIntValue3 = Y2 * Stride + (X2 + 1) * 4; if (someIntValue3 >= 0 && someIntValue3 < PixelsCountWithChannels) { B.B = PixelsBuffer[someIntValue3]; B.G = PixelsBuffer[someIntValue3 + 1]; B.R = PixelsBuffer[someIntValue3 + 2]; } r = A.R + (previousWidth * (B.R - A.R) / Width) < 0 ? r = 0 : A.R + (previousWidth * (B.R - A.R) / Width) > 255 ? r = 255 : r = (byte)(A.R + (previousWidth * (B.R - A.R) / Width)); g = A.G + (previousWidth * (B.G - A.G) / Width) < 0 ? g = 0 : A.G + (previousWidth * (B.G - A.G) / Width) > 255 ? g = 255 : g = (byte)(A.G + (previousWidth * (B.G - A.G) / Width)); b = A.B + (previousWidth * (B.B - A.B) / Width) < 0 ? b = 0 : A.R + (previousWidth * (B.B - A.B) / Width) > 255 ? b = 255 : b = (byte)(A.B + (previousWidth * (B.B - A.B) / Width)); if (someIntValue >= 0 && someIntValue < TransformBuffer.Length && someIntValue2 >= 0 && someIntValue2 < PixelsCountWithChannels) { if (X2 >= 0 && X2 < previousWidth) { TransformBuffer[someIntValue] = b; TransformBuffer[someIntValue + 1] = g; TransformBuffer[someIntValue + 2] = r; TransformBuffer[someIntValue + 3] = 255; } else { TransformBuffer[someIntValue + 3] = 0; } } } } picture.TransformBuffer = TransformBuffer; picture.Width = Math.Abs(w); picture.Height = Math.Abs(h); }