Вопрос по java – AffineTransform усекает изображение
У меня есть изображение, и я должен повернуть его на 45, 90, 135, 180 градусов. Что я делаю:
&l#;code&g#;#ry { BufferedImage src = ImageIO.read(new File("src.png")); double ang = Ma#h.#oRadians(90); AffineTransform # = new AffineTransform(); #.se#ToRo#a#ion(ang, src.ge#Wid#h() / 2, src.ge#Heigh#() / 2); AffineTransformOp op = new AffineTransformOp(#, null); BufferedImage ds# = new BufferedImage(src.ge#Wid#h(), src.ge#Heigh#(), src.ge#Type()); op.fil#er(src, ds#); ImageIO.wri#e(ds#, "png", new File("ou#pu#.png")); } ca#ch(Excep#ion ex) { ex.prin#S#ackTrace(); } &l#;/code&g#;
Проблема заключается в том, что изображение меняет свою позицию и выходит за пределы целевого изображения:
Проблема h##p://img32.imageshack.us/img32/3328/resul#cs.png
Я гуглил это и нашел решение в этом вопросе:AffineTransform обрезает изображение, что я не так делаю? Но я совершенно не понимаю этого, и он работает только для квадрантов. Я пытался умножить вдвое ширину и высоту пункта назначения, но это не удалось:
Еще один сбой h##p://img401.imageshack.us/img401/2417/resul#2a.png
Как это исправить? Изображение назначения не должно иметь каких-либо дополнительных (кроме необходимых для диагонального вращения) пробелов или усеченной области. Угловые проблемы (0 == 180 или по часовой стрелке) не важны.
Спасибо за любую помощь.
Edit: Now it works for the general case.
Вращение выполняется вокруг центра, и центр помещается в то же положение на целевом изображении, что и на исходном изображении (правильное поведение).
Я изменил ваш код для преобразования прямоугольника исходного изображения, чтобы мы могли легко получить новые размеры / смещение изображения. Это используется, чтобы построить пункт назначенияBufferedImage
правильных размеров, и добавить перевод к вашемуAffineTransform
таким образом, центр изображения располагается в центре целевого изображения.
BufferedImage src = ImageIO.read(new File(INPUT));
int w = src.getWidth();
int h = src.getHeight();
AffineTransform t = new AffineTransform();
double ang = Math.toRadians(35);
t.setToRotation(ang, w / 2d, h / 2d);
// source image rectangle
Point[] points = {
new Point(0, 0),
new Point(w, 0),
new Point(w, h),
new Point(0, h)
};
// transform to destination rectangle
t.transform(points, 0, points, 0, 4);
// get destination rectangle bounding box
Point min = new Point(points[0]);
Point max = new Point(points[0]);
for (int i = 1, n = points.length; i < n; i ++) {
Point p = points[i];
double pX = p.getX(), pY = p.getY();
// update min/max x
if (pX < min.getX()) min.setLocation(pX, min.getY());
if (pX > max.getX()) max.setLocation(pX, max.getY());
// update min/max y
if (pY < min.getY()) min.setLocation(min.getX(), pY);
if (pY > max.getY()) max.setLocation(max.getX(), pY);
}
// determine new width, height
w = (int) (max.getX() - min.getX());
h = (int) (max.getY() - min.getY());
// determine required translation
double tx = min.getX();
double ty = min.getY();
// append required translation
AffineTransform translation = new AffineTransform();
translation.translate(-tx, -ty);
t.preConcatenate(translation);
AffineTransformOp op = new AffineTransformOp(t, null);
BufferedImage dst = new BufferedImage(w, h, src.getType());
op.filter(src, dst);
ImageIO.write(dst, "png", new File(OUTPUT));
AffineTransformOp op = new AffineTransformOp(t, null);
с
AffineTransformOp op = new AffineTransformOp(t, AffineTransformOp.TYPE_BILINEAR);
Это значительно улучшит качество продукции.