简体   繁体   English

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

[英]How to rotate around the image center by itext?

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*/

How to rotate around the image center by itext? 如何通过itext围绕图像中心旋转?

If we have an Image image and coordinates x, y , we can draw the image without rotation with its lower left corner at the given coordinates like this 如果我们有一个Image image并且坐标为x, y ,则可以在不旋转的情况下绘制图像,其左下角位于给定坐标处,如下所示

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

A bitmap image from the resources has a size of 1x1 with the coordinate origin at its lower left. 资源中的位图图像的大小为1x1,坐标原点位于其左下角。 Thus, this operation stretches the image to its correct size and moves it so its lower left is at the given coordinates. 因此,此操作将图像拉伸到正确的大小并移动它,使其左下角位于给定的坐标处。

If we want to draw the same image as if the one drawn above was rotated around its center by an angle rotate , therefore, we can do this by moving the 1x1 image so that the origin is in its center, stretch it to its correct size, rotate it, and then move the origin (which still is at the center of the rotated image) to the center of the unrotated image. 如果我们要绘制相同的图像,就像上面绘制的图像围绕其中心rotate了一个角度rotate ,因此,我们可以通过移动1x1图像以使原点位于其中心来进行此操作,将其拉伸到正确的大小,旋转它,然后将原点(仍在旋转图像的中心)移动到未旋转图像的中心。 These operations are easier to express using AffineTransform instances (from package com.itextpdf.awt.geom ) instead number tupels. 使用AffineTransform实例(来自com.itextpdf.awt.geom包)而不是数字tupel,可以更轻松地表达这些操作。 Thus: 从而:

// 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 test method testAddRotatedImage ) AddRotatedImage.java测试方法testAddRotatedImage

For example drawing both images using 例如使用绘制两个图像

int x = 200;
int y = 300;
float rotate = (float) Math.PI / 3;

results in something like this: 结果是这样的:

屏幕截图

With a Flip 翻转

The OP asked in a comment OP在评论中要求

how to add rotate and flip image? 如何添加旋转和翻转图像?

For this you simply insert a mirroring affine transformation into the sequence of transformations above. 为此,您只需在上面的转换序列中插入一个仿射仿射转换。

Unfortunately the OP did not mention which he meant a horizontal or a vertical flip. 不幸的是,OP没有提到他的意思是水平翻转或垂直翻转。 But as changing the rotation angle accordingly transforms one in the other, that isn't really necessary, either. 但是,随着改变旋转角度相应地彼此转换,这也不是必须的。

// 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 test method testAddRotatedFlippedImage ) AddRotatedImage.java测试方法testAddRotatedFlippedImage

The result with the same image as above: 与上图相同的结果:

屏幕截图

With Interpolation 带插值

The OP asked in a yet another comment OP在另一个评论中询问

How anti aliasing ? 如何抗锯齿?

The iText Image class knows an Interpolation property. iText Image类知道Interpolation属性。 By setting it to true ( before adding the image to the document, obviously), 通过将其设置为true(显然, 将图像添加到文档之前 ),

image.setInterpolation(true);

low resolution images are subject to interpolation when drawn. 低分辨率图像在绘制时会进行插值。

Eg using a 2x2 image with differently colored pixels instead of the image of Willi, you get the following results, first without interpolation, then with interpolation: 例如,使用具有不同颜色像素的2x2图像而不是Willi图像,您将获得以下结果,首先不进行插值,然后进行插值:

rotationInterpolatedImage.pdf截图

Confer the AddRotatedImage.java test testAddRotatedInterpolatedImage which adds this image: 授予AddRotatedImage.java测试testAddRotatedInterpolatedImage来添加此图像:

Beware: iText Image property Interpolation effectively sets the Interpolate entry in the PDF image dictionary. 当心: iText Image属性Interpolation有效地设置了PDF图像字典中的Interpolate项。 The PDF specification notes in this context: PDF规范在这种情况下说明:

NOTE A conforming Reader may choose to not implement this feature of PDF, or may use any specific implementation of interpolation that it wishes. 注意合格的读者可以选择不实现PDF的此功能,或者可以使用希望的插值的任何特定实现。

Thus, on some viewers interpolation may occur differently than in your viewer, maybe even not at all. 因此,在某些查看器上,插值可能与您的查看器中的插值不同,甚至根本没有。 If you need a specific kind of interpolation on every viewer, upscale the image with the desired amount of interpolation / anti-aliasing before loading it into an iText Image . 如果您需要在每个查看器上使用特定种类的插值,请在将图像加载到iText Image之前,以所需的插值/抗锯齿量对图像进行放大。

    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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM