如何通过itext在图像中心周围旋转?

时间:2016-09-07 07:52:52

标签: java image rotation itext center

double degPi = degrees * Math.PI / 180;   
double a = Math.cos(degPi)*tImgCover.getScaledHeight();
double b = Math.sin(degPi)*tImgCover.getScaledWidth();
double c = -Math.sin(degPi) * tImgCover.getScaledHeight();
double d = Math.cos(degPi)* tImgCover.getScaledWidth();
double e = absX;
double f = absY;

contentByte.addImage(imgae, a, b, c, d, e, f);/*add image*/

如何通过itext在图像中心周围旋转?

2 个答案:

答案 0 :(得分:2)

如果我们有一个Image image并且坐标x, y,我们可以在不给定旋转的情况下绘制图像,其左下角位于给定坐标处,如下所示

contentByte.addImage(image, image.getWidth(), 0, 0, image.getHeight(), x, y);

来自资源的位图图像的大小为1x1,坐标原点位于其左下方。因此,此操作将图像拉伸到正确的大小并移动它,使其左下角位于给定的坐标处。

如果我们想绘制相同的图像,就好像上面绘制的图像围绕其中心旋转一个角度rotate,因此,我们可以通过移动1x1图像使原点位于其中心来实现,将其拉伸到正确的大小,旋转它,然后将原点(仍然位于旋转图像的中心)移动到未旋转图像的中心。使用AffineTransform实例(来自包com.itextpdf.awt.geom)而不是数字tupels更容易表达这些操作。因此:

// Draw image as if the previous image was rotated around its center
// Image starts out being 1x1 with origin in lower left
// Move origin to center of image
AffineTransform A = AffineTransform.getTranslateInstance(-0.5, -0.5);
// Stretch it to its dimensions
AffineTransform B = AffineTransform.getScaleInstance(image.getWidth(), image.getHeight());
// Rotate it
AffineTransform C = AffineTransform.getRotateInstance(rotate);
// Move it to have the same center as above
AffineTransform D = AffineTransform.getTranslateInstance(x + image.getWidth()/2, y + image.getHeight()/2);
// Concatenate
AffineTransform M = (AffineTransform) A.clone();
M.preConcatenate(B);
M.preConcatenate(C);
M.preConcatenate(D);
//Draw
contentByte.addImage(image, M);

AddRotatedImage.java测试方法testAddRotatedImage

例如,使用

绘制两个图像
int x = 200;
int y = 300;
float rotate = (float) Math.PI / 3;

结果如下:

Screenshot

使用翻转

OP在评论中提到

  

如何添加旋转和翻转图像?

为此,您只需在上面的转换序列中插入镜像仿射变换。

不幸的是OP没有提到他的意思是水平或垂直翻转。但是,因为改变旋转角度会相应地转换为另一个,这也不是必需的。

// Draw image as if the previous image was flipped and rotated around its center
// Image starts out being 1x1 with origin in lower left
// Move origin to center of image
AffineTransform A = AffineTransform.getTranslateInstance(-0.5, -0.5);
// Flip it horizontally
AffineTransform B = new AffineTransform(-1, 0, 0, 1, 0, 0);
// Stretch it to its dimensions
AffineTransform C = AffineTransform.getScaleInstance(image.getWidth(), image.getHeight());
// Rotate it
AffineTransform D = AffineTransform.getRotateInstance(rotate);
// Move it to have the same center as above
AffineTransform E = AffineTransform.getTranslateInstance(x + image.getWidth()/2, y + image.getHeight()/2);
// Concatenate
AffineTransform M = (AffineTransform) A.clone();
M.preConcatenate(B);
M.preConcatenate(C);
M.preConcatenate(D);
M.preConcatenate(E);
//Draw
contentByte.addImage(image, M);

AddRotatedImage.java测试方法testAddRotatedFlippedImage

与上图相同的结果:

Screenshot

使用插值

OP又在另一条评论中提出了

  

如何抗锯齿?

iText Image类知道Interpolation属性。通过将其设置为true(之前将图像添加到文档中,显然),

image.setInterpolation(true);

低分辨率图像在绘制时会进行插值。

E.g。使用具有不同颜色像素的2x2图像而不是Willi图像,您将获得以下结果,首先不使用插值,然后使用插值:

rotatedInterpolatedImage.pdf screenshot

授予添加此图片的AddRotatedImage.java测试testAddRotatedInterpolatedImage

注意: iText Image属性Interpolation有效地设置了PDF图片字典中的插值条目。 PDF规范在此上下文中注明:

  

注意符合本标准的阅读器可能选择不实现PDF的此功能,或者可以使用其希望的任何特定插值实现。

因此,在某些观看者中,插值可能与您的观看者不同,甚至可能根本不同。如果您需要在每个查看器上进行特定类型的插值,请在将图像加载到iText Image之前使用所需的插值/消除锯齿量对图像进行放大。

答案 1 :(得分:1)

    public static BufferedImage rotateClockwise90( BufferedImage inputImage ){
        int width = inputImage.getWidth();
        int height = inputImage.getHeight();
        BufferedImage returnImage = new BufferedImage( height, width , inputImage.getType()  );

        for( int x = 0; x < width; x++ ) {
            for( int y = 0; y < height; y++ ) {
                returnImage.setRGB( height-y-1, x, inputImage.getRGB( x, y  )  );

            }
        }
        return returnImage;
}