Reputation: 524
in itext 7.1, I am adding an image to a pdf document with following code :
Document document = new Document(writerPdf); //make a new document object
ImageData imgData = ImageDataFactory.create(imageBytes);
Image image = new Image(imgData);
document.add(image);
This works fine for most images but I have come across an image that seems normal on desktop but when adding to pdf it is rotated by -90 .
imgData.getRotation() gives 0 as output
My question is :
how to check if image has any rotation set.
imgData.setRotation(90) does not seem to work for me. How to rotate . Thanks.
Upvotes: 1
Views: 2756
Reputation: 31
Before you add image, you should check image with uri of image. This function will auto rotate the image for you:
public static boolean rotatedImage(Uri uri) throws IOException {
InputStream input = MyApplication.getContext().getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither = true; // optional
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; // optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
return false;
}
int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
double ratio = (originalSize > THUMBNAIL_SIZE) ? (originalSize / (double) THUMBNAIL_SIZE) : 1.0;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
bitmapOptions.inDither = true; // optional
bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
input = MyApplication.getContext().getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
// Rotate the bitmap if the image is in landscape orientation
ExifInterface exif = null;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
exif = new ExifInterface(MyApplication.getContext().getContentResolver().openInputStream(uri));
} else {
exif = new ExifInterface(uri.getPath());
}
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotationDegrees = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotationDegrees = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotationDegrees = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotationDegrees = 270;
break;
}
if (rotationDegrees != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotationDegrees);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (rotatedBitmap != null && !rotatedBitmap.equals(bitmap)) {
bitmap.recycle(); // Release the original bitmap
bitmap = rotatedBitmap; // Set the rotated bitmap as the new bitmap
}
}
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(uri.getPath())));
return true;
}
Upvotes: 0
Reputation: 96074
iText 7 unfortunately in general does not read (or at least not provide) that information, the Rotation
property of ImageData
currently is only extracted for TIFF files.
If the image has EXIF metadata and the orientation is properly contained in them, though, you can try and read those metadata using an appropriate library and use that orientation for inserting the image using iText.
One such library is Drew Noakes's metadata-extractor, cf. e.g. his answer here. It can be retrieved via maven using
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.11.0</version>
</dependency>
With that dependency available, you can go ahead and try:
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageBytes));
ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
double angle = 0;
switch (orientation)
{
case 1:
case 2:
angle = 0; break;
case 3:
case 4:
angle = Math.PI; break;
case 5:
case 6:
angle = - Math.PI / 2; break;
case 7:
case 8:
angle = Math.PI / 2; break;
}
Document document = new Document(writerPdf);
ImageData imgData = ImageDataFactory.create(imageBytes);
Image image = new Image(imgData);
image.setRotationAngle(angle);
document.add(image);
(from the RecognizeRotatedImage test testOskar
)
(For values 2, 4, 5, and 7 one actually also needs to flip the image; for more backgrounds look e.g. here.)
To be safe, consider wrapping the EXIF related code parts in an appropriate try-catch
envelope.
Upvotes: 2
Reputation: 524
for anyone else facing this issue , this is response from iText team You will have to write your own logic for this. iText has no way of detecting whether or not your image has been rotated. If your working with portrait images for example, you could create a method that compares the width of the image to its height and rotates it accordingly. However this is out of scope for iText.
Upvotes: 2