blob: 124dfcbde5ace1702cd08e5d6c9e3e73e607502b [file] [log] [blame]
import 'dart:math';
import '../image.dart';
import '../util/interpolation.dart';
/// Returns a copy of the [src] image, rotated by [angle] degrees.
Image copyRotate(Image src, num angle, {int interpolation = LINEAR}) {
num nangle = angle % 360.0;
// Optimized version for orthogonal angles.
if ((nangle % 90.0) == 0.0) {
int wm1 = src.width - 1;
int hm1 = src.height - 1;
int iangle = nangle ~/ 90.0;
switch (iangle) {
case 1: // 90 deg.
Image dst =
Image(src.height, src.width, src.format, src.exif, src.iccProfile);
for (int y = 0; y < dst.height; ++y) {
for (int x = 0; x < dst.width; ++x) {
dst.setPixel(x, y, src.getPixel(y, hm1 - x));
}
}
return dst;
case 2: // 180 deg.
Image dst =
Image(src.width, src.height, src.format, src.exif, src.iccProfile);
for (int y = 0; y < dst.height; ++y) {
for (int x = 0; x < dst.width; ++x) {
dst.setPixel(x, y, src.getPixel(wm1 - x, hm1 - y));
}
}
return dst;
case 3: // 270 deg.
Image dst =
Image(src.height, src.width, src.format, src.exif, src.iccProfile);
for (int y = 0; y < dst.height; ++y) {
for (int x = 0; x < dst.width; ++x) {
dst.setPixel(x, y, src.getPixel(wm1 - y, x));
}
}
return dst;
default: // 0 deg.
return new Image.from(src);
}
}
// Generic angle.
double rad = (nangle * pi / 180.0);
double ca = cos(rad);
double sa = sin(rad);
double ux = (src.width * ca).abs();
double uy = (src.width * sa).abs();
double vx = (src.height * sa).abs();
double vy = (src.height * ca).abs();
double w2 = 0.5 * src.width;
double h2 = 0.5 * src.height;
double dw2 = 0.5 * (ux + vx);
double dh2 = 0.5 * (uy + vy);
Image dst = Image((ux + vx).toInt(), (uy + vy).toInt(), Image.RGBA, src.exif,
src.iccProfile);
for (int y = 0; y < dst.height; ++y) {
for (int x = 0; x < dst.width; ++x) {
int c = src.getPixelInterpolate(w2 + (x - dw2) * ca + (y - dh2) * sa,
h2 - (x - dw2) * sa + (y - dh2) * ca, interpolation);
dst.setPixel(x, y, c);
}
}
return dst;
}